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,
70 bool synthesizeBodies,
71 bool addStaticInitBranch,
72 bool addCXXNewAllocator,
74 : Injector(injector), SynthesizeBodies(synthesizeBodies)
85 llvm::DeleteContainerSeconds(
Contexts);
94 IsAutosynthesized =
false;
95 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
96 Stmt *Body = FD->getBody();
98 Stmt *SynthesizedBody =
100 if (SynthesizedBody) {
101 Body = SynthesizedBody;
102 IsAutosynthesized =
true;
107 else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
108 Stmt *Body = MD->getBody();
110 Stmt *SynthesizedBody =
112 if (SynthesizedBody) {
113 Body = SynthesizedBody;
114 IsAutosynthesized =
true;
118 }
else if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D))
119 return BD->getBody();
121 = dyn_cast_or_null<FunctionTemplateDecl>(D))
122 return FunTmpl->getTemplatedDecl()->getBody();
124 llvm_unreachable(
"unknown code decl");
141 return Tmp && Body->getLocStart().isValid();
146 return isa<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
151 return MD->getSelfDecl();
152 if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
154 for (
const auto &
I : BD->captures()) {
155 const VarDecl *VD =
I.getVariable();
170 if (!LC.capturesVariable())
173 VarDecl *VD = LC.getCapturedVar();
185 if (
const Expr *e = dyn_cast<Expr>(stmt))
186 stmt = e->IgnoreParens();
187 (void) (*forcedBlkExprs)[
stmt];
192 assert(forcedBlkExprs);
193 if (
const Expr *e = dyn_cast<Expr>(stmt))
194 stmt = e->IgnoreParens();
195 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
196 forcedBlkExprs->find(stmt);
197 assert(itr != forcedBlkExprs->end());
234 if (!builtCompleteCFG) {
241 builtCompleteCFG =
true;
249 return completeCFG.get();
254 return cfgStmtMap.get();
258 return cfgStmtMap.get();
284 for (
const auto *
I :
C->inits()) {
285 PM->addStmt(
I->getInit());
290 if (builtCompleteCFG)
303 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
318 const CFGBlock *Blk,
unsigned Idx) {
319 return getLocationContextManager().
getStackFrame(
this, Parent, S, Blk, Idx);
325 const void *ContextData) {
331 const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
337 if (!isa<NamespaceDecl>(Parent))
339 ND = cast<NamespaceDecl>(Parent);
347 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
348 return Manager->getLocationContextManager();
362 ID.AddPointer(parent);
382 template <
typename LOC,
typename DATA>
387 llvm::FoldingSetNodeID
ID;
391 LOC *L = cast_or_null<LOC>(
Contexts.FindNodeOrInsertPos(ID, InsertPos));
394 L =
new LOC(ctx, parent, d);
404 const CFGBlock *blk,
unsigned idx) {
405 llvm::FoldingSetNodeID
ID;
409 cast_or_null<StackFrameContext>(
Contexts.FindNodeOrInsertPos(ID, InsertPos));
421 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
428 const void *ContextData) {
429 llvm::FoldingSetNodeID
ID;
433 cast_or_null<BlockInvocationContext>(
Contexts.FindNodeOrInsertPos(ID,
479 switch (LCtx->getKind()) {
481 OS << Indent <<
'#' << Frame++ <<
' ';
482 cast<StackFrameContext>(LCtx)->
getDecl()->print(OS, PP);
486 OS << Indent <<
" (scope)\n";
489 OS << Indent <<
" (block context: "
490 << cast<BlockInvocationContext>(LCtx)->getContextData()
506 class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
509 llvm::SmallPtrSet<const VarDecl*, 4> Visited;
510 llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
514 : BEVals(bevals), BC(bc) {}
516 void VisitStmt(
Stmt *
S) {
517 for (
Stmt *Child : S->children())
525 if (!VD->hasLocalStorage()) {
526 if (Visited.insert(VD).second)
527 BEVals.push_back(VD, BC);
541 Expr *Semantic = *it;
543 Semantic = OVE->getSourceExpr();
554 llvm::BumpPtrAllocator &A) {
563 for (
const auto &CI : BD->
captures()) {
568 FindBlockDeclRefExprsVals F(*BV, BC);
575 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
577 if (!ReferencedBlockVars)
578 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
582 return llvm::make_range(V->begin(), V->end());
585 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
586 if (!ManagedAnalyses)
599 delete forcedBlkExprs;
600 delete ReferencedBlockVars;
602 if (ManagedAnalyses) {
604 llvm::DeleteContainerSeconds(*M);
610 llvm::DeleteContainerSeconds(Contexts);
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
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
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
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.
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.
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.
AnalysisDeclContextManager(bool useUnoptimizedCFG=false, bool addImplicitDtors=false, bool addInitializers=false, bool addTemporaryDtors=false, bool synthesizeBodies=false, bool addStaticInitBranches=false, bool addCXXNewAllocator=true, CodeInjector *injector=nullptr)
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 TemplateArgument * iterator
const StackFrameContext * getCurrentStackFrame() const
friend class AnalysisDeclContext
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
buildCFG - Builds a CFG from an AST.
bool PruneTriviallyFalseEdges
Represents a static or instance method of a struct/union/class.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
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.
SmallVector< Context, 8 > Contexts
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
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...
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.
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)