Go to the documentation of this file.
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"
51 using namespace clang;
58 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
64 : ADCMgr(ADCMgr), D(D) {
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,
75 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
76 SynthesizeBodies(synthesizeBodies) {
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();
101 if (SynthesizedBody) {
102 Body = SynthesizedBody;
103 IsAutosynthesized =
true;
108 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109 Stmt *Body = MD->getBody();
112 if (SynthesizedBody) {
113 Body = SynthesizedBody;
114 IsAutosynthesized =
true;
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();
123 llvm_unreachable(
"unknown code decl");
145 return isa<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
149 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
150 return MD->getSelfDecl();
151 if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
153 for (
const auto &I : BD->captures()) {
154 const VarDecl *VD = I.getVariable();
156 return dyn_cast<ImplicitParamDecl>(VD);
160 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
168 for (
const auto &LC : parent->
captures()) {
169 if (!LC.capturesVariable())
172 VarDecl *VD = LC.getCapturedVar();
174 return dyn_cast<ImplicitParamDecl>(VD);
184 if (
const auto *e = dyn_cast<Expr>(
stmt))
185 stmt = e->IgnoreParens();
186 (void) (*forcedBlkExprs)[
stmt];
191 assert(forcedBlkExprs);
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());
233 if (!builtCompleteCFG) {
240 builtCompleteCFG =
true;
248 return completeCFG.get();
253 return cfgStmtMap.get();
257 return cfgStmtMap.get();
282 if (
const auto *C = dyn_cast<CXXConstructorDecl>(
getDecl())) {
283 for (
const auto *I : C->inits()) {
284 PM->addStmt(I->getInit());
289 if (builtCompleteCFG)
296 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
303 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
305 AC = std::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
314 unsigned BlockCount,
unsigned Index) {
315 return getLocationContextManager().
getStackFrame(
this, ParentLC, S, Blk,
327 const auto *ND = dyn_cast<NamespaceDecl>(DC);
332 if (!isa<NamespaceDecl>(
Parent))
334 ND = cast<NamespaceDecl>(
Parent);
337 return ND->isStdNamespace();
342 llvm::raw_string_ostream OS(Str);
345 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
346 OS << FD->getQualifiedNameAsString();
352 for (
const auto &
P : FD->parameters()) {
353 if (
P != *FD->param_begin())
360 }
else if (isa<BlockDecl>(D)) {
368 }
else if (
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
371 OS << (OMD->isInstanceMethod() ?
'-' :
'+') <<
'[';
373 if (
const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
374 OS << OID->getName();
375 }
else if (
const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
376 OS << OID->getName();
377 }
else if (
const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
378 if (OC->IsClassExtension()) {
379 OS << OC->getClassInterface()->getName();
381 OS << OC->getIdentifier()->getNameStart() <<
'('
382 << OC->getIdentifier()->getNameStart() <<
')';
384 }
else if (
const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
385 OS << OCD->getClassInterface()->getName() <<
'(' << OCD->getName() <<
')';
387 OS <<
' ' << OMD->getSelector().getAsString() <<
']';
396 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
397 return ADCMgr->getLocationContextManager();
411 ID.AddPointer(parent);
430 const CFGBlock *blk,
unsigned blockCount,
unsigned idx) {
431 llvm::FoldingSetNodeID
ID;
435 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(
ID, InsertPos));
438 Contexts.InsertNode(L, InsertPos);
446 llvm::FoldingSetNodeID
ID;
450 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(
ID,
454 Contexts.InsertNode(L, InsertPos);
466 if (
const auto *SFC = dyn_cast<StackFrameContext>(LC))
492 Out <<
SM.getExpansionLineNumber(Loc);
507 switch (LCtx->getKind()) {
509 Out <<
"\t#" << Frame <<
' ';
511 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
514 Out <<
"Calling anonymous code";
515 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
521 Out <<
"Invoking block";
522 if (
const Decl *D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
523 Out <<
" defined at line ";
533 unsigned int Space,
bool IsDot,
535 printMoreInfoPerContext)
const {
546 <<
"{ \"lctx_id\": " << LCtx->getID() <<
", \"location_context\": \"";
547 switch (LCtx->getKind()) {
549 Out <<
'#' << Frame <<
" Call\", \"calling\": \"";
551 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
552 Out << D->getQualifiedNameAsString();
554 Out <<
"anonymous code";
556 Out <<
"\", \"location\": ";
557 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
563 Out <<
", \"items\": ";
566 Out <<
"Invoking block\" ";
567 if (
const Decl *D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
568 Out <<
", \"location\": ";
575 printMoreInfoPerContext(LCtx);
578 if (LCtx->getParent())
592 class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
601 : BEVals(bevals), BC(bc) {}
603 void VisitStmt(
Stmt *S) {
604 for (
auto *Child : S->children())
611 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
612 if (!VD->hasLocalStorage()) {
613 if (Visited.insert(VD).second)
628 Expr *Semantic = *it;
629 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
630 Semantic = OVE->getSourceExpr();
642 llvm::BumpPtrAllocator &A) {
651 for (
const auto &CI : BD->
captures()) {
656 FindBlockDeclRefExprsVals F(*BV, BC);
663 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
665 if (!ReferencedBlockVars)
666 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
670 return llvm::make_range(
V->begin(),
V->end());
673 std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
674 if (!ManagedAnalyses)
687 delete forcedBlkExprs;
688 delete ReferencedBlockVars;
699 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
700 E = Contexts.end(); I != E; ) {
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
CFGStmtMap * getCFGStmtMap()
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
ASTContext & getASTContext() const LLVM_READONLY
ASTContext & getASTContext() const
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D)
void clear()
Discard all previously created LocationContext objects.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const StackFrameContext * getStackFrame() const
semantics_iterator semantics_begin()
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
unsigned getLine() const
Return the presumed line number of this location.
bool isBodyAutosynthesized() const
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Encodes a location in the source.
bool synthesizeBodies() const
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const ImplicitParamDecl * getSelfDecl() const
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
const StackFrameContext * getStackFrame(LocationContext const *ParentLC, const Stmt *S, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
It represents a stack frame of the call stack (based on CallEvent).
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
bool MarkElidedCXXConstructors
Describes how types, statements, expressions, and declarations should be printed.
semantics_iterator semantics_end()
AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG=false, bool addImplicitDtors=false, bool addInitializers=false, bool addTemporaryDtors=false, bool addLifetime=false, bool addLoopExit=false, bool addScopes=false, bool synthesizeBodies=false, bool addStaticInitBranches=false, bool addCXXNewAllocator=true, bool addRichCXXConstructors=true, bool markElidedCXXConstructors=true, bool addVirtualBaseBranches=true, CodeInjector *injector=nullptr)
static CFGStmtMap * Build(CFG *C, ParentMap *PM)
Returns a new CFGMap for the given CFG.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
SourceManager & getSourceManager()
const BlockInvocationContext * getBlockInvocationContext(const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)
Obtain a context of the block invocation using its parent context.
bool AddRichCXXConstructors
This class handles loading and caching of source files into memory.
bool PruneTriviallyFalseEdges
void dumpCFG(bool ShowColors)
void registerForcedBlockExpression(const Stmt *stmt)
static bool isSelfDecl(const VarDecl *VD)
Returns true if.
ArrayRef< Capture > captures() const
Represents a single basic block in a source-level CFG.
bool inTopFrame() const override
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const
Prints out the call stack.
void print(raw_ostream &OS, const SourceManager &SM) const
ParentMap & getParentMap()
bool isBodyAutosynthesizedFromModelFile() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
const BlockDecl * getBlockDecl() const
virtual bool inTopFrame() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isParentOf(const LocationContext *LC) const
It represents a block invocation (based on BlockCall).
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
void setParent(const Stmt *S, const Stmt *Parent)
Manually sets the parent of S to Parent.
bool AddVirtualBaseBranches
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
~LocationContextManager()
Represents a variable declaration or definition.
unsigned getColumn() const
Return the presumed column number of this location.
static bool isInStdNamespace(const Decl *D)
capture_const_range captures() const
const StackFrameContext * getStackFrame(AnalysisDeclContext *ADC, const LocationContext *ParentLC, const Stmt *S, const CFGBlock *Block, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
BumpVector< const VarDecl * > DeclVec
unsigned TerseOutput
Provide a 'terse' output.
AnalysisDeclContext * getContext(const Decl *D)
CFG * getUnoptimizedCFG()
Expr *const * semantics_iterator
void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, const SourceManager &SM, bool AddBraces=true)
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
llvm::DenseMap< const void *, std::unique_ptr< ManagedAnalysis > > ManagedAnalysisMap
const LocationContext * getParent() const
It might return null.
Represents a C++ struct/union/class.
static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM)
Add each synthetic statement in the CFG to the parent map, using the source statement's parent.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
CFG::BuildOptions & getCFGBuildOptions()
LLVM_DUMP_METHOD void dump() const
const BlockInvocationContext * getBlockInvocationContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)
Obtain a context of the block invocation using its parent context.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
void clear()
Discard all previously created AnalysisDeclContexts.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Decl - This represents one declaration (or definition), e.g.
bool AddStaticInitBranches
void Profile(llvm::FoldingSetNodeID &ID) override
Stmt * getParent(Stmt *) const
static std::string getFunctionName(const Decl *D)
synthetic_stmt_iterator synthetic_stmt_end() const
ObjCMethodDecl - Represents an instance or class method declaration.
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
static DeclVec * LazyInitializeReferencedDecls(const BlockDecl *BD, void *&Vec, llvm::BumpPtrAllocator &A)
static void printLocation(raw_ostream &Out, const SourceManager &SM, SourceLocation Loc)
virtual ~ManagedAnalysis()
const Decl * getDecl() const
Stmt - This represents one statement.
bool isValid() const
Return true if this is a valid SourceLocation object.
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, AnalysisDeclContext *ctx, const LocationContext *parent, const void *data)
__device__ __2f16 float bool s
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
SourceLocation getBeginLoc() const LLVM_READONLY
ForcedBlkExprs ** forcedBlkExprs
__device__ __2f16 float c
void Profile(llvm::FoldingSetNodeID &ID) override
Stmt * getBody(const FunctionDecl *D)
Factory method for creating bodies for ordinary functions.
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
bool isLambda() const
Determine whether this class describes a lambda function object.
Represents an unpacked "presumed" location which can be presented to the user.
This represents one expression.
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
SourceLocation getLocation() const
void push_back(const_reference Elt, BumpVectorContext &C)
A reference to a declared variable, function, enum, etc.
const Decl * getDecl() const
Represents a function declaration or definition.
virtual ~LocationContext()
const LangOptions & getLangOpts() const
DeclContext * getDeclContext()
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.