Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/Analysis/AnalysisDeclContext.cpp
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||
#include <cassert> | #include <cassert> | ||||
#include <memory> | #include <memory> | ||||
using namespace clang; | using namespace clang; | ||||
using ManagedAnalysisMap = llvm::DenseMap<const void *, ManagedAnalysis *>; | using ManagedAnalysisMap = llvm::DenseMap<const void *, ManagedAnalysis *>; | ||||
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr, | ||||
const Decl *d, | const Decl *D, | ||||
const CFG::BuildOptions &buildOptions) | const CFG::BuildOptions &Options) | ||||
: Manager(Mgr), D(d), cfgBuildOptions(buildOptions) { | : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) { | ||||
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | ||||
} | } | ||||
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr, | ||||
const Decl *d) | const Decl *D) | ||||
: Manager(Mgr), D(d) { | : ADCMgr(ADCMgr), D(D) { | ||||
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; | ||||
} | } | ||||
AnalysisDeclContextManager::AnalysisDeclContextManager( | AnalysisDeclContextManager::AnalysisDeclContextManager( | ||||
ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors, | ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors, | ||||
bool addInitializers, bool addTemporaryDtors, bool addLifetime, | bool addInitializers, bool addTemporaryDtors, bool addLifetime, | ||||
bool addLoopExit, bool addScopes, bool synthesizeBodies, | bool addLoopExit, bool addScopes, bool synthesizeBodies, | ||||
bool addStaticInitBranch, bool addCXXNewAllocator, | bool addStaticInitBranch, bool addCXXNewAllocator, | ||||
Show All 18 Lines | |||||
void AnalysisDeclContextManager::clear() { Contexts.clear(); } | void AnalysisDeclContextManager::clear() { Contexts.clear(); } | ||||
Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { | Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { | ||||
IsAutosynthesized = false; | IsAutosynthesized = false; | ||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | ||||
Stmt *Body = FD->getBody(); | Stmt *Body = FD->getBody(); | ||||
if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body)) | if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body)) | ||||
Body = CoroBody->getBody(); | Body = CoroBody->getBody(); | ||||
if (Manager && Manager->synthesizeBodies()) { | if (ADCMgr && ADCMgr->synthesizeBodies()) { | ||||
Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD); | Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD); | ||||
if (SynthesizedBody) { | if (SynthesizedBody) { | ||||
Body = SynthesizedBody; | Body = SynthesizedBody; | ||||
IsAutosynthesized = true; | IsAutosynthesized = true; | ||||
} | } | ||||
} | } | ||||
return Body; | return Body; | ||||
} | } | ||||
else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | ||||
Stmt *Body = MD->getBody(); | Stmt *Body = MD->getBody(); | ||||
if (Manager && Manager->synthesizeBodies()) { | if (ADCMgr && ADCMgr->synthesizeBodies()) { | ||||
Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD); | Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD); | ||||
if (SynthesizedBody) { | if (SynthesizedBody) { | ||||
Body = SynthesizedBody; | Body = SynthesizedBody; | ||||
IsAutosynthesized = true; | IsAutosynthesized = true; | ||||
} | } | ||||
} | } | ||||
return Body; | return Body; | ||||
} else if (const auto *BD = dyn_cast<BlockDecl>(D)) | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) | ||||
return BD->getBody(); | return BD->getBody(); | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { | ||||
if (!AC) | if (!AC) | ||||
AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions); | AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions); | ||||
return AC.get(); | return AC.get(); | ||||
} | } | ||||
BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; } | BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; } | ||||
const StackFrameContext * | const StackFrameContext * | ||||
AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S, | AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC, | ||||
const CFGBlock *Blk, unsigned BlockCount, | const Stmt *S, const CFGBlock *Blk, | ||||
unsigned Idx) { | unsigned BlockCount, unsigned Index) { | ||||
return getLocationContextManager().getStackFrame(this, Parent, S, Blk, | return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk, | ||||
BlockCount, Idx); | BlockCount, Index); | ||||
} | } | ||||
const BlockInvocationContext * | const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext( | ||||
AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent, | const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) { | ||||
const BlockDecl *BD, | return getLocationContextManager().getBlockInvocationContext(this, ParentLC, | ||||
const void *ContextData) { | BD, Data); | ||||
return getLocationContextManager().getBlockInvocationContext(this, parent, | |||||
BD, ContextData); | |||||
} | } | ||||
bool AnalysisDeclContext::isInStdNamespace(const Decl *D) { | bool AnalysisDeclContext::isInStdNamespace(const Decl *D) { | ||||
const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext(); | const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext(); | ||||
const auto *ND = dyn_cast<NamespaceDecl>(DC); | const auto *ND = dyn_cast<NamespaceDecl>(DC); | ||||
if (!ND) | if (!ND) | ||||
return false; | return false; | ||||
while (const DeclContext *Parent = ND->getParent()) { | while (const DeclContext *Parent = ND->getParent()) { | ||||
if (!isa<NamespaceDecl>(Parent)) | if (!isa<NamespaceDecl>(Parent)) | ||||
break; | break; | ||||
ND = cast<NamespaceDecl>(Parent); | ND = cast<NamespaceDecl>(Parent); | ||||
} | } | ||||
return ND->isStdNamespace(); | return ND->isStdNamespace(); | ||||
} | } | ||||
LocationContextManager &AnalysisDeclContext::getLocationContextManager() { | LocationContextManager &AnalysisDeclContext::getLocationContextManager() { | ||||
assert(Manager && | assert( | ||||
ADCMgr && | |||||
"Cannot create LocationContexts without an AnalysisDeclContextManager!"); | "Cannot create LocationContexts without an AnalysisDeclContextManager!"); | ||||
return Manager->getLocationContextManager(); | return ADCMgr->getLocationContextManager(); | ||||
} | } | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// FoldingSet profiling. | // FoldingSet profiling. | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, | void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, | ||||
ContextKind ck, | ContextKind ck, | ||||
AnalysisDeclContext *ctx, | AnalysisDeclContext *ctx, | ||||
const LocationContext *parent, | const LocationContext *parent, | ||||
const void *data) { | const void *data) { | ||||
ID.AddInteger(ck); | ID.AddInteger(ck); | ||||
ID.AddPointer(ctx); | ID.AddPointer(ctx); | ||||
ID.AddPointer(parent); | ID.AddPointer(parent); | ||||
ID.AddPointer(data); | ID.AddPointer(data); | ||||
} | } | ||||
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { | void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { | ||||
Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, | Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, | ||||
BlockCount, Index); | BlockCount, Index); | ||||
} | } | ||||
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) { | |||||
Profile(ID, getAnalysisDeclContext(), getParent(), Enter); | |||||
} | |||||
void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { | void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { | ||||
Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData); | Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data); | ||||
} | } | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// LocationContext creation. | // LocationContext creation. | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
template <typename LOC, typename DATA> | |||||
const LOC* | |||||
LocationContextManager::getLocationContext(AnalysisDeclContext *ctx, | |||||
const LocationContext *parent, | |||||
const DATA *d) { | |||||
llvm::FoldingSetNodeID ID; | |||||
LOC::Profile(ID, ctx, parent, d); | |||||
void *InsertPos; | |||||
LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); | |||||
if (!L) { | |||||
L = new LOC(ctx, parent, d, ++NewID); | |||||
Contexts.InsertNode(L, InsertPos); | |||||
} | |||||
return L; | |||||
} | |||||
const StackFrameContext *LocationContextManager::getStackFrame( | const StackFrameContext *LocationContextManager::getStackFrame( | ||||
AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, | AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, | ||||
const CFGBlock *blk, unsigned blockCount, unsigned idx) { | const CFGBlock *blk, unsigned blockCount, unsigned idx) { | ||||
llvm::FoldingSetNodeID ID; | llvm::FoldingSetNodeID ID; | ||||
StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx); | StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx); | ||||
void *InsertPos; | void *InsertPos; | ||||
auto *L = | auto *L = | ||||
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); | cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); | ||||
if (!L) { | if (!L) { | ||||
L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID); | L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID); | ||||
Contexts.InsertNode(L, InsertPos); | Contexts.InsertNode(L, InsertPos); | ||||
} | } | ||||
return L; | return L; | ||||
} | } | ||||
const ScopeContext * | const BlockInvocationContext *LocationContextManager::getBlockInvocationContext( | ||||
LocationContextManager::getScope(AnalysisDeclContext *ctx, | AnalysisDeclContext *ADC, const LocationContext *ParentLC, | ||||
const LocationContext *parent, | const BlockDecl *BD, const void *Data) { | ||||
const Stmt *s) { | |||||
return getLocationContext<ScopeContext, Stmt>(ctx, parent, s); | |||||
} | |||||
const BlockInvocationContext * | |||||
LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx, | |||||
const LocationContext *parent, | |||||
const BlockDecl *BD, | |||||
const void *ContextData) { | |||||
llvm::FoldingSetNodeID ID; | llvm::FoldingSetNodeID ID; | ||||
BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData); | BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data); | ||||
void *InsertPos; | void *InsertPos; | ||||
auto *L = | auto *L = | ||||
cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID, | cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID, | ||||
InsertPos)); | InsertPos)); | ||||
if (!L) { | if (!L) { | ||||
L = new BlockInvocationContext(ctx, parent, BD, ContextData, ++NewID); | L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID); | ||||
Contexts.InsertNode(L, InsertPos); | Contexts.InsertNode(L, InsertPos); | ||||
} | } | ||||
return L; | return L; | ||||
} | } | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// LocationContext methods. | // LocationContext methods. | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
Show All 27 Lines | |||||
static void printLocation(raw_ostream &Out, const SourceManager &SM, | static void printLocation(raw_ostream &Out, const SourceManager &SM, | ||||
SourceLocation Loc) { | SourceLocation Loc) { | ||||
if (Loc.isFileID() && SM.isInMainFile(Loc)) | if (Loc.isFileID() && SM.isInMainFile(Loc)) | ||||
Out << SM.getExpansionLineNumber(Loc); | Out << SM.getExpansionLineNumber(Loc); | ||||
else | else | ||||
Loc.print(Out, SM); | Loc.print(Out, SM); | ||||
} | } | ||||
void LocationContext::dumpStack(raw_ostream &Out, const char *NL, | void LocationContext::dumpStack(raw_ostream &Out) const { | ||||
std::function<void(const LocationContext *)> | |||||
printMoreInfoPerContext) const { | |||||
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | ||||
PrintingPolicy PP(Ctx.getLangOpts()); | PrintingPolicy PP(Ctx.getLangOpts()); | ||||
PP.TerseOutput = 1; | PP.TerseOutput = 1; | ||||
const SourceManager &SM = | const SourceManager &SM = | ||||
getAnalysisDeclContext()->getASTContext().getSourceManager(); | getAnalysisDeclContext()->getASTContext().getSourceManager(); | ||||
unsigned Frame = 0; | unsigned Frame = 0; | ||||
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) { | for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) { | ||||
switch (LCtx->getKind()) { | switch (LCtx->getKind()) { | ||||
case StackFrame: | case StackFrame: | ||||
Out << "\t#" << Frame << ' '; | Out << "\t#" << Frame << ' '; | ||||
++Frame; | ++Frame; | ||||
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl())) | if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl())) | ||||
Out << "Calling " << D->getQualifiedNameAsString(); | Out << "Calling " << D->getQualifiedNameAsString(); | ||||
else | else | ||||
Out << "Calling anonymous code"; | Out << "Calling anonymous code"; | ||||
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | ||||
Out << " at line "; | Out << " at line "; | ||||
printLocation(Out, SM, S->getBeginLoc()); | printLocation(Out, SM, S->getBeginLoc()); | ||||
} | } | ||||
break; | break; | ||||
case Scope: | |||||
Out << "Entering scope"; | |||||
break; | |||||
case Block: | case Block: | ||||
Out << "Invoking block"; | Out << "Invoking block"; | ||||
if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | ||||
Out << " defined at line "; | Out << " defined at line "; | ||||
printLocation(Out, SM, D->getBeginLoc()); | printLocation(Out, SM, D->getBeginLoc()); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
Out << NL; | Out << '\n'; | ||||
printMoreInfoPerContext(LCtx); | |||||
} | } | ||||
} | } | ||||
void LocationContext::printJson(raw_ostream &Out, const char *NL, | void LocationContext::printJson(raw_ostream &Out, const char *NL, | ||||
unsigned int Space, bool IsDot, | unsigned int Space, bool IsDot, | ||||
std::function<void(const LocationContext *)> | std::function<void(const LocationContext *)> | ||||
printMoreInfoPerContext) const { | printMoreInfoPerContext) const { | ||||
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); | ||||
Show All 20 Lines | case StackFrame: | ||||
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) { | ||||
printSourceLocationAsJson(Out, S->getBeginLoc(), SM); | printSourceLocationAsJson(Out, S->getBeginLoc(), SM); | ||||
} else { | } else { | ||||
Out << "null"; | Out << "null"; | ||||
} | } | ||||
Out << ", \"items\": "; | Out << ", \"items\": "; | ||||
break; | break; | ||||
case Scope: | |||||
Out << "Entering scope\" "; | |||||
break; | |||||
case Block: | case Block: | ||||
Out << "Invoking block\" "; | Out << "Invoking block\" "; | ||||
if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) { | ||||
Out << ", \"location\": "; | Out << ", \"location\": "; | ||||
printSourceLocationAsJson(Out, D->getBeginLoc(), SM); | printSourceLocationAsJson(Out, D->getBeginLoc(), SM); | ||||
Out << ' '; | Out << ' '; | ||||
} | } | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 139 Lines • Show Last 20 Lines |