AnalysisDeclContext.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. assert(ctx);
  188. }
  189. public:
  190. virtual ~LocationContext();
  191. ContextKind getKind() const { return Kind; }
  192. int64_t getID() const { return ID; }
  193. LLVM_ATTRIBUTE_RETURNS_NONNULL
  194. AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
  195. /// It might return null.
  196. const LocationContext *getParent() const { return Parent; }
  197. bool isParentOf(const LocationContext *LC) const;
  198. const Decl *getDecl() const { return Ctx->getDecl(); }
  199. CFG *getCFG() const { return Ctx->getCFG(); }
  200. template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
  201. const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
  202. /// \copydoc AnalysisDeclContext::getSelfDecl()
  203. const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
  204. const StackFrameContext *getStackFrame() const;
  205. /// \returns Whether the current LocationContext has no caller context.
  206. virtual bool inTopFrame() const;
  207. virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
  208. /// Prints out the call stack.
  209. ///
  210. /// \param Out The out stream.
  211. LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
  212. /// Prints out the call stack in \c json format.
  213. ///
  214. /// \param Out The out stream.
  215. /// \param NL The newline.
  216. /// \param Space The space count for indentation.
  217. /// \param IsDot Whether the output format is \c dot.
  218. /// \param printMoreInfoPerContext
  219. /// A callback to print more information for each context, for example:
  220. /// \code
  221. /// [&](const LocationContext *LC) { LC->dump(); }
  222. /// \endcode
  223. void printJson(
  224. raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
  225. bool IsDot = false,
  226. std::function<void(const LocationContext *)> printMoreInfoPerContext =
  227. [](const LocationContext *) {}) const;
  228. LLVM_DUMP_METHOD void dump() const;
  229. static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
  230. AnalysisDeclContext *ctx,
  231. const LocationContext *parent, const void *data);
  232. };
  233. /// It represents a stack frame of the call stack (based on CallEvent).
  234. class StackFrameContext : public LocationContext {
  235. friend class LocationContextManager;
  236. // The call site where this stack frame is established.
  237. const Stmt *CallSite;
  238. // The parent block of the call site.
  239. const CFGBlock *Block;
  240. // The number of times the 'Block' has been visited.
  241. // It allows discriminating between stack frames of the same call that is
  242. // called multiple times in a loop.
  243. const unsigned BlockCount;
  244. // The index of the call site in the CFGBlock.
  245. const unsigned Index;
  246. StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
  247. const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
  248. unsigned Index, int64_t ID)
  249. : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
  250. Block(Block), BlockCount(BlockCount), Index(Index) {}
  251. public:
  252. ~StackFrameContext() override = default;
  253. const Stmt *getCallSite() const { return CallSite; }
  254. const CFGBlock *getCallSiteBlock() const { return Block; }
  255. bool inTopFrame() const override { return getParent() == nullptr; }
  256. unsigned getIndex() const { return Index; }
  257. CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
  258. void Profile(llvm::FoldingSetNodeID &ID) override;
  259. static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
  260. const LocationContext *ParentLC, const Stmt *S,
  261. const CFGBlock *Block, unsigned BlockCount,
  262. unsigned Index) {
  263. ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
  264. ID.AddPointer(Block);
  265. ID.AddInteger(BlockCount);
  266. ID.AddInteger(Index);
  267. }
  268. static bool classof(const LocationContext *LC) {
  269. return LC->getKind() == StackFrame;
  270. }
  271. };
  272. /// It represents a block invocation (based on BlockCall).
  273. class BlockInvocationContext : public LocationContext {
  274. friend class LocationContextManager;
  275. const BlockDecl *BD;
  276. // FIXME: Come up with a more type-safe way to model context-sensitivity.
  277. const void *Data;
  278. BlockInvocationContext(AnalysisDeclContext *ADC,
  279. const LocationContext *ParentLC, const BlockDecl *BD,
  280. const void *Data, int64_t ID)
  281. : LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {}
  282. public:
  283. ~BlockInvocationContext() override = default;
  284. const BlockDecl *getBlockDecl() const { return BD; }
  285. const void *getData() const { return Data; }
  286. void Profile(llvm::FoldingSetNodeID &ID) override;
  287. static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
  288. const LocationContext *ParentLC, const BlockDecl *BD,
  289. const void *Data) {
  290. ProfileCommon(ID, Block, ADC, ParentLC, BD);
  291. ID.AddPointer(Data);
  292. }
  293. static bool classof(const LocationContext *LC) {
  294. return LC->getKind() == Block;
  295. }
  296. };
  297. class LocationContextManager {
  298. llvm::FoldingSet<LocationContext> Contexts;
  299. // ID used for generating a new location context.
  300. int64_t NewID = 0;
  301. public:
  302. ~LocationContextManager();
  303. /// Obtain a context of the call stack using its parent context.
  304. ///
  305. /// \param ADC The AnalysisDeclContext.
  306. /// \param ParentLC The parent context of this newly created context.
  307. /// \param S The call.
  308. /// \param Block The basic block.
  309. /// \param BlockCount The current count of entering into \p Blk.
  310. /// \param Index The index of \p Blk.
  311. /// \returns The context for \p D with parent context \p ParentLC.
  312. const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
  313. const LocationContext *ParentLC,
  314. const Stmt *S, const CFGBlock *Block,
  315. unsigned BlockCount, unsigned Index);
  316. /// Obtain a context of the block invocation using its parent context.
  317. ///
  318. /// \param ADC The AnalysisDeclContext.
  319. /// \param ParentLC The parent context of this newly created context.
  320. /// \param BD The BlockDecl.
  321. /// \param Data The raw data to store as part of the context.
  322. const BlockInvocationContext *
  323. getBlockInvocationContext(AnalysisDeclContext *ADC,
  324. const LocationContext *ParentLC,
  325. const BlockDecl *BD, const void *Data);
  326. /// Discard all previously created LocationContext objects.
  327. void clear();
  328. };
  329. class AnalysisDeclContextManager {
  330. using ContextMap =
  331. llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
  332. ContextMap Contexts;
  333. LocationContextManager LocCtxMgr;
  334. CFG::BuildOptions cfgBuildOptions;
  335. // Pointer to an interface that can provide function bodies for
  336. // declarations from external source.
  337. std::unique_ptr<CodeInjector> Injector;
  338. // A factory for creating and caching implementations for common
  339. // methods during the analysis.
  340. BodyFarm FunctionBodyFarm;
  341. // Flag to indicate whether or not bodies should be synthesized
  342. // for well-known functions.
  343. bool SynthesizeBodies;
  344. public:
  345. AnalysisDeclContextManager(
  346. ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
  347. bool addImplicitDtors = false, bool addInitializers = false,
  348. bool addTemporaryDtors = false, bool addLifetime = false,
  349. bool addLoopExit = false, bool addScopes = false,
  350. bool synthesizeBodies = false, bool addStaticInitBranches = false,
  351. bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
  352. bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
  353. CodeInjector *injector = nullptr);
  354. AnalysisDeclContext *getContext(const Decl *D);
  355. bool getUseUnoptimizedCFG() const {
  356. return !cfgBuildOptions.PruneTriviallyFalseEdges;
  357. }
  358. CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
  359. /// \returns Whether faux bodies should be synthesized for known functions.
  360. bool synthesizeBodies() const { return SynthesizeBodies; }
  361. /// Obtain the beginning context of the analysis.
  362. ///
  363. /// \returns The top level stack frame for \p D.
  364. const StackFrameContext *getStackFrame(const Decl *D) {
  365. return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0,
  366. 0);
  367. }
  368. /// \copydoc LocationContextManager::getStackFrame()
  369. const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
  370. const LocationContext *Parent,
  371. const Stmt *S, const CFGBlock *Block,
  372. unsigned BlockCount, unsigned Index) {
  373. return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
  374. }
  375. BodyFarm &getBodyFarm();
  376. /// Discard all previously created AnalysisDeclContexts.
  377. void clear();
  378. private:
  379. friend class AnalysisDeclContext;
  380. LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
  381. };
  382. } // namespace clang
  383. #endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
  384. #ifdef __GNUC__
  385. #pragma GCC diagnostic pop
  386. #endif