clang: include/clang/Analysis/PathDiagnostic.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13#ifndef LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H

14#define LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H

15

20#include "llvm/ADT/ArrayRef.h"

21#include "llvm/ADT/FoldingSet.h"

22#include "llvm/ADT/PointerUnion.h"

23#include "llvm/ADT/SmallVector.h"

24#include "llvm/ADT/StringRef.h"

25#include "llvm/Support/Allocator.h"

26#include

27#include

28#include

29#include

30#include

31#include

32#include

33#include

34#include

35#include

36#include

37

39

40class AnalysisDeclContext;

41class BinaryOperator;

42class CallEnter;

43class CallExitEnd;

44class ConditionalOperator;

46class LocationContext;

47class MemberExpr;

48class ProgramPoint;

49class SourceManager;

50

51namespace ento {

52

53

54

55

56

57class PathDiagnostic;

58

59

60

62

63

65

66

67

68

70

71

72

74

75

76

78

79

80

82

83

84

86

87

88

90};

91

93public:

95 public:

97

98 using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;

99

100

102

103

104 const llvm::FoldingSetNodeID NodeID;

105

106

108 };

109

111 llvm::BumpPtrAllocator Alloc;

112 llvm::FoldingSet Set;

113

114 public:

116

117 bool empty() const { return Set.empty(); }

118

120 StringRef ConsumerName,

121 StringRef fileName);

122

124 };

125

126private:

127 virtual void anchor();

128

129public:

132

134

137

138 virtual StringRef getName() const = 0;

139

141

143

145

146

148

149

151

152

155

157

160 }

161

166 }

167

169

170

171

173

174protected:

176 llvm::FoldingSet Diags;

177};

178

179

180

181

182

184public:

186

190};

191

193 llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;

194

196private:

197 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;

198

199 const Stmt *S = nullptr;

200 const Decl *D = nullptr;

204

206 : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}

207

211

214

215public:

216

218

219

222 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),

223 S(K == StmtK ? s : nullptr), SM(&sm),

225 assert(K == SingleLocK || S);

226 assert(K == SingleLocK || Loc.isValid());

227 assert(K == SingleLocK || Range.isValid());

228 }

229

230

232 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {

233 assert(D);

235 assert(Range.isValid());

236 }

237

238

239

240

242 : SM(&sm), Loc(loc, sm), Range(genRange()) {

244 assert(Range.isValid());

245 }

246

247

251 }

252

253

256

257

258

259

264 }

265

266

270

271

272

273

274

278

279

280

286

287

288

291

292

293

296

297

298

301

302

303

306

307

308

311

312

315

316

319

320

321

322

325 bool UseEndOfStatement = false);

326

328 return K == X.K && Loc == X.Loc && Range == X.Range;

329 }

330

332 return !(*this == X);

333 }

334

336 return SM != nullptr;

337 }

338

340 return Loc;

341 }

342

345 }

346

350 return nullptr;

352 }

353

355

356 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }

357

359

362 }

363

365

367

368 void Profile(llvm::FoldingSetNodeID &ID) const;

369

370 void dump() const;

371};

372

374private:

376

377public:

380 : Start(start), End(end) {}

381

384

387

390 End.flatten();

391 }

392

393 void Profile(llvm::FoldingSetNodeID &ID) const {

395 End.Profile(ID);

396 }

397};

398

399

400

401

402

404public:

407

408private:

409 const std::string str;

410 const Kind kind;

412

413

414

415 bool LastInMainSourceFile = false;

416

417

418

419

420

421 StringRef Tag;

422

423 std::vector ranges;

424 std::vector fixits;

425

426protected:

429

430public:

435

437

438

439 void setTag(const char *tag) { Tag = tag; }

440

441

442 const void *getTag() const { return Tag.data(); }

443

444

445

447

448

449

451

454

456

459 return;

460 ranges.push_back(R);

461 }

462

464 if (!B.isValid() || E.isValid())

465 return;

467 }

468

470 fixits.push_back(F);

471 }

472

473

475

476

478

479 virtual void Profile(llvm::FoldingSetNodeID &ID) const;

480

482 LastInMainSourceFile = true;

483 }

484

486 return LastInMainSourceFile;

487 }

488

489 virtual void dump() const = 0;

490};

491

493

494class PathPieces : public std::list {

496 bool ShouldFlattenMacros) const;

497

498public:

501 flattenTo(Result, Result, ShouldFlattenMacros);

503 }

504

505 void dump() const;

506};

507

509private:

511

512public:

514 StringRef s,

516 bool addPosRange = true)

519 "PathDiagnosticSpotPiece's must have a valid location.");

521 }

522

525

526 void Profile(llvm::FoldingSetNodeID &ID) const override;

527

529 return P->getKind() == Event || P->getKind() == Macro ||

