37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/FoldingSet.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallPtrSet.h"
41#include "llvm/ADT/iterator_range.h"
42#include "llvm/Support/Allocator.h"
43#include "llvm/Support/Compiler.h"
44#include "llvm/Support/ErrorHandling.h"
45#include "llvm/Support/SaveAndRestore.h"
46#include "llvm/Support/raw_ostream.h"
57 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
58 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
63 : ADCMgr(ADCMgr), D(D) {
64 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
68 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
69 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
71 bool addStaticInitBranch,
bool addCXXNewAllocator,
72 bool addRichCXXConstructors,
bool markElidedCXXConstructors,
73 bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector)
74 : Injector(
std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()),
76 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
77 cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
78 cfgBuildOptions.AddInitializers = addInitializers;
79 cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
80 cfgBuildOptions.AddLifetime = addLifetime;
81 cfgBuildOptions.AddLoopExit = addLoopExit;
82 cfgBuildOptions.AddScopes = addScopes;
83 cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
84 cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
85 cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
86 cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
87 cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
93 IsAutosynthesized =
false;
94 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
95 Stmt *Body = FD->getBody();
96 if (
auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
97 Body = CoroBody->getBody();
98 if (ADCMgr && ADCMgr->synthesizeBodies()) {
99 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
100 if (SynthesizedBody) {
101 Body = SynthesizedBody;
102 IsAutosynthesized =
true;
107 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
108 Stmt *Body = MD->getBody();
109 if (ADCMgr && ADCMgr->synthesizeBodies()) {
110 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
111 if (SynthesizedBody) {
112 Body = SynthesizedBody;
113 IsAutosynthesized =
true;
117 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D))
118 return BD->getBody();
119 else if (
const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
120 return FunTmpl->getTemplatedDecl()->getBody();
121 else if (
const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
122 if (VD->isFileVarDecl()) {
123 return const_cast<Stmt *
>(dyn_cast_or_null<Stmt>(VD->getInit()));
127 llvm_unreachable(
"unknown code decl");
149 return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
153 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
154 return MD->getSelfDecl();
155 if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
157 for (
const auto &I : BD->captures()) {
158 const VarDecl *VD = I.getVariable();
160 return dyn_cast<ImplicitParamDecl>(VD);
164 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
172 for (
const auto &LC : parent->
captures()) {
173 if (!LC.capturesVariable())
178 return dyn_cast<ImplicitParamDecl>(VD);
188 if (
const auto *e = dyn_cast<Expr>(
stmt))
189 stmt = e->IgnoreParens();
190 (void) (*forcedBlkExprs)[
stmt];
195 assert(forcedBlkExprs);
196 if (
const auto *e = dyn_cast<Expr>(
stmt))
197 stmt = e->IgnoreParens();
198 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
199 forcedBlkExprs->find(
stmt);
200 assert(itr != forcedBlkExprs->end());
218 if (!cfgBuildOptions.PruneTriviallyFalseEdges)
237 if (!builtCompleteCFG) {
238 SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
false);
243 builtCompleteCFG =
true;
251 return completeCFG.get();
285 if (
const auto *
C = dyn_cast<CXXConstructorDecl>(
getDecl())) {
286 for (
const auto *I :
C->inits()) {
287 PM->addStmt(I->getInit());
292 if (builtCompleteCFG)
299 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
306 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
308 AC = std::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
317 unsigned BlockCount,
unsigned Index) {
318 return getStackFrameManager().getStackFrame(
this, ParentSF,
Data, E, Blk,
324 const auto *ND = dyn_cast<NamespaceDecl>(DC);
334 return ND->isStdNamespace();
339 llvm::raw_string_ostream OS(Str);
342 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
343 OS << FD->getQualifiedNameAsString();
349 for (
const auto &P : FD->parameters()) {
350 if (P != *FD->param_begin())
365 }
else if (
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
368 OS << (OMD->isInstanceMethod() ?
'-' :
'+') <<
'[';
370 if (
const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
371 OS << OID->getName();
372 }
else if (
const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
373 OS << OID->getName();
374 }
else if (
const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
375 if (OC->IsClassExtension()) {
376 OS << OC->getClassInterface()->getName();
378 OS << OC->getIdentifier()->getNameStart() <<
'('
379 << OC->getIdentifier()->getNameStart() <<
')';
381 }
else if (
const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
382 OS << OCD->getClassInterface()->getName() <<
'(' << OCD->getName() <<
')';
384 OS <<
' ' << OMD->getSelector().getAsString() <<
']';
392 "Cannot create StackFrames without an AnalysisDeclContextManager!");
393 return ADCMgr->getStackFrameManager();
411 const Expr *E,
const CFGBlock *B,
unsigned BlockCount,
unsigned StmtIdx) {
412 llvm::FoldingSetNodeID ID;
415 StackFrame *SF = Frames.FindNodeOrInsertPos(ID, InsertPos);
417 SF =
new StackFrame(Ctx, Parent,
Data, E, B, BlockCount, StmtIdx, ++NewID);
418 Frames.InsertNode(SF, InsertPos);
428 return llvm::any_of(SF->
parents(),
429 [
this](
const StackFrame &A) { return &A == this; });
435 Out <<
SM.getExpansionLineNumber(Loc);
449 Out <<
"\t#" << Idx <<
' ';
450 if (
const auto *D = dyn_cast<NamedDecl>(SF.getDecl()))
453 Out <<
"Calling anonymous code";
454 if (
const Expr *E = SF.getCallSite()) {
463 raw_ostream &Out,
const char *NL,
unsigned int Space,
bool IsDot,
474 <<
"{ \"lctx_id\": " << SF.getID() <<
", \"location_context\": \"";
475 Out <<
'#' << Idx <<
" Call\", \"calling\": \"";
476 if (
const auto *D = dyn_cast<NamedDecl>(SF.getDecl()))
477 Out << D->getQualifiedNameAsString();
479 Out <<
"anonymous code";
481 Out <<
"\", \"location\": ";
482 if (
const Expr *E = SF.getCallSite()) {
488 Out <<
", \"items\": ";
490 printMoreInfoPerStackFrame(&SF);
507class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
516 : BEVals(bevals), BC(bc) {}
518 void VisitStmt(
Stmt *S) {
524 void VisitDeclRefExpr(DeclRefExpr *DR) {
526 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
527 if (!VD->hasLocalStorage()) {
528 if (Visited.insert(VD).second)
534 void VisitBlockExpr(BlockExpr *BR) {
540 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
543 Expr *Semantic = *it;
544 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
545 Semantic = OVE->getSourceExpr();
557 llvm::BumpPtrAllocator &A) {
566 for (
const auto &CI : BD->
captures()) {
571 FindBlockDeclRefExprsVals F(*BV, BC);
578llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
580 if (!ReferencedBlockVars)
581 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
585 return llvm::make_range(
V->begin(),
V->end());
588std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
589 if (!ManagedAnalyses)
602 delete forcedBlkExprs;
603 delete ReferencedBlockVars;
610 for (llvm::FoldingSet<StackFrame>::iterator I = Frames.begin(),
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.
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 CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
ParentMap & getParentMap()
const Decl * getDecl() const
const CFGStmtMap * getCFGStmtMap()
static bool isInStdNamespace(const Decl *D)
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
const ImplicitParamDecl * getSelfDecl() const
ASTContext & getASTContext() const
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
bool isBodyAutosynthesized() const
CFG * getUnoptimizedCFG()
const StackFrame * getStackFrame(const StackFrame *ParentSF, const void *Data, const Expr *E, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
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
void push_back(const_reference Elt, BumpVectorContext &C)
Represents a single basic block in a source-level 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.
This represents one expression.
Represents a function declaration or definition.
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.
void clear()
Discard all previously created StackFrame objects.
const StackFrame * getStackFrame(AnalysisDeclContext *ADC, const StackFrame *ParentSF, const void *Data, const Expr *E, const CFGBlock *Block, unsigned BlockCount, unsigned StmtIdx)
Obtain a context of the call stack using its parent context.
It represents a stack frame of the call stack.
LLVM_DUMP_METHOD void dump() const
StackFrame(AnalysisDeclContext *ADC, const StackFrame *Parent, const void *Data, const Expr *E, const CFGBlock *Block, unsigned BlockCount, unsigned Index, int64_t ID)
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const
Prints out the call stack.
bool isParentOf(const StackFrame *SF) const
void Profile(llvm::FoldingSetNodeID &ID)
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const StackFrame *)> printMoreInfoPerStackFrame=[](const StackFrame *) {}) const
Prints out the call stack in json format.
llvm::iterator_range< parent_iterator > parents() const
Iterates over the strict ancestors of this frame, i.e.
const StackFrame * getParent() const
It might return null.
llvm::iterator_range< parent_iterator > parentsIncludingSelf() const
Iterates over this frame followed by all of its ancestors.
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.