clang: lib/Analysis/AnalysisDeclContext.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

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"

48#include

49#include

50

51using namespace clang;

52

53using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr>;

54

58 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {

60}

61

64 : ADCMgr(ADCMgr), D(D) {

66}

67

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,

74 bool addVirtualBaseBranches, CodeInjector *injector)

75 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),

76 SynthesizeBodies(synthesizeBodies) {

81 cfgBuildOptions.AddLifetime = addLifetime;

82 cfgBuildOptions.AddLoopExit = addLoopExit;

83 cfgBuildOptions.AddScopes = addScopes;

89}

90

92

94 IsAutosynthesized = false;

95 if (const auto *FD = dyn_cast(D)) {

96 Stmt *Body = FD->getBody();

97 if (auto *CoroBody = dyn_cast_or_null(Body))

98 Body = CoroBody->getBody();

101 if (SynthesizedBody) {

102 Body = SynthesizedBody;

103 IsAutosynthesized = true;

104 }

105 }

106 return Body;

107 }

108 else if (const auto *MD = dyn_cast(D)) {

109 Stmt *Body = MD->getBody();

112 if (SynthesizedBody) {

113 Body = SynthesizedBody;

114 IsAutosynthesized = true;

115 }

116 }

117 return Body;

118 } else if (const auto *BD = dyn_cast(D))

119 return BD->getBody();

120 else if (const auto *FunTmpl = dyn_cast_or_null(D))

121 return FunTmpl->getTemplatedDecl()->getBody();

122

123 llvm_unreachable("unknown code decl");

124}

125

127 bool Tmp;

129}

130

132 bool Tmp;

134 return Tmp;

135}

136

138 bool Tmp;

141}

142

143

145 return isa_and_nonnull(VD) && VD->getName() == "self";

146}

147

149 if (const auto *MD = dyn_cast(D))

150 return MD->getSelfDecl();

151 if (const auto *BD = dyn_cast(D)) {

152

153 for (const auto &I : BD->captures()) {

154 const VarDecl *VD = I.getVariable();

156 return dyn_cast(VD);

157 }

158 }

159

160 auto *CXXMethod = dyn_cast(D);

161 if (!CXXMethod)

162 return nullptr;

163

166 return nullptr;

167

168 for (const auto &LC : parent->captures()) {

169 if (!LC.capturesVariable())

170 continue;

171

172 ValueDecl *VD = LC.getCapturedVar();

173 if (isSelfDecl(dyn_cast(VD)))

174 return dyn_cast(VD);

175 }

176

177 return nullptr;

178}

179

181 if (!forcedBlkExprs)

183

184 if (const auto *e = dyn_cast(stmt))

185 stmt = e->IgnoreParens();

186 (void) (*forcedBlkExprs)[stmt];

187}

188

191 assert(forcedBlkExprs);

192 if (const auto *e = dyn_cast(stmt))

193 stmt = e->IgnoreParens();

194 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =

195 forcedBlkExprs->find(stmt);

196 assert(itr != forcedBlkExprs->end());

197 return itr->second;

198}

199

200

201

203 if (!TheCFG)

204 return;

205

208 I != E; ++I) {

210 }

211}

212

216

217 if (!builtCFG) {

219

220

221 builtCFG = true;

222

223 if (PM)

225

226

228 }

229 return cfg.get();

230}

231

233 if (!builtCompleteCFG) {

235 completeCFG =

237

238

239 builtCompleteCFG = true;

240

241 if (PM)

243

244

246 }

247 return completeCFG.get();

248}

249

251 if (cfgStmtMap)

252 return cfgStmtMap.get();

253

256 return cfgStmtMap.get();

257 }

258

259 return nullptr;

260}

261

263 if (CFA)

264 return CFA.get();

265

268 return CFA.get();

269 }

270

271 return nullptr;

272}

273

276}

277

279 if (!PM) {

281 if (const auto *C = dyn_cast(getDecl())) {

282 for (const auto *I : C->inits()) {

283 PM->addStmt(I->getInit());

284 }

285 }

286 if (builtCFG)

288 if (builtCompleteCFG)

290 }

291 return *PM;

292}

293

295 if (const auto *FD = dyn_cast(D)) {

296

297

298 FD->hasBody(FD);

299 D = FD;

300 }

301

302 std::unique_ptr &AC = Contexts[D];

303 if (!AC)

304 AC = std::make_unique(this, D, cfgBuildOptions);

305 return AC.get();

306}

307

309

313 unsigned BlockCount, unsigned Index) {

314 return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,

315 BlockCount, Index);

316}

317

322}

323

326 const auto *ND = dyn_cast(DC);

327 if (!ND)

328 return false;

329

331 if (!isa(Parent))

332 break;

333 ND = cast(Parent);

334 }

335

336 return ND->isStdNamespace();

337}

338

340 std::string Str;

341 llvm::raw_string_ostream OS(Str);

343

344 if (const FunctionDecl *FD = dyn_cast(D)) {

345 OS << FD->getQualifiedNameAsString();

346

347

348

350 OS << '(';

351 for (const auto &P : FD->parameters()) {

352 if (P != *FD->param_begin())

353 OS << ", ";

354 OS << P->getType();

355 }

356 OS << ')';

357 }

358

359 } else if (isa(D)) {

361

363 OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()

364 << ')';

365 }

366

