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