29 #include "llvm/ADT/SmallPtrSet.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/SaveAndRestore.h"
32 #include "llvm/Support/raw_ostream.h"
34 using namespace clang;
43 cfgBuildOptions(buildOptions),
44 forcedBlkExprs(nullptr),
46 builtCompleteCFG(
false),
47 ReferencedBlockVars(nullptr),
48 ManagedAnalyses(nullptr)
57 forcedBlkExprs(nullptr),
59 builtCompleteCFG(
false),
60 ReferencedBlockVars(nullptr),
61 ManagedAnalyses(nullptr)
67 bool addImplicitDtors,
69 bool addTemporaryDtors,
71 bool synthesizeBodies,
72 bool addStaticInitBranch,
73 bool addCXXNewAllocator,
75 : Injector(injector), SynthesizeBodies(synthesizeBodies)
94 IsAutosynthesized =
false;
95 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
96 Stmt *Body = FD->getBody();
97 if (
auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
98 Body = CoroBody->getBody();
100 Stmt *SynthesizedBody =
102 if (SynthesizedBody) {
103 Body = SynthesizedBody;
104 IsAutosynthesized =
true;
109 else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
110 Stmt *Body = MD->getBody();
112 Stmt *SynthesizedBody =
114 if (SynthesizedBody) {
115 Body = SynthesizedBody;
116 IsAutosynthesized =
true;
120 }
else if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D))
121 return BD->getBody();
123 = dyn_cast_or_null<FunctionTemplateDecl>(D))
124 return FunTmpl->getTemplatedDecl()->getBody();
126 llvm_unreachable(
"unknown code decl");
148 return isa<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
153 return MD->getSelfDecl();
154 if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
156 for (
const auto &
I : BD->captures()) {
157 const VarDecl *VD =
I.getVariable();
172 if (!LC.capturesVariable())
175 VarDecl *VD = LC.getCapturedVar();
187 if (
const Expr *e = dyn_cast<Expr>(stmt))
188 stmt = e->IgnoreParens();
189 (void) (*forcedBlkExprs)[
stmt];
194 assert(forcedBlkExprs);
195 if (
const Expr *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());
236 if (!builtCompleteCFG) {
243 builtCompleteCFG =
true;
251 return completeCFG.get();
256 return cfgStmtMap.get();
260 return cfgStmtMap.get();
286 for (
const auto *
I : C->inits()) {
287 PM->addStmt(
I->getInit());
292 if (builtCompleteCFG)
305 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
312 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
314 AC = llvm::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
320 const CFGBlock *Blk,
unsigned Idx) {
321 return getLocationContextManager().
getStackFrame(
this, Parent, S, Blk, Idx);
327 const void *ContextData) {
339 if (!isa<NamespaceDecl>(Parent))
341 ND = cast<NamespaceDecl>(Parent);
349 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
350 return Manager->getLocationContextManager();
364 ID.AddPointer(parent);
384 template <
typename LOC,
typename DATA>
389 llvm::FoldingSetNodeID
ID;
390 LOC::Profile(ID, ctx, parent, d);
393 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
396 L =
new LOC(ctx, parent, d);
397 Contexts.InsertNode(L, InsertPos);
406 const CFGBlock *blk,
unsigned idx) {
407 llvm::FoldingSetNodeID
ID;
411 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
414 Contexts.InsertNode(L, InsertPos);
423 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
430 const void *ContextData) {
431 llvm::FoldingSetNodeID
ID;
435 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
439 Contexts.InsertNode(L, InsertPos);
481 switch (LCtx->getKind()) {
483 OS << Indent <<
'#' << Frame++ <<
' ';
484 cast<StackFrameContext>(LCtx)->
getDecl()->
print(OS, PP);
488 OS << Indent <<
" (scope)\n";
491 OS << Indent <<
" (block context: "
492 << cast<BlockInvocationContext>(LCtx)->getContextData()
508 class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
511 llvm::SmallPtrSet<const VarDecl*, 4> Visited;
512 llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
516 : BEVals(bevals), BC(bc) {}
518 void VisitStmt(
Stmt *
S) {
527 if (!VD->hasLocalStorage()) {
528 if (Visited.insert(VD).second)
529 BEVals.push_back(VD, BC);
543 Expr *Semantic = *it;
545 Semantic = OVE->getSourceExpr();
556 llvm::BumpPtrAllocator &A) {
565 for (
const auto &CI : BD->
captures()) {
570 FindBlockDeclRefExprsVals F(*BV, BC);
577 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
579 if (!ReferencedBlockVars)
580 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
584 return llvm::make_range(V->begin(), V->end());
587 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
588 if (!ManagedAnalyses)
601 delete forcedBlkExprs;
602 delete ReferencedBlockVars;
604 if (ManagedAnalyses) {
606 llvm::DeleteContainerSeconds(*M);
620 for (llvm::FoldingSet<LocationContext>::iterator
I = Contexts.begin(),
621 E = Contexts.end();
I !=
E; ) {
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
The base class of a hierarchy of objects representing analyses tied to AnalysisDeclContext.
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
BumpVector< const VarDecl * > DeclVec
ASTContext & getASTContext() const
void Profile(llvm::FoldingSetNodeID &ID) override
ArrayRef< Capture > captures() const
capture_const_range captures() const
CFGStmtMap * getCFGStmtMap()
Expr *const * semantics_iterator
Stmt - This represents one statement.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
Decl - This represents one declaration (or definition), e.g.
Defines the C++ template declaration subclasses.
bool isStdNamespace() const
NamespaceDecl - Represent a C++ namespace.
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool AddStaticInitBranches
Represents a C++ constructor within a class.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
ObjCMethodDecl - Represents an instance or class method declaration.
Describes how types, statements, expressions, and declarations should be printed. ...
const ImplicitParamDecl * getSelfDecl() const
Return the ImplicitParamDecl* associated with 'self' if this AnalysisDeclContext wraps an ObjCMethodD...
unsigned TerseOutput
Provide a 'terse' output.
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
synthetic_stmt_iterator synthetic_stmt_end() const
AnalysisDeclContext contains the context data for the function or method under analysis.
AnalysisDeclContext * getAnalysisDeclContext() const
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
AnalysisDeclContextManager(bool useUnoptimizedCFG=false, bool addImplicitDtors=false, bool addInitializers=false, bool addTemporaryDtors=false, bool addLifetime=false, bool synthesizeBodies=false, bool addStaticInitBranches=false, bool addCXXNewAllocator=true, CodeInjector *injector=nullptr)
bool synthesizeBodies() const
Return true if faux bodies should be synthesized for well-known functions.
~AnalysisDeclContextManager()
void setParent(const Stmt *S, const Stmt *Parent)
Manually sets the parent of S to Parent.
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
const LangOptions & getLangOpts() const
llvm::DenseMap< const void *, ManagedAnalysis * > ManagedAnalysisMap
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
semantics_iterator semantics_end()
bool isParentOf(const LocationContext *LC) const
Scope - A scope is a transient data structure that is used while parsing the program.
const Decl * getDecl() const
void clear()
Discard all previously created LocationContext objects.
detail::InMemoryDirectory::const_iterator I
ForcedBlkExprs ** forcedBlkExprs
CFGBlock - Represents a single basic block in a source-level CFG.
Stmt * getBody() const
Get the body of the Declaration.
AnalysisDeclContext * getContext(const Decl *D)
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Expr - This represents one expression.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
void Profile(llvm::FoldingSetNodeID &ID) override
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
DeclContext * getDeclContext()
bool inTopFrame() const override
Return true if the current LocationContext has no caller context.
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
DeclContext * getParent()
getParent - Returns the containing DeclContext.
const ScopeContext * getScope(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s)
const StackFrameContext * getStackFrame(LocationContext const *Parent, const Stmt *S, const CFGBlock *Blk, unsigned Idx)
const StackFrameContext * getStackFrame(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx)
CFG * getUnoptimizedCFG()
Return a version of the CFG without any edges pruned.
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Stmt * getParent(Stmt *) const
~LocationContextManager()
const StackFrameContext * getCurrentStackFrame() const
bool isValid() const
Return true if this is a valid SourceLocation object.
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
buildCFG - Builds a CFG from an AST.
ASTContext & getASTContext() const LLVM_READONLY
bool PruneTriviallyFalseEdges
Represents a static or instance method of a struct/union/class.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
const Decl * getDecl() const
virtual ~ManagedAnalysis()
const BlockDecl * getBlockDecl() const
void push_back(const_reference Elt, BumpVectorContext &C)
const LocationContext * getParent() const
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
static CFGStmtMap * Build(CFG *C, ParentMap *PM)
Returns a new CFGMap for the given CFG.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
static DeclVec * LazyInitializeReferencedDecls(const BlockDecl *BD, void *&Vec, llvm::BumpPtrAllocator &A)
void Profile(llvm::FoldingSetNodeID &ID) override
virtual ~LocationContext()
detail::InMemoryDirectory::const_iterator E
bool isBodyAutosynthesizedFromModelFile() const
Checks if the body of the Decl is generated by the BodyFarm from a model file.
semantics_iterator semantics_begin()
bool isLambda() const
Determine whether this class describes a lambda function object.
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
static bool isSelfDecl(const VarDecl *VD)
Returns true if.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
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...
PseudoConstantAnalysis * getPseudoConstantAnalysis()
const BlockInvocationContext * getBlockInvocationContext(AnalysisDeclContext *ctx, const LocationContext *parent, const BlockDecl *BD, const void *ContextData)
Represents a C++ struct/union/class.
void dumpCFG(bool ShowColors)
void registerForcedBlockExpression(const Stmt *stmt)
A reference to a declared variable, function, enum, etc.
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
const BlockInvocationContext * getBlockInvocationContext(const LocationContext *parent, const BlockDecl *BD, const void *ContextData)
ParentMap & getParentMap()
void clear()
Discard all previously created AnalysisDeclContexts.
SourceLocation getLocStart() const LLVM_READONLY
void dump(const LangOptions &LO, bool ShowColors) const
dump - A simple pretty printer of a CFG that outputs to stderr.
Declaration of a template function.
static BodyFarm & getBodyFarm(ASTContext &C, CodeInjector *injector=nullptr)
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D)
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, AnalysisDeclContext *ctx, const LocationContext *parent, const void *data)