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 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
68 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
69 bool addLoopExit,
bool synthesizeBodies,
bool addStaticInitBranch,
71 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
72 SynthesizeBodies(synthesizeBodies) {
86 IsAutosynthesized =
false;
87 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
88 Stmt *Body = FD->getBody();
89 if (
auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
90 Body = CoroBody->getBody();
91 if (Manager && Manager->synthesizeBodies()) {
92 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD);
93 if (SynthesizedBody) {
94 Body = SynthesizedBody;
95 IsAutosynthesized =
true;
100 else if (
const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
101 Stmt *Body = MD->getBody();
102 if (Manager && Manager->synthesizeBodies()) {
103 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
104 if (SynthesizedBody) {
105 Body = SynthesizedBody;
106 IsAutosynthesized =
true;
110 }
else if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D))
111 return BD->getBody();
113 = dyn_cast_or_null<FunctionTemplateDecl>(D))
114 return FunTmpl->getTemplatedDecl()->getBody();
116 llvm_unreachable(
"unknown code decl");
132 Stmt *Body = getBody(Tmp);
138 return isa<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
143 return MD->getSelfDecl();
144 if (
const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
146 for (
const auto &I : BD->captures()) {
147 const VarDecl *VD = I.getVariable();
162 if (!LC.capturesVariable())
165 VarDecl *VD = LC.getCapturedVar();
177 if (
const Expr *e = dyn_cast<Expr>(stmt))
178 stmt = e->IgnoreParens();
179 (void) (*forcedBlkExprs)[
stmt];
184 assert(forcedBlkExprs);
185 if (
const Expr *e = dyn_cast<Expr>(stmt))
186 stmt = e->IgnoreParens();
187 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
188 forcedBlkExprs->find(stmt);
189 assert(itr != forcedBlkExprs->end());
208 return getUnoptimizedCFG();
211 cfg =
CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
226 if (!builtCompleteCFG) {
230 CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
233 builtCompleteCFG =
true;
241 return completeCFG.get();
246 return cfgStmtMap.get();
248 if (
CFG *c = getCFG()) {
250 return cfgStmtMap.get();
260 if (
CFG *c = getCFG()) {
269 getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
276 for (
const auto *I :
C->inits()) {
282 if (builtCompleteCFG)
295 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
302 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
304 AC = llvm::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
312 const CFGBlock *Blk,
unsigned Idx) {
313 return getLocationContextManager().
getStackFrame(
this, Parent, S, Blk, Idx);
319 const void *ContextData) {
331 if (!isa<NamespaceDecl>(
Parent))
333 ND = cast<NamespaceDecl>(
Parent);
341 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
342 return Manager->getLocationContextManager();
356 ID.AddPointer(parent);
361 Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index);
365 Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
369 Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
376 template <
typename LOC,
typename DATA>
381 llvm::FoldingSetNodeID
ID;
382 LOC::Profile(ID, ctx, parent, d);
385 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
388 L =
new LOC(ctx, parent, d);
389 Contexts.InsertNode(L, InsertPos);
398 const CFGBlock *blk,
unsigned idx) {
399 llvm::FoldingSetNodeID
ID;
403 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
406 Contexts.InsertNode(L, InsertPos);
415 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
422 const void *ContextData) {
423 llvm::FoldingSetNodeID
ID;
427 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
431 Contexts.InsertNode(L, InsertPos);
451 return getCurrentStackFrame()->inTopFrame();
467 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
473 switch (LCtx->getKind()) {
475 OS << Indent <<
'#' << Frame++ <<
' ';
476 cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP);
480 OS << Indent <<
" (scope)\n";
483 OS << Indent <<
" (block context: " 484 << cast<BlockInvocationContext>(LCtx)->getContextData()
492 dumpStack(llvm::errs());
500 class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
503 llvm::SmallPtrSet<const VarDecl*, 4> Visited;
504 llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
508 : BEVals(bevals), BC(bc) {}
510 void VisitStmt(
Stmt *S) {
519 if (!VD->hasLocalStorage()) {
520 if (Visited.insert(VD).second)
535 Expr *Semantic = *it;
537 Semantic = OVE->getSourceExpr();
548 llvm::BumpPtrAllocator &A) {
557 for (
const auto &CI : BD->
captures()) {
562 FindBlockDeclRefExprsVals F(*BV, BC);
569 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
571 if (!ReferencedBlockVars)
572 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
576 return llvm::make_range(V->begin(), V->end());
579 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
580 if (!ManagedAnalyses)
593 delete forcedBlkExprs;
594 delete ReferencedBlockVars;
596 if (ManagedAnalyses) {
598 llvm::DeleteContainerSeconds(*M);
610 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
611 E = Contexts.end(); I != E; ) {
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
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.
BumpVector< const VarDecl * > DeclVec
void Profile(llvm::FoldingSetNodeID &ID) override
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Stmt * getBody() const
Get the body of the Declaration.
CFGStmtMap * getCFGStmtMap()
Expr *const * semantics_iterator
Stmt - This represents one statement.
Decl - This represents one declaration (or definition), e.g.
Defines the C++ template declaration subclasses.
Stmt * getParent(Stmt *) const
NamespaceDecl - Represent a C++ namespace.
capture_const_range captures() const
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. ...
unsigned TerseOutput
Provide a 'terse' output.
bool isParentOf(const LocationContext *LC) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
void addStmt(Stmt *S)
Adds and/or updates the parent/child-relations of the complete stmt tree of S.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
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.
llvm::DenseMap< const void *, ManagedAnalysis * > ManagedAnalysisMap
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
const StackFrameContext * getCurrentStackFrame() const
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
semantics_iterator semantics_end()
const LocationContext * getParent() const
bool isLambda() const
Determine whether this class describes a lambda function object.
Scope - A scope is a transient data structure that is used while parsing the program.
void clear()
Discard all previously created LocationContext objects.
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
ForcedBlkExprs ** forcedBlkExprs
CFGBlock - Represents a single basic block in a source-level CFG.
AnalysisDeclContext * getContext(const Decl *D)
bool isBodyAutosynthesizedFromModelFile() const
Checks if the body of the Decl is generated by the BodyFarm from a model file.
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()
BodyFarm & getBodyFarm()
Get a reference to {.
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
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)
CFG::BuildOptions & getCFGBuildOptions()
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.
const ImplicitParamDecl * getSelfDecl() const
Return the ImplicitParamDecl* associated with 'self' if this AnalysisDeclContext wraps an ObjCMethodD...
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.
~LocationContextManager()
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.
bool isStdNamespace() const
virtual ~ManagedAnalysis()
void push_back(const_reference Elt, BumpVectorContext &C)
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
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...
ArrayRef< Capture > captures() const
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()
semantics_iterator semantics_begin()
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)
synthetic_stmt_iterator synthetic_stmt_end() const
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
void registerForcedBlockExpression(const Stmt *stmt)
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
A reference to a declared variable, function, enum, etc.
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
const LangOptions & getLangOpts() const
Declaration of a template function.
AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG=false, bool addImplicitDtors=false, bool addInitializers=false, bool addTemporaryDtors=false, bool addLifetime=false, bool addLoopExit=false, bool synthesizeBodies=false, bool addStaticInitBranches=false, bool addCXXNewAllocator=true, 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)