530 P->getKind() == Note || P->getKind() == PopUp;

531 }

532};

533

535 std::optional IsPrunable;

536

537public:

539 StringRef s, bool addPosRange = true)

542

543

544

545

547 if (IsPrunable && !override)

548 return;

550 }

551

552

553 bool isPrunable() const { return IsPrunable.value_or(false); }

554

555 void dump() const override;

556

558 return P->getKind() == Event;

559 }

560};

561

563 const Decl *Caller;

564 const Decl *Callee = nullptr;

565

566

567

568 bool NoExit;

569

570

571

572 bool IsCalleeAnAutosynthesizedPropertyAccessor = false;

573

574

575

576 std::string CallStackMessage;

577

584 path(oldPath) {}

585

586public:

591

593

595

598

601

603

604 std::shared_ptr getCallEnterEvent() const;

605 std::shared_ptr

607 std::shared_ptr getCallExitEvent() const;

608

612 for (const auto &I : path)

613 I->flattenLocations();

614 }

615

616 static std::shared_ptr

619

621 const Decl *caller);

622

623 void dump() const override;

624

625 void Profile(llvm::FoldingSetNodeID &ID) const override;

626

628 return P->getKind() == Call;

629 }

630};

631

633 std::vector LPairs;

634

635public:

638 StringRef s)

641 }

642

647 }

648

650

652 assert(!LPairs.empty() &&

653 "PathDiagnosticControlFlowPiece needs at least one location.");

654 return LPairs[0].getStart();

655 }

656

658 assert(!LPairs.empty() &&

659 "PathDiagnosticControlFlowPiece needs at least one location.");

660 return LPairs[0].getEnd();

661 }

662

664 LPairs[0].setStart(L);

665 }

666

668 LPairs[0].setEnd(L);

669 }

670

672

675 }

676

677 using iterator = std::vector::iterator;

678

681

683 for (auto &I : *this)

684 I.flatten();

685 }

686

688 std::vector::const_iterator;

689

692

695 }

696

697 void dump() const override;

698

699 void Profile(llvm::FoldingSetNodeID &ID) const override;

700};

701

703public:

707

709

713 I->flattenLocations();

714 }

715

717 return P->getKind() == Macro;

718 }

719

720 void dump() const override;

721

722 void Profile(llvm::FoldingSetNodeID &ID) const override;

723};

724

726public:

728 bool AddPosRange = true)

731

733 return P->getKind() == Note;

734 }

735

736 void dump() const override;

737

738 void Profile(llvm::FoldingSetNodeID &ID) const override;

739};

740

742public:

744 bool AddPosRange = true)

747

749 return P->getKind() == PopUp;

750 }

751

752 void dump() const override;

753

754 void Profile(llvm::FoldingSetNodeID &ID) const override;

755};

756

757

759

760

761

762

764 std::string CheckerName;

765 const Decl *DeclWithIssue;

767 std::string VerboseDesc;

768 std::string ShortDesc;

769 std::string Category;

770 std::dequestd::string OtherDesc;

771

772

774

777

778

779

781 const Decl *UniqueingDecl;

782

783

784 const Decl *AnalysisEntryPoint = nullptr;

785

786

787 std::unique_ptr ExecutedLines;

788

789public:

792 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,

794 const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,

795 std::unique_ptr ExecutedLines);

797

799

800

801

803 if (pathStack.empty())

804 return pathImpl;

805 return *pathStack.back();

806 }

807

808

810 return pathImpl;

811 }

812

813

815

817 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }

818

820

822 assert(Loc.isValid() && "End location already set!");

823 Loc = EndPiece->getLocation();

824 assert(Loc.isValid() && "Invalid location for end-of-path piece");

826 }

827

829 if (!ShortDesc.empty())

830 ShortDesc += S;

831 VerboseDesc += S;

832 }

833

835

837 return ShortDesc.empty() ? VerboseDesc : ShortDesc;

838 }

839

843

844 using meta_iterator = std::dequestd::string::const_iterator;

845

848 void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }

849

851 return *ExecutedLines;

852 }

853

855 return *ExecutedLines;

856 }

857

858

860

861

862

863

865

867 DeclWithIssue = D;

868 }

869

871 return Loc;

872 }

873

875 Loc = NewLoc;

876 }

877

878

880 return UniqueingLoc;

881 }

882

883

885 return UniqueingDecl;

886 }

887

889 Loc.flatten();

890 for (const auto &I : pathImpl)

891 I->flattenLocations();

892 }

893

894

895

896

897

898 void Profile(llvm::FoldingSetNodeID &ID) const;

899

900

901

902

903

904 void FullProfile(llvm::FoldingSetNodeID &ID) const;

905};

906

907}

908}

909

910#endif

This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::SourceLocation class and associated facilities.

