| File: | build/source/clang/lib/Analysis/AnalysisDeclContext.cpp |
| Warning: | line 145, column 52 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===// | |||
| 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 | // This file defines AnalysisDeclContext, a class that manages the analysis | |||
| 10 | // context data for path sensitive analysis. | |||
| 11 | // | |||
| 12 | //===----------------------------------------------------------------------===// | |||
| 13 | ||||
| 14 | #include "clang/Analysis/AnalysisDeclContext.h" | |||
| 15 | #include "clang/AST/ASTContext.h" | |||
| 16 | #include "clang/AST/Decl.h" | |||
| 17 | #include "clang/AST/DeclBase.h" | |||
| 18 | #include "clang/AST/DeclCXX.h" | |||
| 19 | #include "clang/AST/DeclObjC.h" | |||
| 20 | #include "clang/AST/DeclTemplate.h" | |||
| 21 | #include "clang/AST/Expr.h" | |||
| 22 | #include "clang/AST/LambdaCapture.h" | |||
| 23 | #include "clang/AST/ParentMap.h" | |||
| 24 | #include "clang/AST/PrettyPrinter.h" | |||
| 25 | #include "clang/AST/Stmt.h" | |||
| 26 | #include "clang/AST/StmtCXX.h" | |||
| 27 | #include "clang/AST/StmtVisitor.h" | |||
| 28 | #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" | |||
| 29 | #include "clang/Analysis/BodyFarm.h" | |||
| 30 | #include "clang/Analysis/CFG.h" | |||
| 31 | #include "clang/Analysis/CFGStmtMap.h" | |||
| 32 | #include "clang/Analysis/Support/BumpVector.h" | |||
| 33 | #include "clang/Basic/JsonSupport.h" | |||
| 34 | #include "clang/Basic/LLVM.h" | |||
| 35 | #include "clang/Basic/SourceLocation.h" | |||
| 36 | #include "clang/Basic/SourceManager.h" | |||
| 37 | #include "llvm/ADT/DenseMap.h" | |||
| 38 | #include "llvm/ADT/FoldingSet.h" | |||
| 39 | #include "llvm/ADT/STLExtras.h" | |||
| 40 | #include "llvm/ADT/SmallPtrSet.h" | |||
| 41 | #include "llvm/ADT/iterator_range.h" | |||
| 42 | #include "llvm/Support/Allocator.h" | |||
| 43 | #include "llvm/Support/Casting.h" | |||
| 44 | #include "llvm/Support/Compiler.h" | |||
| 45 | #include "llvm/Support/ErrorHandling.h" | |||
| 46 | #include "llvm/Support/SaveAndRestore.h" | |||
| 47 | #include "llvm/Support/raw_ostream.h" | |||
| 48 | #include <cassert> | |||
| 49 | #include <memory> | |||
| 50 | ||||
| 51 | using namespace clang; | |||
| 52 | ||||
| 53 | using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>; | |||
| 54 | ||||
| 55 | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr, | |||
| 56 | const Decl *D, | |||
| 57 | const CFG::BuildOptions &Options) | |||
| 58 | : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) { | |||
| 59 | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | |||
| 60 | } | |||
| 61 | ||||
| 62 | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr, | |||
| 63 | const Decl *D) | |||
| 64 | : ADCMgr(ADCMgr), D(D) { | |||
| 65 | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | |||
| 66 | } | |||
| 67 | ||||
| 68 | AnalysisDeclContextManager::AnalysisDeclContextManager( | |||
| 69 | ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors, | |||
| 70 | bool addInitializers, bool addTemporaryDtors, bool addLifetime, | |||
| 71 | bool addLoopExit, bool addScopes, bool synthesizeBodies, | |||
| 72 | bool addStaticInitBranch, bool addCXXNewAllocator, | |||
| 73 | bool addRichCXXConstructors, bool markElidedCXXConstructors, | |||
| 74 | bool addVirtualBaseBranches, CodeInjector *injector) | |||
| 75 | : Injector(injector), FunctionBodyFarm(ASTCtx, injector), | |||
| 76 | SynthesizeBodies(synthesizeBodies) { | |||
| 77 | cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; | |||
| 78 | cfgBuildOptions.AddImplicitDtors = addImplicitDtors; | |||
| 79 | cfgBuildOptions.AddInitializers = addInitializers; | |||
| 80 | cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors; | |||
| 81 | cfgBuildOptions.AddLifetime = addLifetime; | |||
| 82 | cfgBuildOptions.AddLoopExit = addLoopExit; | |||
| 83 | cfgBuildOptions.AddScopes = addScopes; | |||
| 84 | cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; | |||
| 85 | cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; | |||
| 86 | cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors; | |||
| 87 | cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors; | |||
| 88 | cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches; | |||
| 89 | } | |||
| 90 | ||||
| 91 | void AnalysisDeclContextManager::clear() { Contexts.clear(); } | |||
| 92 | ||||
| 93 | Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { | |||
| 94 | IsAutosynthesized = false; | |||
| 95 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
| 96 | Stmt *Body = FD->getBody(); | |||
| 97 | if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body)) | |||
| 98 | Body = CoroBody->getBody(); | |||
| 99 | if (ADCMgr && ADCMgr->synthesizeBodies()) { | |||
| 100 | Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD); | |||
| 101 | if (SynthesizedBody) { | |||
| 102 | Body = SynthesizedBody; | |||
| 103 | IsAutosynthesized = true; | |||
| 104 | } | |||
| 105 | } | |||
| 106 | return Body; | |||
| 107 | } | |||
| 108 | else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
| 109 | Stmt *Body = MD->getBody(); | |||
| 110 | if (ADCMgr && ADCMgr->synthesizeBodies()) { | |||
| 111 | Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD); | |||
| 112 | if (SynthesizedBody) { | |||
| 113 | Body = SynthesizedBody; | |||
| 114 | IsAutosynthesized = true; | |||
| 115 | } | |||
| 116 | } | |||
| 117 | return Body; | |||
| 118 | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) | |||
| 119 | return BD->getBody(); | |||
| 120 | else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D)) | |||
| 121 | return FunTmpl->getTemplatedDecl()->getBody(); | |||
| 122 | ||||
| 123 | llvm_unreachable("unknown code decl")::llvm::llvm_unreachable_internal("unknown code decl", "clang/lib/Analysis/AnalysisDeclContext.cpp" , 123); | |||
| 124 | } | |||
| 125 | ||||
| 126 | Stmt *AnalysisDeclContext::getBody() const { | |||
| 127 | bool Tmp; | |||
| 128 | return getBody(Tmp); | |||
| 129 | } | |||
| 130 | ||||
| 131 | bool AnalysisDeclContext::isBodyAutosynthesized() const { | |||
| 132 | bool Tmp; | |||
| 133 | getBody(Tmp); | |||
| 134 | return Tmp; | |||
| 135 | } | |||
| 136 | ||||
| 137 | bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const { | |||
| 138 | bool Tmp; | |||
| 139 | Stmt *Body = getBody(Tmp); | |||
| 140 | return Tmp && Body->getBeginLoc().isValid(); | |||
| 141 | } | |||
| 142 | ||||
| 143 | /// Returns true if \param VD is an Objective-C implicit 'self' parameter. | |||
| 144 | static bool isSelfDecl(const VarDecl *VD) { | |||
| 145 | return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->getName() == "self"; | |||
| ||||
| 146 | } | |||
| 147 | ||||
| 148 | const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { | |||
| 149 | if (const auto *MD
| |||
| ||||
| 150 | return MD->getSelfDecl(); | |||
| 151 | if (const auto *BD
| |||
| 152 | // See if 'self' was captured by the block. | |||
| 153 | for (const auto &I : BD->captures()) { | |||
| 154 | const VarDecl *VD = I.getVariable(); | |||
| 155 | if (isSelfDecl(VD)) | |||
| 156 | return dyn_cast<ImplicitParamDecl>(VD); | |||
| 157 | } | |||
| 158 | } | |||
| 159 | ||||
| 160 | auto *CXXMethod = dyn_cast<CXXMethodDecl>(D); | |||
| 161 | if (!CXXMethod
| |||
| 162 | return nullptr; | |||
| 163 | ||||
| 164 | const CXXRecordDecl *parent = CXXMethod->getParent(); | |||
| 165 | if (!parent->isLambda()) | |||
| 166 | return nullptr; | |||
| 167 | ||||
| 168 | for (const auto &LC : parent->captures()) { | |||
| 169 | if (!LC.capturesVariable()) | |||
| 170 | continue; | |||
| 171 | ||||
| 172 | ValueDecl *VD = LC.getCapturedVar(); | |||
| 173 | if (isSelfDecl(dyn_cast<VarDecl>(VD))) | |||
| 174 | return dyn_cast<ImplicitParamDecl>(VD); | |||
| 175 | } | |||
| 176 | ||||
| 177 | return nullptr; | |||
| 178 | } | |||
| 179 | ||||
| 180 | void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) { | |||
| 181 | if (!forcedBlkExprs) | |||
| 182 | forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); | |||
| 183 | // Default construct an entry for 'stmt'. | |||
| 184 | if (const auto *e = dyn_cast<Expr>(stmt)) | |||
| 185 | stmt = e->IgnoreParens(); | |||
| 186 | (void) (*forcedBlkExprs)[stmt]; | |||
| 187 | } | |||
| 188 | ||||
| 189 | const CFGBlock * | |||
| 190 | AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) { | |||
| 191 | assert(forcedBlkExprs)(static_cast <bool> (forcedBlkExprs) ? void (0) : __assert_fail ("forcedBlkExprs", "clang/lib/Analysis/AnalysisDeclContext.cpp" , 191, __extension__ __PRETTY_FUNCTION__)); | |||
| 192 | if (const auto *e = dyn_cast<Expr>(stmt)) | |||
| 193 | stmt = e->IgnoreParens(); | |||
| 194 | CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = | |||
| 195 | forcedBlkExprs->find(stmt); | |||
| 196 | assert(itr != forcedBlkExprs->end())(static_cast <bool> (itr != forcedBlkExprs->end()) ? void (0) : __assert_fail ("itr != forcedBlkExprs->end()", "clang/lib/Analysis/AnalysisDeclContext.cpp", 196, __extension__ __PRETTY_FUNCTION__)); | |||
| 197 | return itr->second; | |||
| 198 | } | |||
| 199 | ||||
| 200 | /// Add each synthetic statement in the CFG to the parent map, using the | |||
| 201 | /// source statement's parent. | |||
| 202 | static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) { | |||
| 203 | if (!TheCFG) | |||
| 204 | return; | |||
| 205 | ||||
| 206 | for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(), | |||
| 207 | E = TheCFG->synthetic_stmt_end(); | |||
| 208 | I != E; ++I) { | |||
| 209 | PM.setParent(I->first, PM.getParent(I->second)); | |||
| 210 | } | |||
| 211 | } | |||
| 212 | ||||
| 213 | CFG *AnalysisDeclContext::getCFG() { | |||
| 214 | if (!cfgBuildOptions.PruneTriviallyFalseEdges) | |||
| 215 | return getUnoptimizedCFG(); | |||
| 216 | ||||
| 217 | if (!builtCFG) { | |||
| 218 | cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions); | |||
| 219 | // Even when the cfg is not successfully built, we don't | |||
| 220 | // want to try building it again. | |||
| 221 | builtCFG = true; | |||
| 222 | ||||
| 223 | if (PM) | |||
| 224 | addParentsForSyntheticStmts(cfg.get(), *PM); | |||
| 225 | ||||
| 226 | // The Observer should only observe one build of the CFG. | |||
| 227 | getCFGBuildOptions().Observer = nullptr; | |||
| 228 | } | |||
| 229 | return cfg.get(); | |||
| 230 | } | |||
| 231 | ||||
| 232 | CFG *AnalysisDeclContext::getUnoptimizedCFG() { | |||
| 233 | if (!builtCompleteCFG) { | |||
| 234 | SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, false); | |||
| 235 | completeCFG = | |||
| 236 | CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions); | |||
| 237 | // Even when the cfg is not successfully built, we don't | |||
| 238 | // want to try building it again. | |||
| 239 | builtCompleteCFG = true; | |||
| 240 | ||||
| 241 | if (PM) | |||
| 242 | addParentsForSyntheticStmts(completeCFG.get(), *PM); | |||
| 243 | ||||
| 244 | // The Observer should only observe one build of the CFG. | |||
| 245 | getCFGBuildOptions().Observer = nullptr; | |||
| 246 | } | |||
| 247 | return completeCFG.get(); | |||
| 248 | } | |||
| 249 | ||||
| 250 | CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() { | |||
| 251 | if (cfgStmtMap) | |||
| 252 | return cfgStmtMap.get(); | |||
| 253 | ||||
| 254 | if (CFG *c = getCFG()) { | |||
| 255 | cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); | |||
| 256 | return cfgStmtMap.get(); | |||
| 257 | } | |||
| 258 | ||||
| 259 | return nullptr; | |||
| 260 | } | |||
| 261 | ||||
| 262 | CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() { | |||
| 263 | if (CFA) | |||
| 264 | return CFA.get(); | |||
| 265 | ||||
| 266 | if (CFG *c = getCFG()) { | |||
| 267 | CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c)); | |||
| 268 | return CFA.get(); | |||
| 269 | } | |||
| 270 | ||||
| 271 | return nullptr; | |||
| 272 | } | |||
| 273 | ||||
| 274 | void AnalysisDeclContext::dumpCFG(bool ShowColors) { | |||
| 275 | getCFG()->dump(getASTContext().getLangOpts(), ShowColors); | |||
| 276 | } | |||
| 277 | ||||
| 278 | ParentMap &AnalysisDeclContext::getParentMap() { | |||
| 279 | if (!PM) { | |||
| 280 | PM.reset(new ParentMap(getBody())); | |||
| 281 | if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) { | |||
| 282 | for (const auto *I : C->inits()) { | |||
| 283 | PM->addStmt(I->getInit()); | |||
| 284 | } | |||
| 285 | } | |||
| 286 | if (builtCFG) | |||
| 287 | addParentsForSyntheticStmts(getCFG(), *PM); | |||
| 288 | if (builtCompleteCFG) | |||
| 289 | addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM); | |||
| 290 | } | |||
| 291 | return *PM; | |||
| 292 | } | |||
| 293 | ||||
| 294 | AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { | |||
| 295 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
| 296 | // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl | |||
| 297 | // that has the body. | |||
| 298 | FD->hasBody(FD); | |||
| 299 | D = FD; | |||
| 300 | } | |||
| 301 | ||||
| 302 | std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D]; | |||
| 303 | if (!AC) | |||
| 304 | AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions); | |||
| 305 | return AC.get(); | |||
| 306 | } | |||
| 307 | ||||
| 308 | BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; } | |||
| 309 | ||||
| 310 | const StackFrameContext * | |||
| 311 | AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC, | |||
| 312 | const Stmt *S, const CFGBlock *Blk, | |||
| 313 | unsigned BlockCount, unsigned Index) { | |||
| 314 | return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk, | |||
| 315 | BlockCount, Index); | |||
| 316 | } | |||
| 317 | ||||
| 318 | const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext( | |||
| 319 | const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) { | |||
| 320 | return getLocationContextManager().getBlockInvocationContext(this, ParentLC, | |||
| 321 | BD, Data); | |||
| 322 | } | |||
| 323 | ||||
| 324 | bool AnalysisDeclContext::isInStdNamespace(const Decl *D) { | |||
| 325 | const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext(); | |||
| 326 | const auto *ND = dyn_cast<NamespaceDecl>(DC); | |||
| 327 | if (!ND) | |||
| 328 | return false; | |||
| 329 | ||||
| 330 | while (const DeclContext *Parent = ND->getParent()) { | |||
| 331 | if (!isa<NamespaceDecl>(Parent)) | |||
| 332 | break; | |||
| 333 | ND = cast<NamespaceDecl>(Parent); | |||
| 334 | } | |||
| 335 | ||||
| 336 | return ND->isStdNamespace(); | |||
| 337 | } | |||
| 338 | ||||
| 339 | std::string AnalysisDeclContext::getFunctionName(const Decl *D) { | |||
| 340 | std::string Str; | |||
| 341 | llvm::raw_string_ostream OS(Str); | |||
| 342 | const ASTContext &Ctx = D->getASTContext(); | |||
| 343 | ||||
| 344 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { | |||
| 345 | OS << FD->getQualifiedNameAsString(); | |||
| 346 | ||||
| 347 | // In C++, there are overloads. | |||
| 348 | ||||
| 349 | if (Ctx.getLangOpts().CPlusPlus) { | |||
| 350 | OS << '('; | |||
| 351 | for (const auto &P : FD->parameters()) { | |||
| 352 | if (P != *FD->param_begin()) | |||
| 353 | OS << ", "; | |||
| 354 | OS << P->getType(); | |||
| 355 | } | |||
| 356 | OS << ')'; | |||
| 357 | } | |||
| 358 | ||||
| 359 | } else if (isa<BlockDecl>(D)) { | |||
| 360 | PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation()); | |||
| 361 | ||||
| 362 | if (Loc.isValid()) { | |||
| 363 | OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn() | |||
| 364 | << ')'; | |||
| 365 | } | |||
| 366 | ||||
| 367 | } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { | |||
| 368 | ||||
| 369 | // FIXME: copy-pasted from CGDebugInfo.cpp. | |||
| 370 | OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; | |||
| 371 | const DeclContext *DC = OMD->getDeclContext(); | |||
| 372 | if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) { | |||
| 373 | OS << OID->getName(); | |||
| 374 | } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) { | |||
| 375 | OS << OID->getName(); | |||
| 376 | } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) { | |||
| 377 | if (OC->IsClassExtension()) { | |||
| 378 | OS << OC->getClassInterface()->getName(); | |||
| 379 | } else { | |||
| 380 | OS << OC->getIdentifier()->getNameStart() << '(' | |||
| 381 | << OC->getIdentifier()->getNameStart() << ')'; | |||
| 382 | } | |||
| 383 | } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) { | |||
| 384 | OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')'; | |||
| 385 | } | |||
| 386 | OS << ' ' << OMD->getSelector().getAsString() << ']'; | |||
| 387 | } | |||
| 388 | ||||
| 389 | return Str; | |||
| 390 | } | |||
| 391 | ||||
| 392 | LocationContextManager &AnalysisDeclContext::getLocationContextManager() { | |||
| 393 | assert((static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!" ) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\"" , "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__ __PRETTY_FUNCTION__)) | |||
| 394 | ADCMgr &&(static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!" ) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\"" , "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__ __PRETTY_FUNCTION__)) | |||
| 395 | "Cannot create LocationContexts without an AnalysisDeclContextManager!")(static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!" ) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\"" , "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__ __PRETTY_FUNCTION__)); | |||
| 396 | return ADCMgr->getLocationContextManager(); | |||
| 397 | } | |||
| 398 | ||||
| 399 | //===----------------------------------------------------------------------===// | |||
| 400 | // FoldingSet profiling. | |||
| 401 | //===----------------------------------------------------------------------===// | |||
| 402 | ||||
| 403 | void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, | |||
| 404 | ContextKind ck, | |||
| 405 | AnalysisDeclContext *ctx, | |||
| 406 | const LocationContext *parent, | |||
| 407 | const void *data) { | |||
| 408 | ID.AddInteger(ck); | |||
| 409 | ID.AddPointer(ctx); | |||
| 410 | ID.AddPointer(parent); | |||
| 411 | ID.AddPointer(data); | |||
| 412 | } | |||
| 413 | ||||
| 414 | void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { | |||
| 415 | Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, | |||
| 416 | BlockCount, Index); | |||
| 417 | } | |||
| 418 | ||||
| 419 | void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { | |||
| 420 | Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data); | |||
| 421 | } | |||
| 422 | ||||
| 423 | //===----------------------------------------------------------------------===// | |||
| 424 | // LocationContext creation. | |||
| 425 | //===----------------------------------------------------------------------===// | |||
| 426 | ||||
| 427 | const StackFrameContext *LocationContextManager::getStackFrame( | |||
| 428 | AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, | |||
| 429 | const CFGBlock *blk, unsigned blockCount, unsigned idx) { | |||
| 430 | llvm::FoldingSetNodeID ID; | |||
| 431 | StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx); | |||
| 432 | void *InsertPos; | |||
| 433 | auto *L = | |||
| 434 | cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); | |||
| 435 | if (!L) { | |||
| 436 | L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID); | |||
| 437 | Contexts.InsertNode(L, InsertPos); | |||
| 438 | } | |||
| 439 | return L; | |||
| 440 | } | |||
| 441 | ||||
| 442 | const BlockInvocationContext *LocationContextManager::getBlockInvocationContext( | |||
| 443 | AnalysisDeclContext *ADC, const LocationContext *ParentLC, | |||
| 444 | const BlockDecl *BD, const void *Data) { | |||
| 445 | llvm::FoldingSetNodeID ID; | |||
| 446 | BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data); | |||
| 447 | void *InsertPos; | |||
| 448 | auto *L = | |||
| 449 | cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID, | |||
| 450 | InsertPos)); | |||
| 451 | if (!L) { | |||
| 452 | L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID); | |||
| 453 | Contexts.InsertNode(L, InsertPos); | |||
| 454 | } | |||
| 455 | return L; | |||
| 456 | } | |||
| 457 | ||||
| 458 | //===----------------------------------------------------------------------===// | |||
| 459 | // LocationContext methods. | |||
| 460 | //===----------------------------------------------------------------------===// | |||
| 461 | ||||
| 462 | const StackFrameContext *LocationContext::getStackFrame() const { | |||
| 463 | const LocationContext *LC = this; | |||
| 464 | while (LC) { | |||
| 465 | if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) | |||
| 466 | return SFC; | |||
| 467 | LC = LC->getParent(); | |||
| 468 | } | |||
| 469 | return nullptr; | |||
| 470 | } | |||
| 471 | ||||
| 472 | bool LocationContext::inTopFrame() const { | |||
| 473 | return getStackFrame()->inTopFrame(); | |||
| 474 | } | |||
| 475 | ||||
| 476 | bool LocationContext::isParentOf(const LocationContext *LC) const { | |||
| 477 | do { | |||
| 478 | const LocationContext *Parent = LC->getParent(); | |||
| 479 | if (Parent == this) | |||
| 480 | return true; | |||
| 481 | else | |||
| 482 | LC = Parent; | |||
| 483 | } while (LC); | |||
| 484 | ||||
| 485 | return false; | |||
| 486 | } | |||
| 487 | ||||
| 488 | static void printLocation(raw_ostream &Out, const SourceManager &SM, | |||
| 489 | SourceLocation Loc) { | |||
| 490 | if (Loc.isFileID() && SM.isInMainFile(Loc)) | |||
| 491 | Out << SM.getExpansionLineNumber(Loc); | |||
| 492 | else | |||
| 493 | Loc.print(Out, SM); | |||
| 494 | } | |||
| 495 | ||||
| 496 | void LocationContext::dumpStack(raw_ostream &Out) const { | |||
| 497 | ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | |||
| 498 | PrintingPolicy PP(Ctx.getLangOpts()); | |||
| 499 | PP.TerseOutput = 1; | |||
| 500 | ||||
| 501 | const SourceManager &SM = | |||
| 502 | getAnalysisDeclContext()->getASTContext().getSourceManager(); | |||
| 503 | ||||
| 504 | unsigned Frame = 0; | |||
| 505 | for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) { | |||
| 506 | switch (LCtx->getKind()) { | |||
| 507 | case StackFrame: | |||
| 508 | Out << "\t#" << Frame << ' '; | |||
| 509 | ++Frame; | |||
| 510 | if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl())) | |||
| 511 | Out << "Calling " << AnalysisDeclContext::getFunctionName(D); | |||
| 512 | else | |||
| 513 | Out << "Calling anonymous code"; | |||
| 514 | if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | |||
| 515 | Out << " at line "; | |||
| 516 | printLocation(Out, SM, S->getBeginLoc()); | |||
| 517 | } | |||
| 518 | break; | |||
| 519 | case Block: | |||
| 520 | Out << "Invoking block"; | |||
| 521 | if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | |||
| 522 | Out << " defined at line "; | |||
| 523 | printLocation(Out, SM, D->getBeginLoc()); | |||
| 524 | } | |||
| 525 | break; | |||
| 526 | } | |||
| 527 | Out << '\n'; | |||
| 528 | } | |||
| 529 | } | |||
| 530 | ||||
| 531 | void LocationContext::printJson(raw_ostream &Out, const char *NL, | |||
| 532 | unsigned int Space, bool IsDot, | |||
| 533 | std::function<void(const LocationContext *)> | |||
| 534 | printMoreInfoPerContext) const { | |||
| 535 | ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | |||
| 536 | PrintingPolicy PP(Ctx.getLangOpts()); | |||
| 537 | PP.TerseOutput = 1; | |||
| 538 | ||||
| 539 | const SourceManager &SM = | |||
| 540 | getAnalysisDeclContext()->getASTContext().getSourceManager(); | |||
| 541 | ||||
| 542 | unsigned Frame = 0; | |||
| 543 | for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) { | |||
| 544 | Indent(Out, Space, IsDot) | |||
| 545 | << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \""; | |||
| 546 | switch (LCtx->getKind()) { | |||
| 547 | case StackFrame: | |||
| 548 | Out << '#' << Frame << " Call\", \"calling\": \""; | |||
| 549 | ++Frame; | |||
| 550 | if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl())) | |||
| 551 | Out << D->getQualifiedNameAsString(); | |||
| 552 | else | |||
| 553 | Out << "anonymous code"; | |||
| 554 | ||||
| 555 | Out << "\", \"location\": "; | |||
| 556 | if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | |||
| 557 | printSourceLocationAsJson(Out, S->getBeginLoc(), SM); | |||
| 558 | } else { | |||
| 559 | Out << "null"; | |||
| 560 | } | |||
| 561 | ||||
| 562 | Out << ", \"items\": "; | |||
| 563 | break; | |||
| 564 | case Block: | |||
| 565 | Out << "Invoking block\" "; | |||
| 566 | if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | |||
| 567 | Out << ", \"location\": "; | |||
| 568 | printSourceLocationAsJson(Out, D->getBeginLoc(), SM); | |||
| 569 | Out << ' '; | |||
| 570 | } | |||
| 571 | break; | |||
| 572 | } | |||
| 573 | ||||
| 574 | printMoreInfoPerContext(LCtx); | |||
| 575 | ||||
| 576 | Out << '}'; | |||
| 577 | if (LCtx->getParent()) | |||
| 578 | Out << ','; | |||
| 579 | Out << NL; | |||
| 580 | } | |||
| 581 | } | |||
| 582 | ||||
| 583 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void LocationContext::dump() const { printJson(llvm::errs()); } | |||
| 584 | ||||
| 585 | //===----------------------------------------------------------------------===// | |||
| 586 | // Lazily generated map to query the external variables referenced by a Block. | |||
| 587 | //===----------------------------------------------------------------------===// | |||
| 588 | ||||
| 589 | namespace { | |||
| 590 | ||||
| 591 | class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{ | |||
| 592 | BumpVector<const VarDecl *> &BEVals; | |||
| 593 | BumpVectorContext &BC; | |||
| 594 | llvm::SmallPtrSet<const VarDecl *, 4> Visited; | |||
| 595 | llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts; | |||
| 596 | ||||
| 597 | public: | |||
| 598 | FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals, | |||
| 599 | BumpVectorContext &bc) | |||
| 600 | : BEVals(bevals), BC(bc) {} | |||
| 601 | ||||
| 602 | void VisitStmt(Stmt *S) { | |||
| 603 | for (auto *Child : S->children()) | |||
| 604 | if (Child) | |||
| 605 | Visit(Child); | |||
| 606 | } | |||
| 607 | ||||
| 608 | void VisitDeclRefExpr(DeclRefExpr *DR) { | |||
| 609 | // Non-local variables are also directly modified. | |||
| 610 | if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) { | |||
| 611 | if (!VD->hasLocalStorage()) { | |||
| 612 | if (Visited.insert(VD).second) | |||
| 613 | BEVals.push_back(VD, BC); | |||
| 614 | } | |||
| 615 | } | |||
| 616 | } | |||
| 617 | ||||
| 618 | void VisitBlockExpr(BlockExpr *BR) { | |||
| 619 | // Blocks containing blocks can transitively capture more variables. | |||
| 620 | IgnoredContexts.insert(BR->getBlockDecl()); | |||
| 621 | Visit(BR->getBlockDecl()->getBody()); | |||
| 622 | } | |||
| 623 | ||||
| 624 | void VisitPseudoObjectExpr(PseudoObjectExpr *PE) { | |||
| 625 | for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(), | |||
| 626 | et = PE->semantics_end(); it != et; ++it) { | |||
| 627 | Expr *Semantic = *it; | |||
| 628 | if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) | |||
| 629 | Semantic = OVE->getSourceExpr(); | |||
| 630 | Visit(Semantic); | |||
| 631 | } | |||
| 632 | } | |||
| 633 | }; | |||
| 634 | ||||
| 635 | } // namespace | |||
| 636 | ||||
| 637 | using DeclVec = BumpVector<const VarDecl *>; | |||
| 638 | ||||
| 639 | static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD, | |||
| 640 | void *&Vec, | |||
| 641 | llvm::BumpPtrAllocator &A) { | |||
| 642 | if (Vec) | |||
| 643 | return (DeclVec*) Vec; | |||
| 644 | ||||
| 645 | BumpVectorContext BC(A); | |||
| 646 | DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>(); | |||
| 647 | new (BV) DeclVec(BC, 10); | |||
| 648 | ||||
| 649 | // Go through the capture list. | |||
| 650 | for (const auto &CI : BD->captures()) { | |||
| 651 | BV->push_back(CI.getVariable(), BC); | |||
| 652 | } | |||
| 653 | ||||
| 654 | // Find the referenced global/static variables. | |||
| 655 | FindBlockDeclRefExprsVals F(*BV, BC); | |||
| 656 | F.Visit(BD->getBody()); | |||
| 657 | ||||
| 658 | Vec = BV; | |||
| 659 | return BV; | |||
| 660 | } | |||
| 661 | ||||
| 662 | llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator> | |||
| 663 | AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) { | |||
| 664 | if (!ReferencedBlockVars) | |||
| 665 | ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>(); | |||
| 666 | ||||
| 667 | const DeclVec *V = | |||
| 668 | LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A); | |||
| 669 | return llvm::make_range(V->begin(), V->end()); | |||
| 670 | } | |||
| 671 | ||||
| 672 | std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) { | |||
| 673 | if (!ManagedAnalyses) | |||
| 674 | ManagedAnalyses = new ManagedAnalysisMap(); | |||
| 675 | ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; | |||
| 676 | return (*M)[tag]; | |||
| 677 | } | |||
| 678 | ||||
| 679 | //===----------------------------------------------------------------------===// | |||
| 680 | // Cleanup. | |||
| 681 | //===----------------------------------------------------------------------===// | |||
| 682 | ||||
| 683 | ManagedAnalysis::~ManagedAnalysis() = default; | |||
| 684 | ||||
| 685 | AnalysisDeclContext::~AnalysisDeclContext() { | |||
| 686 | delete forcedBlkExprs; | |||
| 687 | delete ReferencedBlockVars; | |||
| 688 | delete (ManagedAnalysisMap*) ManagedAnalyses; | |||
| 689 | } | |||
| 690 | ||||
| 691 | LocationContext::~LocationContext() = default; | |||
| 692 | ||||
| 693 | LocationContextManager::~LocationContextManager() { | |||
| 694 | clear(); | |||
| 695 | } | |||
| 696 | ||||
| 697 | void LocationContextManager::clear() { | |||
| 698 | for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(), | |||
| 699 | E = Contexts.end(); I != E; ) { | |||
| 700 | LocationContext *LC = &*I; | |||
| 701 | ++I; | |||
| 702 | delete LC; | |||
| 703 | } | |||
| 704 | Contexts.clear(); | |||
| 705 | } |