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/Casting.h"
44#include "llvm/Support/Compiler.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/SaveAndRestore.h"
47#include "llvm/Support/raw_ostream.h"
58 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
64 : ADCMgr(ADCMgr), D(D) {
69 ASTContext &ASTCtx,
bool useUnoptimizedCFG,
bool addImplicitDtors,
70 bool addInitializers,
bool addTemporaryDtors,
bool addLifetime,
71 bool addLoopExit,
bool addScopes,
bool synthesizeBodies,
72 bool addStaticInitBranch,
bool addCXXNewAllocator,
73 bool addRichCXXConstructors,
bool markElidedCXXConstructors,
75 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
76 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();
101 if (SynthesizedBody) {
102 Body = SynthesizedBody;
103 IsAutosynthesized =
true;
108 else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109 Stmt *Body = MD->getBody();
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");
145 return isa_and_nonnull<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();
156 return dyn_cast<ImplicitParamDecl>(VD);
160 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
168 for (
const auto &LC : parent->
captures()) {
169 if (!LC.capturesVariable())
174 return dyn_cast<ImplicitParamDecl>(VD);
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());
233 if (!builtCompleteCFG) {
239 builtCompleteCFG =
true;
247 return completeCFG.get();
252 return cfgStmtMap.get();
256 return cfgStmtMap.get();
281 if (
const auto *
C = dyn_cast<CXXConstructorDecl>(
getDecl())) {
282 for (
const auto *I :
C->inits()) {
283 PM->addStmt(I->getInit());
288 if (builtCompleteCFG)
295 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
302 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
304 AC = std::make_unique<AnalysisDeclContext>(
this, D, cfgBuildOptions);
313 unsigned BlockCount,
unsigned Index) {
314 return getLocationContextManager().
getStackFrame(
this, ParentLC, S, Blk,
326 const auto *ND = dyn_cast<NamespaceDecl>(DC);
331 if (!isa<NamespaceDecl>(
Parent))
333 ND = cast<NamespaceDecl>(
Parent);
336 return ND->isStdNamespace();
341 llvm::raw_string_ostream OS(Str);
344 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
345 OS << FD->getQualifiedNameAsString();
351 for (
const auto &
P : FD->parameters()) {
352 if (
P != *FD->param_begin())
359 }
else if (isa<BlockDecl>(D)) {
367 }
else if (
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
370 OS << (OMD->isInstanceMethod() ?
'-' :
'+') <<
'[';
372 if (
const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
373 OS << OID->getName();
374 }
else if (
const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
375 OS << OID->getName();
376 }
else if (
const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
377 if (OC->IsClassExtension()) {
378 OS << OC->getClassInterface()->getName();
380 OS << OC->getIdentifier()->getNameStart() <<
'('
381 << OC->getIdentifier()->getNameStart() <<
')';
383 }
else if (
const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
384 OS << OCD->getClassInterface()->getName() <<
'(' << OCD->getName() <<
')';
386 OS <<
' ' << OMD->getSelector().getAsString() <<
']';
395 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
396 return ADCMgr->getLocationContextManager();
410 ID.AddPointer(parent);
429 const CFGBlock *blk,
unsigned blockCount,
unsigned idx) {
430 llvm::FoldingSetNodeID ID;
434 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
437 Contexts.InsertNode(L, InsertPos);
445 llvm::FoldingSetNodeID ID;
449 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
453 Contexts.InsertNode(L, InsertPos);
465 if (
const auto *SFC = dyn_cast<StackFrameContext>(LC))
491 Out <<
SM.getExpansionLineNumber(Loc);
506 switch (LCtx->getKind()) {
508 Out <<
"\t#" << Frame <<
' ';
510 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
513 Out <<
"Calling anonymous code";
514 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
520 Out <<
"Invoking block";
521 if (
const Decl *D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
522 Out <<
" defined at line ";
532 unsigned int Space,
bool IsDot,
534 printMoreInfoPerContext)
const {
544 Indent(Out, Space, IsDot)
545 <<
"{ \"lctx_id\": " << LCtx->getID() <<
", \"location_context\": \"";
546 switch (LCtx->getKind()) {
548 Out <<
'#' << Frame <<
" Call\", \"calling\": \"";
550 if (
const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
551 Out << D->getQualifiedNameAsString();
553 Out <<
"anonymous code";
555 Out <<
"\", \"location\": ";
556 if (
const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
562 Out <<
", \"items\": ";
565 Out <<
"Invoking block\" ";
566 if (
const Decl *D = cast<BlockInvocationContext>(LCtx)->
getDecl()) {
567 Out <<
", \"location\": ";
574 printMoreInfoPerContext(LCtx);
577 if (LCtx->getParent())
591class FindBlockDeclRefExprsVals :
public StmtVisitor<FindBlockDeclRefExprsVals>{
600 : BEVals(bevals), BC(bc) {}
602 void VisitStmt(
Stmt *S) {
603 for (
auto *Child : S->children())
610 if (
const auto *VD = dyn_cast<VarDecl>(DR->
getDecl())) {
611 if (!VD->hasLocalStorage()) {
627 Expr *Semantic = *it;
628 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
629 Semantic = OVE->getSourceExpr();
641 llvm::BumpPtrAllocator &A) {
650 for (
const auto &CI : BD->
captures()) {
655 FindBlockDeclRefExprsVals F(*BV, BC);
662llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
664 if (!ReferencedBlockVars)
665 ReferencedBlockVars =
new llvm::DenseMap<const BlockDecl*,void*>();
669 return llvm::make_range(
V->begin(),
V->end());
672std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(
const void *tag) {
673 if (!ManagedAnalyses)
686 delete forcedBlkExprs;
687 delete ReferencedBlockVars;
698 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
699 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, 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
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
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()
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.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
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.
@ C
Languages that the frontend can parse and compile.
void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, const SourceManager &SM, bool AddBraces=true)
Describes how types, statements, expressions, and declarations should be printed.
unsigned TerseOutput
Provide a 'terse' output.