__device__ __2f16 float __ockl_bool s

AnalysisDeclContext contains the context data for the function, method or block under analysis.

A builtin binary operation expression such as "x + y" or "x <= y".

Represents a point when we begin processing an inlined call.

Represents a point when we finish the call exit sequence (for inlined call).

CompoundStmt - This represents a group of statements like { stmt stmt }.

ConditionalOperator - The ?: ternary operator.

Decl - This represents one declaration (or definition), e.g.

Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...

A SourceLocation and its associated SourceManager.

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

Stmt - This represents one statement.

bool isValid() const =delete

~PathDiagnosticCallPiece() override

PathDiagnosticLocation getLocation() const override

void setCallee(const CallEnter &CE, const SourceManager &SM)

PathDiagnosticLocation callEnter

void dump() const override

std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const

void setCallStackMessage(StringRef st)

bool hasCallStackMessage()

static bool classof(const PathDiagnosticPiece *P)

const Decl * getCallee() const

static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)

PathDiagnosticLocation callReturn

void flattenLocations() override

std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const

void Profile(llvm::FoldingSetNodeID &ID) const override

const Decl * getCaller() const

std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const

PathDiagnosticLocation callEnterWithin

PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)

void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)

const llvm::FoldingSetNodeID NodeID

A precomputed hash tag used for uniquing PDFileEntry objects.

std::vector< std::pair< StringRef, StringRef > > ConsumerFiles

void Profile(llvm::FoldingSetNodeID &ID)

Used for profiling in the FoldingSet.

ConsumerFiles files

A vector of <consumer,file> pairs.

PDFileEntry(llvm::FoldingSetNodeID &NodeID)

@ None

Only runs visitors, no output generated.

@ Everything

Used for HTML, shows both "arrows" and control notes.

@ Extensive

Used for plist output, used for "arrows" generation.

@ Minimal

Used for SARIF and text output.

PathDiagnosticConsumer()=default

virtual bool supportsLogicalOpControlFlow() const

virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0

bool shouldAddPathEdges() const

virtual bool supportsCrossFileDiagnostics() const

Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...

void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)

virtual StringRef getName() const =0

virtual PathGenerationScheme getGenerationScheme() const

llvm::FoldingSet< PathDiagnostic > Diags

virtual ~PathDiagnosticConsumer()

void FlushDiagnostics(FilesMade *FilesMade)

bool shouldAddControlNotes() const

bool shouldGenerateDiagnostics() const

PathDiagnosticLocation getStartLocation() const

PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)

std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator

void push_back(const PathDiagnosticLocationPair &X)

void setEndLocation(const PathDiagnosticLocation &L)

static bool classof(const PathDiagnosticPiece *P)

void dump() const override

PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s)

std::vector< PathDiagnosticLocationPair >::iterator iterator

const_iterator begin() const

PathDiagnosticLocation getLocation() const override

void setStartLocation(const PathDiagnosticLocation &L)

const_iterator end() const

~PathDiagnosticControlFlowPiece() override

PathDiagnosticLocation getEndLocation() const

void Profile(llvm::FoldingSetNodeID &ID) const override

void flattenLocations() override

void setPrunable(bool isPrunable, bool override=false)

Mark the diagnostic piece as being potentially prunable.

static bool classof(const PathDiagnosticPiece *P)

~PathDiagnosticEventPiece() override

PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true)

void dump() const override

bool isPrunable() const

Return true if the diagnostic piece is prunable.

const PathDiagnosticLocation & getEnd() const

void Profile(llvm::FoldingSetNodeID &ID) const

const PathDiagnosticLocation & getStart() const

void setStart(const PathDiagnosticLocation &L)

void setEnd(const PathDiagnosticLocation &L)

PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)

static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)

For member expressions, return the location of the '.

const Stmt * asStmt() const

static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)

Create a location for the beginning of the enclosing declaration body.

void Profile(llvm::FoldingSetNodeID &ID) const

PathDiagnosticLocation(const Decl *d, const SourceManager &sm)

Create a location corresponding to the given declaration.

PathDiagnosticRange asRange() const

const Decl * asDecl() const

bool operator!=(const PathDiagnosticLocation &X) const

const SourceManager & getManager() const

static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)

Create the location for the operator of the binary expression.

static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)

Create a location for the end of the compound statement.

static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)

Create a location for the beginning of the compound statement.

static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement=false)

Construct a source location that corresponds to either the beginning or the end of the given statemen...

static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)

Create a location for the end of the statement.

static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)

Create a location for the beginning of the declaration.

FullSourceLoc asLocation() const

bool operator==(const PathDiagnosticLocation &X) const

PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)

Create a location at an explicit offset in the source.

static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)

Create a location corresponding to the given declaration.

static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)

PathDiagnosticLocation()=default

Create an invalid location.

static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)

