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);
345 OS << FD->getQualifiedNameAsString();
351 for (
const auto &
P : FD->parameters()) {
352 if (
P != *FD->param_begin())
359 }
else if (isa<BlockDecl>(
D)) {
363 OS <<
"block (line: " <<
Loc.getLine() <<
", col: " <<
Loc.getColumn()
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()
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)
Describes how types, statements, expressions, and declarations should be printed.
unsigned TerseOutput
Provide a 'terse' output.