38 #include "llvm/ADT/DenseMap.h" 39 #include "llvm/ADT/FoldingSet.h" 40 #include "llvm/ADT/STLExtras.h" 41 #include "llvm/ADT/SmallPtrSet.h" 42 #include "llvm/ADT/iterator_range.h" 43 #include "llvm/Support/Allocator.h" 44 #include "llvm/Support/Casting.h" 45 #include "llvm/Support/Compiler.h" 46 #include "llvm/Support/ErrorHandling.h" 47 #include "llvm/Support/SaveAndRestore.h" 48 #include "llvm/Support/raw_ostream.h" 52 using namespace clang;
59 : Manager(Mgr), D(d), cfgBuildOptions(buildOptions) {
65 : Manager(Mgr), D(d) {
70 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
71 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
72 bool addLoopExit,
bool addScopes,
bool synthesizeBodies,
73 bool addStaticInitBranch,
bool addCXXNewAllocator,
74 bool addRichCXXConstructors,
bool markElidedCXXConstructors,
76 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
77 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();
99 if (Manager && Manager->synthesizeBodies()) {
100 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD);
101 if (SynthesizedBody) {
102 Body = SynthesizedBody;
103 IsAutosynthesized =
true;
108 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109 Stmt *Body = MD->getBody();
110 if (Manager && Manager->synthesizeBodies()) {
111 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
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");
139 Stmt *Body = getBody(Tmp);
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();
168 for (
const auto &LC : parent->
captures()) {
169 if (!LC.capturesVariable())
172 VarDecl *VD = LC.getCapturedVar();
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());
215 return getUnoptimizedCFG();
218 cfg =
CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
233 if (!builtCompleteCFG) {
237 CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
240 builtCompleteCFG =
true;
248 return completeCFG.get();
253 return cfgStmtMap.get();
255 if (
CFG *c = getCFG()) {
257 return cfgStmtMap.get();
267 if (
CFG *c = getCFG()) {
276 getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
282 if (
const auto *
C = dyn_cast<CXXConstructorDecl>(getDecl())) {
283 for (
const auto *I :
C->inits()) {
289 if (builtCompleteCFG)
302 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
309 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
311 AC = llvm::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
319 const CFGBlock *Blk,
unsigned Idx) {
320 return getLocationContextManager().
getStackFrame(
this, Parent, S, Blk, Idx);
326 const void *ContextData) {
338 if (!isa<NamespaceDecl>(
Parent))
340 ND = cast<NamespaceDecl>(
Parent);
348 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
349 return Manager->getLocationContextManager();
363 ID.AddPointer(parent);
368 Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index);
372 Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
376 Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
383 template <
typename LOC,
typename DATA>
388 llvm::FoldingSetNodeID
ID;
389 LOC::Profile(ID, ctx, parent, d);
392 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
395 L =
new LOC(ctx, parent, d);
396 Contexts.InsertNode(L, InsertPos);
405 const CFGBlock *blk,
unsigned idx) {
406 llvm::FoldingSetNodeID
ID;
410 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
413 Contexts.InsertNode(L, InsertPos);
422 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
429 const void *ContextData) {
430 llvm::FoldingSetNodeID
ID;
434 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
438 Contexts.InsertNode(L, InsertPos);
450 if (
const auto *SFC = dyn_cast<StackFrameContext>(LC))
482 raw_ostream &OS, StringRef Indent,
const char *NL,
const char *Sep,
483 std::function<
void(
const LocationContext *)> printMoreInfoPerContext)
const {
484 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
489 getAnalysisDeclContext()->getASTContext().getSourceManager();
493 switch (LCtx->getKind()) {
495 OS << Indent <<
'#' << Frame <<
' ';
497 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
498 OS <<
"Calling " << D->getQualifiedNameAsString();
500 OS <<
"Calling anonymous code";
501 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
507 OS <<
"Entering scope";
510 OS <<
"Invoking block";
511 if (
const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
512 OS <<
" defined at ";
519 printMoreInfoPerContext(LCtx);
524 dumpStack(llvm::errs());
533 class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
536 llvm::SmallPtrSet<const VarDecl *, 4> Visited;
537 llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
542 : BEVals(bevals), BC(bc) {}
544 void VisitStmt(
Stmt *S) {
552 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
553 if (!VD->hasLocalStorage()) {
554 if (Visited.insert(VD).second)
569 Expr *Semantic = *it;
570 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
571 Semantic = OVE->getSourceExpr();
583 llvm::BumpPtrAllocator &A) {
592 for (
const auto &CI : BD->
captures()) {
597 FindBlockDeclRefExprsVals F(*BV, BC);
604 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
606 if (!ReferencedBlockVars)
607 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
611 return llvm::make_range(V->begin(), V->end());
614 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
615 if (!ManagedAnalyses)
628 delete forcedBlkExprs;
629 delete ReferencedBlockVars;
631 if (ManagedAnalyses) {
633 llvm::DeleteContainerSeconds(*M);
645 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
646 E = Contexts.end(); I != E; ) {
Defines the clang::ASTContext interface.
const BlockDecl * getBlockDecl() const
The base class of a hierarchy of objects representing analyses tied to AnalysisDeclContext.
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.
Defines the SourceManager interface.
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, CodeInjector *injector=nullptr)
Decl - This represents one declaration (or definition), e.g.
Defines the C++ template declaration subclasses.
Stmt * getParent(Stmt *) const
Represent a C++ namespace.
capture_const_range captures() const
bool AddStaticInitBranches
Represents a variable declaration or definition.
Describes how types, statements, expressions, and declarations should be printed. ...
unsigned TerseOutput
Provide a 'terse' output.
bool isParentOf(const LocationContext *LC) const
void print(raw_ostream &OS, const SourceManager &SM) 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.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
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
const StackFrameContext * getStackFrame(AnalysisDeclContext *Ctx, LocationContext const *Parent, const Stmt *S, const CFGBlock *Blk, unsigned Idx)
ForcedBlkExprs ** forcedBlkExprs
Represents a single basic block in a source-level CFG.
AnalysisDeclContext * getContext(const Decl *D)
static void printLocation(raw_ostream &OS, const SourceManager &SM, SourceLocation SLoc)
bool isBodyAutosynthesizedFromModelFile() const
Checks if the body of the Decl is generated by the BodyFarm from a model file.
Pepresents a block literal declaration, which is like an unnamed FunctionDecl.
Expr - This represents one expression.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
BumpVector< const VarDecl * > DeclVec
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.
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)
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
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...
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
~LocationContextManager()
Encodes a location in the source.
static std::unique_ptr< CFG > buildCFG(const Decl *D, Stmt *AST, ASTContext *C, const BuildOptions &BO)
Builds a CFG from an AST.
SourceLocation getLocStart() 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.
bool isStdNamespace() const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
bool MarkElidedCXXConstructors
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 StackFrameContext * getStackFrame() const
const BlockInvocationContext * getBlockInvocationContext(AnalysisDeclContext *ctx, const LocationContext *parent, const BlockDecl *BD, const void *ContextData)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
llvm::DenseMap< const void *, ManagedAnalysis * > ManagedAnalysisMap
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
void dumpCFG(bool ShowColors)
synthetic_stmt_iterator synthetic_stmt_end() const
bool AddRichCXXConstructors
StringRef getName() const
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.
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D)
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, AnalysisDeclContext *ctx, const LocationContext *parent, const void *data)
Defines the LambdaCapture class.