Constructs a location for the end of the enclosing declaration body.

PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)

Create a location corresponding to the given statement.

const Stmt * getStmtOrNull() const

static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)

Convert the given location into a single kind location.

static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)

Create a location for the beginning of the declaration.

bool hasValidLocation() const

void dump() const override

void flattenLocations() override

PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)

static bool classof(const PathDiagnosticPiece *P)

void Profile(llvm::FoldingSetNodeID &ID) const override

~PathDiagnosticMacroPiece() override

void Profile(llvm::FoldingSetNodeID &ID) const override

void dump() const override

PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)

~PathDiagnosticNotePiece() override

static bool classof(const PathDiagnosticPiece *P)

ArrayRef< SourceRange > getRanges() const

Return the SourceRanges associated with this PathDiagnosticPiece.

void addRange(SourceRange R)

virtual PathDiagnosticLocation getLocation() const =0

void addFixit(FixItHint F)

void setAsLastInMainSourceFile()

virtual void dump() const =0

void setTag(const char *tag)

Tag this PathDiagnosticPiece with the given C-string.

bool isLastInMainSourceFile() const

PathDiagnosticPiece(const PathDiagnosticPiece &)=delete

virtual void Profile(llvm::FoldingSetNodeID &ID) const

StringRef getTagStr() const

Return the string representation of the tag.

PathDiagnosticPiece & operator=(const PathDiagnosticPiece &)=delete

virtual ~PathDiagnosticPiece()

void addRange(SourceLocation B, SourceLocation E)

PathDiagnosticPiece()=delete

virtual void flattenLocations()=0

DisplayHint getDisplayHint() const

getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...

const void * getTag() const

Return the opaque tag (if any) on the PathDiagnosticPiece.

StringRef getString() const

ArrayRef< FixItHint > getFixits() const

Return the fix-it hints associated with this PathDiagnosticPiece.

PathDiagnosticRange()=default

PathDiagnosticRange(SourceRange R, bool isP=false)

void flattenLocations() override

void Profile(llvm::FoldingSetNodeID &ID) const override

static bool classof(const PathDiagnosticPiece *P)

PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)

PathDiagnosticLocation getLocation() const override

PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.

StringRef getCheckerName() const

PathPieces & getActivePath()

Return the path currently used by builders for constructing the PathDiagnostic.

void addMeta(StringRef s)

meta_iterator meta_end() const

void setDeclWithIssue(const Decl *D)

FilesToLineNumsMap & getExecutedLines()

void FullProfile(llvm::FoldingSetNodeID &ID) const

Profiles the diagnostic, including its path.

PathDiagnosticLocation getUniqueingLoc() const

Get the location on which the report should be uniqued.

std::deque< std::string >::const_iterator meta_iterator

StringRef getVerboseDescription() const

void appendToDesc(StringRef S)

const Decl * getDeclWithIssue() const

Return the semantic context where an issue occurred.

void pushActivePath(PathPieces *p)

const Decl * getAnalysisEntryPoint() const

Get the top-level entry point from which this issue was discovered.

void Profile(llvm::FoldingSetNodeID &ID) const

Profiles the diagnostic, independent of the path it references.

void setLocation(PathDiagnosticLocation NewLoc)

const FilesToLineNumsMap & getExecutedLines() const

unsigned full_size()

Return the unrolled size of the path.

void setEndOfPath(PathDiagnosticPieceRef EndPiece)

StringRef getBugType() const

const Decl * getUniqueingDecl() const

Get the declaration containing the uniqueing location.

PathPieces & getMutablePieces()

Return a mutable version of 'path'.

StringRef getCategory() const

StringRef getShortDescription() const

meta_iterator meta_begin() const

bool isWithinCall() const

PathDiagnosticLocation getLocation() const

PathPieces flatten(bool ShouldFlattenMacros) const

A Range represents the closed range [from, to].

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

std::map< FileID, std::set< unsigned > > FilesToLineNumsMap

File IDs mapped to sets of line numbers.

llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

These options tweak the behavior of path diangostic consumers.

bool ShouldDisplayMacroExpansions

Whether to include additional information about macro expansions with the diagnostics,...

bool ShouldDisplayWarningsAsErrors

Whether the consumer should treat consumed diagnostics as hard errors.

bool ShouldApplyFixIts

Whether the consumer should attempt to rewrite the source file with fix-it hints attached to the diag...

bool ShouldWriteVerboseReportFilename

If the consumer intends to produce multiple output files, should it use a pseudo-random file name or ...

bool ShouldSerializeStats

Whether to include LLVM statistics of the process in the diagnostic.

std::string ToolInvocation

Run-line of the tool that produced the diagnostic.

bool ShouldDisplayDiagnosticName

Whether the consumer should present the name of the entity that emitted the diagnostic (eg....