367 } else if (const ObjCMethodDecl *OMD = dyn_cast(D)) {

368

369

370 OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';

371 const DeclContext *DC = OMD->getDeclContext();

372 if (const auto *OID = dyn_cast(DC)) {

373 OS << OID->getName();

374 } else if (const auto *OID = dyn_cast(DC)) {

375 OS << OID->getName();

376 } else if (const auto *OC = dyn_cast(DC)) {

377 if (OC->IsClassExtension()) {

378 OS << OC->getClassInterface()->getName();

379 } else {

380 OS << OC->getIdentifier()->getNameStart() << '('

381 << OC->getIdentifier()->getNameStart() << ')';

382 }

383 } else if (const auto *OCD = dyn_cast(DC)) {

384 OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';

385 }

386 OS << ' ' << OMD->getSelector().getAsString() << ']';

387 }

388

389 return Str;

390}

391

393 assert(

394 ADCMgr &&

395 "Cannot create LocationContexts without an AnalysisDeclContextManager!");

396 return ADCMgr->getLocationContextManager();

397}

398

399

400

401

402

407 const void *data) {

408 ID.AddInteger(ck);

409 ID.AddPointer(ctx);

410 ID.AddPointer(parent);

411 ID.AddPointer(data);

412}

413

416 BlockCount, Index);

417}

418

421}

422

423

424

425

426

429 const CFGBlock *blk, unsigned blockCount, unsigned idx) {

430 llvm::FoldingSetNodeID ID;

432 void *InsertPos;

433 auto *L =

434 cast_or_null(Contexts.FindNodeOrInsertPos(ID, InsertPos));

435 if (!L) {

436 L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);

437 Contexts.InsertNode(L, InsertPos);

438 }

439 return L;

440}

441

445 llvm::FoldingSetNodeID ID;

447 void *InsertPos;

448 auto *L =

449 cast_or_null(Contexts.FindNodeOrInsertPos(ID,

450 InsertPos));

451 if (!L) {

453 Contexts.InsertNode(L, InsertPos);

454 }

455 return L;

456}

457

458

459

460

461

464 while (LC) {

465 if (const auto *SFC = dyn_cast(LC))

466 return SFC;

468 }

469 return nullptr;

470}

471

474}

475

477 do {

480 return true;

481 else

483 } while (LC);

484

485 return false;

486}

487

491 Out << SM.getExpansionLineNumber(Loc);

492 else

494}

495

500

503

504 unsigned Frame = 0;

506 switch (LCtx->getKind()) {

508 Out << "\t#" << Frame << ' ';

509 ++Frame;

510 if (const auto *D = dyn_cast(LCtx->getDecl()))

512 else

513 Out << "Calling anonymous code";

514 if (const Stmt *S = cast(LCtx)->getCallSite()) {

515 Out << " at line ";

517 }

518 break;

520 Out << "Invoking block";

521 if (const Decl *D = cast(LCtx)->getDecl()) {

522 Out << " defined at line ";

524 }

525 break;

526 }

527 Out << '\n';

528 }

529}

530

532 unsigned int Space, bool IsDot,

534 printMoreInfoPerContext) const {

538

541

542 unsigned Frame = 0;

544 Indent(Out, Space, IsDot)

545 << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";

546 switch (LCtx->getKind()) {

548 Out << '#' << Frame << " Call\", \"calling\": \"";

549 ++Frame;

550 if (const auto *D = dyn_cast(LCtx->getDecl()))

551 Out << D->getQualifiedNameAsString();

552 else

553 Out << "anonymous code";

554

555 Out << "\", \"location\": ";

556 if (const Stmt *S = cast(LCtx)->getCallSite()) {

558 } else {

559 Out << "null";

560 }

561

562 Out << ", \"items\": ";

563 break;

565 Out << "Invoking block\" ";

566 if (const Decl *D = cast(LCtx)->getDecl()) {

567 Out << ", \"location\": ";

569 Out << ' ';

570 }

571 break;

572 }

573

574 printMoreInfoPerContext(LCtx);

575

576 Out << '}';

577 if (LCtx->getParent())

578 Out << ',';

579 Out << NL;

580 }

581}

582

584

585

586

587

588

589namespace {

590

591class FindBlockDeclRefExprsVals : public StmtVisitor{

596

597public:

600 : BEVals(bevals), BC(bc) {}

601

602 void VisitStmt(Stmt *S) {

603 for (auto *Child : S->children())

604 if (Child)

605 Visit(Child);

606 }

607

609

610 if (const auto *VD = dyn_cast(DR->getDecl())) {

611 if (!VD->hasLocalStorage()) {

612 if (Visited.insert(VD).second)

614 }

615 }

616 }

617

618 void VisitBlockExpr(BlockExpr *BR) {

619

622 }

623

627 Expr *Semantic = *it;

628 if (auto *OVE = dyn_cast(Semantic))

629 Semantic = OVE->getSourceExpr();

630 Visit(Semantic);

631 }

632 }

633};

634

635}

636

638

640 void *&Vec,

641 llvm::BumpPtrAllocator &A) {

642 if (Vec)

644

647 new (BV) DeclVec(BC, 10);

648

649

650 for (const auto &CI : BD->captures()) {

651 BV->push_back(CI.getVariable(), BC);

652 }

653

654

655 FindBlockDeclRefExprsVals F(*BV, BC);

657

658 Vec = BV;

659 return BV;

660}

661

662llvm::iterator_rangeAnalysisDeclContext::referenced\_decls\_iterator

664 if (!ReferencedBlockVars)

665 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();

666

669 return llvm::make_range(V->begin(), V->end());

670}

671

672std::unique_ptr &AnalysisDeclContext::getAnalysisImpl(const void *tag) {

673 if (!ManagedAnalyses)

676 return (*M)[tag];

677}

678

679

680

681

682

684

686 delete forcedBlkExprs;

687 delete ReferencedBlockVars;

689}

690

692

695}

696

698 for (llvm::FoldingSet::iterator I = Contexts.begin(),

699 E = Contexts.end(); I != E; ) {

701 ++I;

702 delete LC;

703 }

704 Contexts.clear();

705}

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.