AnalysisDeclContext.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- AnalysisDeclContext.h - Context for path sensitivity -----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. /// \file
  15. /// This file defines AnalysisDeclContext, a class that manages the analysis
  16. /// context data for context sensitive and path sensitive analysis.
  17. /// It also defines the helper classes to model entering, leaving or inlining
  18. /// function calls.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
  22. #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
  23. #include "clang/AST/DeclBase.h"
  24. #include "clang/Analysis/BodyFarm.h"
  25. #include "clang/Analysis/CFG.h"
  26. #include "clang/Analysis/CodeInjector.h"
  27. #include "clang/Basic/LLVM.h"
  28. #include "llvm/ADT/DenseMap.h"
  29. #include "llvm/ADT/FoldingSet.h"
  30. #include "llvm/ADT/StringRef.h"
  31. #include "llvm/ADT/iterator_range.h"
  32. #include "llvm/Support/Allocator.h"
  33. #include <functional>
  34. #include <memory>
  35. namespace clang {
  36. class AnalysisDeclContextManager;
  37. class ASTContext;
  38. class BlockDecl;
  39. class BlockInvocationContext;
  40. class CFGReverseBlockReachabilityAnalysis;
  41. class CFGStmtMap;
  42. class ImplicitParamDecl;
  43. class LocationContext;
  44. class LocationContextManager;
  45. class ParentMap;
  46. class StackFrameContext;
  47. class Stmt;
  48. class VarDecl;
  49. /// The base class of a hierarchy of objects representing analyses tied
  50. /// to AnalysisDeclContext.
  51. class ManagedAnalysis {
  52. protected:
  53. ManagedAnalysis() = default;
  54. public:
  55. virtual ~ManagedAnalysis();
  56. // Subclasses need to implement:
  57. //
  58. // static const void *getTag();
  59. //
  60. // Which returns a fixed pointer address to distinguish classes of
  61. // analysis objects. They also need to implement:
  62. //
  63. // static [Derived*] create(AnalysisDeclContext &Ctx);
  64. //
  65. // which creates the analysis object given an AnalysisDeclContext.
  66. };
  67. /// AnalysisDeclContext contains the context data for the function, method
  68. /// or block under analysis.
  69. class AnalysisDeclContext {
  70. // Backpoint to the AnalysisManager object that created this
  71. // AnalysisDeclContext. This may be null.
  72. AnalysisDeclContextManager *ADCMgr;
  73. const Decl *const D;
  74. std::unique_ptr<CFG> cfg, completeCFG;
  75. std::unique_ptr<CFGStmtMap> cfgStmtMap;
  76. CFG::BuildOptions cfgBuildOptions;
  77. CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
  78. bool builtCFG = false;
  79. bool builtCompleteCFG = false;
  80. std::unique_ptr<ParentMap> PM;
  81. std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
  82. llvm::BumpPtrAllocator A;
  83. llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr;
  84. void *ManagedAnalyses = nullptr;
  85. public:
  86. AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D);
  87. AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D,
  88. const CFG::BuildOptions &BuildOptions);
  89. ~AnalysisDeclContext();
  90. ASTContext &getASTContext() const { return D->getASTContext(); }
  91. const Decl *getDecl() const { return D; }
  92. AnalysisDeclContextManager *getManager() const { return ADCMgr; }
  93. CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
  94. const CFG::BuildOptions &getCFGBuildOptions() const {
  95. return cfgBuildOptions;
  96. }
  97. /// \returns Whether we are adding exception handling edges from CallExprs.
  98. /// If this is false, then try/catch statements and blocks reachable from them
  99. /// can appear to be dead in the CFG, analysis passes must cope with that.
  100. bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
  101. bool getUseUnoptimizedCFG() const {
  102. return !cfgBuildOptions.PruneTriviallyFalseEdges;
  103. }
  104. bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
  105. bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
  106. void registerForcedBlockExpression(const Stmt *stmt);
  107. const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
  108. /// \returns The body of the stored Decl \c D.
  109. Stmt *getBody() const;
  110. /// \copydoc AnalysisDeclContext::getBody()
  111. /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
  112. /// by the BodyFarm.
  113. Stmt *getBody(bool &IsAutosynthesized) const;
  114. /// \returns Whether the body of the Decl \c D is generated by the BodyFarm.
  115. ///
  116. /// \note The lookup is not free. We are going to call getBody behind
  117. /// the scenes.
  118. /// \sa getBody
  119. bool isBodyAutosynthesized() const;
  120. /// \returns Whether the body of the Decl \c D is generated by the BodyFarm
  121. /// from a model file.
  122. ///
  123. /// \note The lookup is not free. We are going to call getBody behind
  124. /// the scenes.
  125. /// \sa getBody
  126. bool isBodyAutosynthesizedFromModelFile() const;
  127. CFG *getCFG();
  128. CFGStmtMap *getCFGStmtMap();
  129. CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
  130. /// \returns A version of the CFG without any edges pruned.
  131. CFG *getUnoptimizedCFG();
  132. void dumpCFG(bool ShowColors);
  133. /// \returns Whether we have built a CFG for this analysis context.
  134. ///
  135. /// \note This doesn't correspond to whether or not a valid CFG exists, it
  136. /// corresponds to whether we *attempted* to build one.
  137. bool isCFGBuilt() const { return builtCFG; }
  138. ParentMap &getParentMap();
  139. using referenced_decls_iterator = const VarDecl *const *;
  140. llvm::iterator_range<referenced_decls_iterator>
  141. getReferencedBlockVars(const BlockDecl *BD);
  142. /// \returns The ImplicitParamDecl associated with \c self if this
  143. /// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise.
  144. const ImplicitParamDecl *getSelfDecl() const;
  145. /// \copydoc LocationContextManager::getStackFrame()
  146. const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
  147. const Stmt *S, const CFGBlock *Blk,
  148. unsigned BlockCount, unsigned Index);
  149. /// \copydoc LocationContextManager::getBlockInvocationContext()
  150. const BlockInvocationContext *
  151. getBlockInvocationContext(const LocationContext *ParentLC,
  152. const BlockDecl *BD, const void *Data);
  153. /// \returns The specified analysis object, lazily running the analysis if
  154. /// necessary or nullptr if the analysis could not run.
  155. template <typename T> T *getAnalysis() {
  156. const void *tag = T::getTag();
  157. std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag);
  158. if (!data)
  159. data = T::create(*this);
  160. return static_cast<T *>(data.get());
  161. }
  162. /// \returns Whether the root namespace of \p D is the \c std C++ namespace.
  163. static bool isInStdNamespace(const Decl *D);
  164. static std::string getFunctionName(const Decl *D);
  165. private:
  166. std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
  167. LocationContextManager &getLocationContextManager();
  168. };
  169. /// It wraps the AnalysisDeclContext to represent both the call stack with
  170. /// the help of StackFrameContext and inside the function calls the
  171. /// BlockInvocationContext. It is needed for context sensitive analysis to
  172. /// model entering, leaving or inlining function calls.
  173. class LocationContext : public llvm::FoldingSetNode {
  174. public:
  175. enum ContextKind { StackFrame, Block };
  176. private:
  177. ContextKind Kind;
  178. // AnalysisDeclContext can't be const since some methods may modify its
  179. // member.
  180. AnalysisDeclContext *Ctx;
  181. const LocationContext *Parent;
  182. int64_t ID;
  183. protected:
  184. LocationContext(ContextKind k, AnalysisDeclContext *ctx,
  185. const LocationContext *parent, int64_t ID)
  186. : Kind(k), Ctx(ctx), Parent(parent), ID(ID) {}
  187. public:
  188. virtual ~LocationContext();
  189. ContextKind getKind() const { return Kind; }
  190. int64_t getID() const { return ID; }
  191. AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
  192. const LocationContext *getParent() const { return Parent; }
  193. bool isParentOf(const LocationContext *LC) const;
  194. const Decl *getDecl() const { return Ctx->getDecl(); }
  195. CFG *getCFG() const { return Ctx->getCFG(); }
  196. template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
  197. const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
  198. /// \copydoc AnalysisDeclContext::getSelfDecl()
  199. const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
  200. const StackFrameContext *getStackFrame() const;
  201. /// \returns Whether the current LocationContext has no caller context.
  202. virtual bool inTopFrame() const;
  203. virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
  204. /// Prints out the call stack.
  205. ///
  206. /// \param Out The out stream.
  207. LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
  208. /// Prints out the call stack in \c json format.
  209. ///
  210. /// \param Out The out stream.
  211. /// \param NL The newline.
  212. /// \param Space The space count for indentation.
  213. /// \param IsDot Whether the output format is \c dot.
  214. /// \param printMoreInfoPerContext
  215. /// A callback to print more information for each context, for example:
  216. /// \code
  217. /// [&](const LocationContext *LC) { LC->dump(); }
  218. /// \endcode
  219. void printJson(
  220. raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
  221. bool IsDot = false,
  222. std::function<void(const LocationContext *)> printMoreInfoPerContext =
  223. [](const LocationContext *) {}) const;
  224. LLVM_DUMP_METHOD void dump() const;
  225. static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
  226. AnalysisDeclContext *ctx,
  227. const LocationContext *parent, const void *data);
  228. };
  229. /// It represents a stack frame of the call stack (based on CallEvent).
  230. class StackFrameContext : public LocationContext {
  231. friend class LocationContextManager;
  232. // The call site where this stack frame is established.
  233. const Stmt *CallSite;
  234. // The parent block of the call site.
  235. const CFGBlock *Block;
  236. // The number of times the 'Block' has been visited.
  237. // It allows discriminating between stack frames of the same call that is
  238. // called multiple times in a loop.
  239. const unsigned BlockCount;
  240. // The index of the call site in the CFGBlock.
  241. const unsigned Index;
  242. StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
  243. const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
  244. unsigned Index, int64_t ID)
  245. : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
  246. Block(Block), BlockCount(BlockCount), Index(Index) {}
  247. public:
  248. ~StackFrameContext() override = default;
  249. const Stmt *getCallSite() const { return CallSite; }
  250. const CFGBlock *getCallSiteBlock() const { return Block; }
  251. bool inTopFrame() const override { return getParent() == nullptr; }
  252. unsigned getIndex() const { return Index; }
  253. CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
  254. void Profile(llvm::FoldingSetNodeID &ID) override;
  255. static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
  256. const LocationContext *ParentLC, const Stmt *S,
  257. const CFGBlock *Block, unsigned BlockCount,
  258. unsigned Index) {
  259. ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
  260. ID.AddPointer(Block);
  261. ID.AddInteger(BlockCount);
  262. ID.AddInteger(Index);
  263. }
  264. static bool classof(const LocationContext *LC) {
  265. return LC->getKind() == StackFrame;
  266. }
  267. };
  268. /// It represents a block invocation (based on BlockCall).
  269. class BlockInvocationContext : public LocationContext {
  270. friend class LocationContextManager;
  271. const BlockDecl *BD;
  272. // FIXME: Come up with a more type-safe way to model context-sensitivity.
  273. const void *Data;
  274. BlockInvocationContext(AnalysisDeclContext *ADC,
  275. const LocationContext *ParentLC, const BlockDecl *BD,
  276. const void *Data, int64_t ID)
  277. : LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {}
  278. public:
  279. ~BlockInvocationContext() override = default;
  280. const BlockDecl *getBlockDecl() const { return BD; }
  281. const void *getData() const { return Data; }
  282. void Profile(llvm::FoldingSetNodeID &ID) override;
  283. static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
  284. const LocationContext *ParentLC, const BlockDecl *BD,
  285. const void *Data) {
  286. ProfileCommon(ID, Block, ADC, ParentLC, BD);
  287. ID.AddPointer(Data);
  288. }
  289. static bool classof(const LocationContext *LC) {
  290. return LC->getKind() == Block;
  291. }
  292. };
  293. class LocationContextManager {
  294. llvm::FoldingSet<LocationContext> Contexts;
  295. // ID used for generating a new location context.
  296. int64_t NewID = 0;
  297. public:
  298. ~LocationContextManager();
  299. /// Obtain a context of the call stack using its parent context.
  300. ///
  301. /// \param ADC The AnalysisDeclContext.
  302. /// \param ParentLC The parent context of this newly created context.
  303. /// \param S The call.
  304. /// \param Block The basic block.
  305. /// \param BlockCount The current count of entering into \p Blk.
  306. /// \param Index The index of \p Blk.
  307. /// \returns The context for \p D with parent context \p ParentLC.
  308. const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
  309. const LocationContext *ParentLC,
  310. const Stmt *S, const CFGBlock *Block,
  311. unsigned BlockCount, unsigned Index);
  312. /// Obtain a context of the block invocation using its parent context.
  313. ///
  314. /// \param ADC The AnalysisDeclContext.
  315. /// \param ParentLC The parent context of this newly created context.
  316. /// \param BD The BlockDecl.
  317. /// \param Data The raw data to store as part of the context.
  318. const BlockInvocationContext *
  319. getBlockInvocationContext(AnalysisDeclContext *ADC,
  320. const LocationContext *ParentLC,
  321. const BlockDecl *BD, const void *Data);
  322. /// Discard all previously created LocationContext objects.
  323. void clear();
  324. };
  325. class AnalysisDeclContextManager {
  326. using ContextMap =
  327. llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
  328. ContextMap Contexts;
  329. LocationContextManager LocCtxMgr;
  330. CFG::BuildOptions cfgBuildOptions;
  331. // Pointer to an interface that can provide function bodies for
  332. // declarations from external source.
  333. std::unique_ptr<CodeInjector> Injector;
  334. // A factory for creating and caching implementations for common
  335. // methods during the analysis.
  336. BodyFarm FunctionBodyFarm;
  337. // Flag to indicate whether or not bodies should be synthesized
  338. // for well-known functions.
  339. bool SynthesizeBodies;
  340. public:
  341. AnalysisDeclContextManager(
  342. ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
  343. bool addImplicitDtors = false, bool addInitializers = false,
  344. bool addTemporaryDtors = false, bool addLifetime = false,
  345. bool addLoopExit = false, bool addScopes = false,
  346. bool synthesizeBodies = false, bool addStaticInitBranches = false,
  347. bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
  348. bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
  349. CodeInjector *injector = nullptr);
  350. AnalysisDeclContext *getContext(const Decl *D);
  351. bool getUseUnoptimizedCFG() const {
  352. return !cfgBuildOptions.PruneTriviallyFalseEdges;
  353. }
  354. CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
  355. /// \returns Whether faux bodies should be synthesized for known functions.
  356. bool synthesizeBodies() const { return SynthesizeBodies; }
  357. /// Obtain the beginning context of the analysis.
  358. ///
  359. /// \returns The top level stack frame for \p D.
  360. const StackFrameContext *getStackFrame(const Decl *D) {
  361. return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0,
  362. 0);
  363. }
  364. /// \copydoc LocationContextManager::getStackFrame()
  365. const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
  366. const LocationContext *Parent,
  367. const Stmt *S, const CFGBlock *Block,
  368. unsigned BlockCount, unsigned Index) {
  369. return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
  370. }
  371. BodyFarm &getBodyFarm();
  372. /// Discard all previously created AnalysisDeclContexts.
  373. void clear();
  374. private:
  375. friend class AnalysisDeclContext;
  376. LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
  377. };
  378. } // namespace clang
  379. #endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
  380. #ifdef __GNUC__
  381. #pragma GCC diagnostic pop
  382. #endif