37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/FoldingSet.h"
39#include "llvm/ADT/SmallPtrSet.h"
40#include "llvm/ADT/iterator_range.h"
41#include "llvm/Support/Allocator.h"
42#include "llvm/Support/Compiler.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/SaveAndRestore.h"
45#include "llvm/Support/raw_ostream.h"
56 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
57 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
62 : ADCMgr(ADCMgr), D(D) {
63 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
67 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
68 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
70 bool addStaticInitBranch,
bool addCXXNewAllocator,
71 bool addRichCXXConstructors,
bool markElidedCXXConstructors,
72 bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector)
73 : Injector(
std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()),
75 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
76 cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
77 cfgBuildOptions.AddInitializers = addInitializers;
78 cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
79 cfgBuildOptions.AddLifetime = addLifetime;
80 cfgBuildOptions.AddLoopExit = addLoopExit;
81 cfgBuildOptions.AddScopes = addScopes;
82 cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
83 cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
84 cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
85 cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
86 cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
92 IsAutosynthesized =
false;
93 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
94 Stmt *Body = FD->getBody();
95 if (
auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
96 Body = CoroBody->getBody();
97 if (ADCMgr && ADCMgr->synthesizeBodies()) {
98 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
99 if (SynthesizedBody) {
100 Body = SynthesizedBody;
101 IsAutosynthesized =
true;
106 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
107 Stmt *Body = MD->getBody();
108 if (ADCMgr && ADCMgr->synthesizeBodies()) {
109 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
110 if (SynthesizedBody) {
111 Body = SynthesizedBody;
112 IsAutosynthesized =
true;
116 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D))
117 return BD->getBody();
118 else if (
const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
119 return FunTmpl->getTemplatedDecl()->getBody();
120 else if (
const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
121 if (VD->isFileVarDecl()) {
122 return const_cast<Stmt *
>(dyn_cast_or_null<Stmt>(VD->getInit()));
126 llvm_unreachable(
"unknown code decl");
148 return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
152 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
153 return MD->getSelfDecl();
154 if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
156 for (
const auto &I : BD->captures()) {
157 const VarDecl *VD = I.getVariable();
159 return dyn_cast<ImplicitParamDecl>(VD);
163 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
171 for (
const auto &LC : parent->
captures()) {
172 if (!LC.capturesVariable())
177 return dyn_cast<ImplicitParamDecl>(VD);
187 if (
const auto *e = dyn_cast<Expr>(
stmt))
188 stmt = e->IgnoreParens();
189 (void) (*forcedBlkExprs)[
stmt];
194 assert(forcedBlkExprs);
195 if (
const auto *e = dyn_cast<Expr>(
stmt))
196 stmt = e->IgnoreParens();
197 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
198 forcedBlkExprs->find(
stmt);
199 assert(itr != forcedBlkExprs->end());
217 if (!cfgBuildOptions.PruneTriviallyFalseEdges)
236 if (!builtCompleteCFG) {
237 SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
false);
242 builtCompleteCFG =
true;
250 return completeCFG.get();
255 return cfgStmtMap.get();
259 return cfgStmtMap.get();
284 if (
const auto *
C = dyn_cast<CXXConstructorDecl>(
getDecl())) {
285 for (
const auto *I :
C->inits()) {
286 PM->addStmt(I->getInit());
291 if (builtCompleteCFG)
298 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
305 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
307 AC = std::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
316 unsigned BlockCount,
unsigned Index) {
317 return getLocationContextManager().
getStackFrame(
this, ParentLC, S, Blk,
323 return getLocationContextManager().getBlockInvocationContext(
this, ParentLC,
329 const auto *ND = dyn_cast<NamespaceDecl>(DC);
339 return ND->isStdNamespace();
344 llvm::raw_string_ostream OS(Str);
347 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
348 OS << FD->getQualifiedNameAsString();
354 for (
const auto &P : FD->parameters()) {
355 if (P != *FD->param_begin())
370 }
else if (
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
373 OS << (OMD->isInstanceMethod() ?
'-' :
'+') <<
'[';
375 if (
const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
376 OS << OID->getName();
377 }
else if (
const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
378 OS << OID->getName();
379 }
else if (
const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
380 if (OC->IsClassExtension()) {
381 OS << OC->getClassInterface()->getName();
383 OS << OC->getIdentifier()->getNameStart() <<
'('
384 << OC->getIdentifier()->getNameStart() <<
')';
386 }
else if (
const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
387 OS << OCD->getClassInterface()->getName() <<
'(' << OCD->getName() <<
')';
389 OS <<
' ' << OMD->getSelector().getAsString() <<
']';
398 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
399 return ADCMgr->getLocationContextManager();
413 ID.AddPointer(parent);
432 const CFGBlock *blk,
unsigned blockCount,
unsigned idx) {
433 llvm::FoldingSetNodeID ID;
437 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
440 Contexts.InsertNode(L, InsertPos);
448 llvm::FoldingSetNodeID ID;
452 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
456 Contexts.InsertNode(L, InsertPos);
468 if (
const auto *SFC = dyn_cast<StackFrameContext>(LC))
494 Out <<
SM.getExpansionLineNumber(Loc);
508 for (
const LocationContext *LCtx =
this; LCtx; LCtx = LCtx->getParent()) {
509 switch (LCtx->getKind()) {
511 Out <<
"\t#" << Frame <<
' ';
513 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
516 Out <<
"Calling anonymous code";
523 Out <<
"Invoking block";
525 Out <<
" defined at line ";
535 unsigned int Space,
bool IsDot,
537 printMoreInfoPerContext)
const {
546 for (
const LocationContext *LCtx =
this; LCtx; LCtx = LCtx->getParent()) {
548 <<
"{ \"lctx_id\": " << LCtx->getID() <<
", \"location_context\": \"";
549 switch (LCtx->getKind()) {
551 Out <<
'#' << Frame <<
" Call\", \"calling\": \"";
553 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
554 Out << D->getQualifiedNameAsString();
556 Out <<
"anonymous code";
558 Out <<
"\", \"location\": ";
565 Out <<
", \"items\": ";
568 Out <<
"Invoking block\" ";
570 Out <<
", \"location\": ";
577 printMoreInfoPerContext(LCtx);
580 if (LCtx->getParent())
594class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
603 : BEVals(bevals), BC(bc) {}
605 void VisitStmt(
Stmt *S) {
611 void VisitDeclRefExpr(DeclRefExpr *DR) {
613 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
614 if (!VD->hasLocalStorage()) {
615 if (Visited.insert(VD).second)
621 void VisitBlockExpr(BlockExpr *BR) {
627 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
630 Expr *Semantic = *it;
631 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
632 Semantic = OVE->getSourceExpr();
644 llvm::BumpPtrAllocator &A) {
653 for (
const auto &CI : BD->
captures()) {
658 FindBlockDeclRefExprsVals F(*BV, BC);
665llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
667 if (!ReferencedBlockVars)
668 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
672 return llvm::make_range(
V->begin(),
V->end());
675std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
676 if (!ManagedAnalyses)
689 delete forcedBlkExprs;
690 delete ReferencedBlockVars;
701 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
702 E = Contexts.end(); I != E; ) {
Defines the clang::ASTContext interface.
static DeclVec * LazyInitializeReferencedDecls(const BlockDecl *BD, void *&Vec, llvm::BumpPtrAllocator &A)
static bool isSelfDecl(const VarDecl *VD)
Returns true if.
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.
static void printLocation(raw_ostream &Out, const SourceManager &SM, SourceLocation Loc)
llvm::DenseMap< const void *, std::unique_ptr< ManagedAnalysis > > ManagedAnalysisMap
BumpVector< const VarDecl * > DeclVec
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the LambdaCapture class.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
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, std::unique_ptr< CodeInjector > injector=nullptr)
friend class AnalysisDeclContext
bool synthesizeBodies() const
void clear()
Discard all previously created AnalysisDeclContexts.
AnalysisDeclContext * getContext(const Decl *D)
AnalysisDeclContext contains the context data for the function, method or block under analysis.
static std::string getFunctionName(const Decl *D)
void registerForcedBlockExpression(const Stmt *stmt)
const BlockInvocationContext * getBlockInvocationContext(const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)
Obtain a context of the block invocation using its parent context.
CFGStmtMap * getCFGStmtMap()
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
ParentMap & getParentMap()
const Decl * getDecl() const
static bool isInStdNamespace(const Decl *D)
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
const ImplicitParamDecl * getSelfDecl() const
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.
ASTContext & getASTContext() const
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
bool isBodyAutosynthesized() const
CFG * getUnoptimizedCFG()
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D)
void dumpCFG(bool ShowColors)
CFG::BuildOptions & getCFGBuildOptions()
bool isBodyAutosynthesizedFromModelFile() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ArrayRef< Capture > captures() const
const BlockDecl * getBlockDecl() const
It represents a block invocation (based on BlockCall).
void Profile(llvm::FoldingSetNodeID &ID) override
void push_back(const_reference Elt, BumpVectorContext &C)
Represents a single basic block in a source-level CFG.
static CFGStmtMap * Build(CFG *C, ParentMap *PM)
Returns a new CFGMap for the given CFG.
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
synthetic_stmt_iterator synthetic_stmt_end() const
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
capture_const_range captures() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Decl - This represents one declaration (or definition), e.g.
Represents a function declaration or definition.
~LocationContextManager()
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.
void clear()
Discard all previously created LocationContext objects.
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.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
LocationContext(ContextKind k, AnalysisDeclContext *ctx, const LocationContext *parent, int64_t ID)
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, AnalysisDeclContext *ctx, const LocationContext *parent, const void *data)
const LocationContext * getParent() const
It might return null.
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const
Prints out the call stack.
LLVM_DUMP_METHOD void dump() const
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
virtual ~LocationContext()
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.
virtual ~ManagedAnalysis()
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ObjCMethodDecl - Represents an instance or class method declaration.
void setParent(const Stmt *S, const Stmt *Parent)
Manually sets the parent of S to Parent.
Stmt * getParent(Stmt *) const
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
semantics_iterator semantics_end()
semantics_iterator semantics_begin()
Expr *const * semantics_iterator
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
void print(raw_ostream &OS, const SourceManager &SM) const
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
It represents a stack frame of the call stack (based on CallEvent).
void Profile(llvm::FoldingSetNodeID &ID) override
bool inTopFrame() const override
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, const SourceManager &SM, bool AddBraces=true)
U cast(CodeGen::Address addr)
int const char * function
Describes how types, statements, expressions, and declarations should be printed.
unsigned TerseOutput
Provide a 'terse' output.