37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/FoldingSet.h"
39#include "llvm/ADT/SmallPtrSet.h"
40#include "llvm/ADT/iterator_range.h"
41#include "llvm/Support/Allocator.h"
42#include "llvm/Support/Compiler.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/SaveAndRestore.h"
45#include "llvm/Support/raw_ostream.h"
56 : ADCMgr(ADCMgr),
D(
D), cfgBuildOptions(Options) {
62 : ADCMgr(ADCMgr),
D(
D) {
67 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
68 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
69 bool addLoopExit,
bool addScopes,
bool synthesizeBodies,
70 bool addStaticInitBranch,
bool addCXXNewAllocator,
71 bool addRichCXXConstructors,
bool markElidedCXXConstructors,
72 bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector)
73 : Injector(
std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()),
74 SynthesizeBodies(synthesizeBodies) {
92 IsAutosynthesized =
false;
93 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
94 Stmt *Body = FD->getBody();
95 if (
auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
96 Body = CoroBody->getBody();
99 if (SynthesizedBody) {
100 Body = SynthesizedBody;
101 IsAutosynthesized =
true;
106 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
107 Stmt *Body = MD->getBody();
110 if (SynthesizedBody) {
111 Body = SynthesizedBody;
112 IsAutosynthesized =
true;
116 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D))
117 return BD->getBody();
118 else if (
const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
119 return FunTmpl->getTemplatedDecl()->getBody();
121 llvm_unreachable(
"unknown code decl");
143 return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->
getName() ==
"self";
147 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
148 return MD->getSelfDecl();
149 if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
151 for (
const auto &I : BD->captures()) {
152 const VarDecl *VD = I.getVariable();
154 return dyn_cast<ImplicitParamDecl>(VD);
158 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
166 for (
const auto &LC : parent->
captures()) {
167 if (!LC.capturesVariable())
172 return dyn_cast<ImplicitParamDecl>(VD);
182 if (
const auto *e = dyn_cast<Expr>(
stmt))
183 stmt = e->IgnoreParens();
184 (void) (*forcedBlkExprs)[
stmt];
189 assert(forcedBlkExprs);
190 if (
const auto *e = dyn_cast<Expr>(
stmt))
191 stmt = e->IgnoreParens();
192 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
193 forcedBlkExprs->find(
stmt);
194 assert(itr != forcedBlkExprs->end());
231 if (!builtCompleteCFG) {
237 builtCompleteCFG =
true;
245 return completeCFG.get();
250 return cfgStmtMap.get();
254 return cfgStmtMap.get();
279 if (
const auto *
C = dyn_cast<CXXConstructorDecl>(
getDecl())) {
280 for (
const auto *I :
C->inits()) {
281 PM->addStmt(I->getInit());
286 if (builtCompleteCFG)
293 if (
const auto *FD = dyn_cast<FunctionDecl>(
D)) {
300 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[
D];
302 AC = std::make_unique<AnalysisDeclContext>(
this,
D, cfgBuildOptions);
311 unsigned BlockCount,
unsigned Index) {
312 return getLocationContextManager().
getStackFrame(
this, ParentLC, S, Blk,
324 const auto *ND = dyn_cast<NamespaceDecl>(DC);
329 if (!isa<NamespaceDecl>(
Parent))
331 ND = cast<NamespaceDecl>(
Parent);
334 return ND->isStdNamespace();
339 llvm::raw_string_ostream OS(Str);
343 OS << FD->getQualifiedNameAsString();
349 for (
const auto &
P : FD->parameters()) {
350 if (
P != *FD->param_begin())
357 }
else if (isa<BlockDecl>(
D)) {
361 OS <<
"block (line: " <<
Loc.getLine() <<
", col: " <<
Loc.getColumn()
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() <<
']';
393 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
394 return ADCMgr->getLocationContextManager();
408 ID.AddPointer(parent);
427 const CFGBlock *blk,
unsigned blockCount,
unsigned idx) {
428 llvm::FoldingSetNodeID ID;
432 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
435 Contexts.InsertNode(L, InsertPos);
443 llvm::FoldingSetNodeID ID;
447 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
451 Contexts.InsertNode(L, InsertPos);
463 if (
const auto *SFC = dyn_cast<StackFrameContext>(LC))
489 Out <<
SM.getExpansionLineNumber(
Loc);
504 switch (LCtx->getKind()) {
506 Out <<
"\t#" << Frame <<
' ';
508 if (
const auto *
D = dyn_cast<NamedDecl>(LCtx->getDecl()))
511 Out <<
"Calling anonymous code";
512 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
518 Out <<
"Invoking block";
519 if (
const Decl *
D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
520 Out <<
" defined at line ";
530 unsigned int Space,
bool IsDot,
532 printMoreInfoPerContext)
const {
542 Indent(Out, Space, IsDot)
543 <<
"{ \"lctx_id\": " << LCtx->getID() <<
", \"location_context\": \"";
544 switch (LCtx->getKind()) {
546 Out <<
'#' << Frame <<
" Call\", \"calling\": \"";
548 if (
const auto *
D = dyn_cast<NamedDecl>(LCtx->getDecl()))
549 Out <<
D->getQualifiedNameAsString();
551 Out <<
"anonymous code";
553 Out <<
"\", \"location\": ";
554 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
560 Out <<
", \"items\": ";
563 Out <<
"Invoking block\" ";
564 if (
const Decl *
D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
565 Out <<
", \"location\": ";
572 printMoreInfoPerContext(LCtx);
575 if (LCtx->getParent())
589class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
598 : BEVals(bevals), BC(bc) {}
600 void VisitStmt(
Stmt *S) {
601 for (
auto *Child : S->children())
608 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
609 if (!VD->hasLocalStorage()) {
625 Expr *Semantic = *it;
626 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
627 Semantic = OVE->getSourceExpr();
639 llvm::BumpPtrAllocator &A) {
648 for (
const auto &CI : BD->
captures()) {
653 FindBlockDeclRefExprsVals F(*BV, BC);
660llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
662 if (!ReferencedBlockVars)
663 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
667 return llvm::make_range(
V->begin(),
V->end());
670std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
671 if (!ManagedAnalyses)
684 delete forcedBlkExprs;
685 delete ReferencedBlockVars;
696 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
697 E = Contexts.end(); I !=
E; ) {
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)
BumpVector< const VarDecl * > DeclVec
llvm::DenseMap< const void *, std::unique_ptr< ManagedAnalysis > > ManagedAnalysisMap
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.
llvm::DenseSet< const void * > Visited
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.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
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)
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 BlockInvocationContext * getBlockInvocationContext(const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)
Obtain a context of the block invocation using its parent context.
CFGStmtMap * getCFGStmtMap()
const CFGBlock * getBlockForRegisteredExpression(const Stmt *stmt)
ParentMap & getParentMap()
const Decl * getDecl() const
static bool isInStdNamespace(const Decl *D)
CFGReverseBlockReachabilityAnalysis * getCFGReachablityAnalysis()
const ImplicitParamDecl * getSelfDecl() const
const StackFrameContext * getStackFrame(LocationContext const *ParentLC, const Stmt *S, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
ASTContext & getASTContext() const
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
bool isBodyAutosynthesized() const
CFG * getUnoptimizedCFG()
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
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const BlockDecl * getBlockDecl() const
It represents a block invocation (based on BlockCall).
void Profile(llvm::FoldingSetNodeID &ID) override
Stmt * getBody(const FunctionDecl *D)
Factory method for creating bodies for ordinary functions.
void push_back(const_reference Elt, BumpVectorContext &C)
Represents a single basic block in a source-level CFG.
static CFGStmtMap * Build(CFG *C, ParentMap *PM)
Returns a new CFGMap for the given CFG.
bool PruneTriviallyFalseEdges
bool AddStaticInitBranches
ForcedBlkExprs ** forcedBlkExprs
bool AddRichCXXConstructors
bool AddVirtualBaseBranches
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
bool MarkElidedCXXConstructors
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
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.
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.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
Represents a function declaration or definition.
~LocationContextManager()
const StackFrameContext * getStackFrame(AnalysisDeclContext *ADC, const LocationContext *ParentLC, const Stmt *S, const CFGBlock *Block, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
void clear()
Discard all previously created LocationContext objects.
const BlockInvocationContext * getBlockInvocationContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)
Obtain a context of the block invocation using its parent context.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, AnalysisDeclContext *ctx, const LocationContext *parent, const void *data)
const LocationContext * getParent() const
It might return null.
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const
Prints out the call stack.
LLVM_DUMP_METHOD void dump() const
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
virtual ~LocationContext()
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
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.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
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.
It represents a stack frame of the call stack (based on CallEvent).
void Profile(llvm::FoldingSetNodeID &ID) override
bool inTopFrame() const override
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.
void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, const SourceManager &SM, bool AddBraces=true)
int const char * function
Describes how types, statements, expressions, and declarations should be printed.
unsigned TerseOutput
Provide a 'terse' output.