clang: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H

15#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H

16

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

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

31#include "llvm/ADT/ImmutableSet.h"

32#include "llvm/ADT/SmallSet.h"

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

34#include "llvm/ADT/StringMap.h"

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

36#include "llvm/ADT/ilist.h"

37#include "llvm/ADT/ilist_node.h"

38#include "llvm/ADT/iterator_range.h"

39#include

40#include

41#include

42#include

43#include

44#include

45

47

48class AnalyzerOptions;

49class ASTContext;

51class LocationContext;

52class SourceManager;

53class Stmt;

54

55namespace ento {

56

57class BugType;

58class CheckerBase;

59class ExplodedGraph;

60class ExplodedNode;

61class ExprEngine;

62class MemRegion;

63

64

65

66

67

68

69

71 llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr>;

72

73

74

75

76

78public:

80

81

83};

84

85

86

87

88

89

90

92private:

94 std::string Msg;

95

96public:

99

100

101

103

104

105

107

109 return Msg;

110 }

111

113 return Msg;

114 }

115};

116

117

118

120public:

122

123protected:

126

131

135

137 : BugReport(kind, bt, "", desc) {}

138

143

144public:

146

148

150

151

152

153

154

155

156

158

159

160

161

162

167 }

168

169

170

171

172

174

175

176

177

179

180

181

182

183

184

185

186

187

188

190

191

192

193

194

196

197

198

199

200

203 auto P = std::make_shared(Pos, Msg);

204

205 for (const auto &R : Ranges)

206 P->addRange(R);

207

208 Notes.push_back(std::move(P));

209 }

210

213 }

214

215

216

217

218

219

220

221

223 assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "

224 "to specify that the report does not have a range.");

226 }

227

228

231 }

232

233

234

235

236

237

238

239

242 }

243

245

246

247

248 virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;

249};

250

253 const Decl *DeclWithIssue = nullptr;

254

255public:

258

261 }

262

264 assert(Location.isValid());

265 return Location;

266 }

267

269 return DeclWithIssue;

270 }

271

274 }

275

278 }

279

280

281

283 DeclWithIssue = declWithIssue;

284 }

285

286 void Profile(llvm::FoldingSetNodeID& hash) const override;

287};

288

290public:

293 using visitor_range = llvm::iterator_range<visitor_iterator>;

294

295protected:

296

297

299

300

301

303

304

305

306

307

308

309

310

312

313

314

315

316

317

318 llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>

320

321

322

324

325

326

328

329

331

332

333

334

336

337

338

339

340

342

343

344

345

346

347

349

350

352

353

354

357

359

360

361

362

363

364

365 std::map<PathDiagnosticPieceRef, std::unique_ptr>

367

368public:

372

376 {},

377 nullptr) {}

378

379

380

381

382

383

384

385

389 const Decl *DeclToUnique)

391 DeclToUnique) {}

392

396 const Decl *DeclToUnique);

397

400 }

401

403

404

405

407

408

410

411

414 }

415

416

419 }

420

422

424

426

427

428

429

432

434

435

436

437

441

443

444

445

446

450

455

456 std::optionalbugreporter::TrackingKind

458

459 std::optionalbugreporter::TrackingKind

461

463

464

465

466

467

470 }

471

472

473

474

475

476

477

478

479

480

483 }

484

485

486

487

488 void Profile(llvm::FoldingSetNodeID &hash) const override;

489

490

491

492

493

494

495 void addVisitor(std::unique_ptr visitor);

496

497 template <class VisitorType, class... Args>

500 std::make_unique(std::forward(ConstructorArgs)...));

501 }

502

503

504

506

507

511

512

513

514

517 }

518

520 std::unique_ptr StackHint) {

521 StackHints[Piece] = std::move(StackHint);

522 }

523

526 }

527

528

529

530 std::string

535 return I->second->getMessage(N);

536 return "";

537 }

538};

539

540

541

542

543

546

547

549

550 void AddReport(std::unique_ptr &&R) {

551 Reports.push_back(std::move(R));

552 }

553

554public:

556

558

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

560 assert(!Reports.empty());

561 Reports.front()->Profile(ID);

562 }

563};

564

565

566

567

568

570public:

572

578};

579

580

581

582

583

584

586private:

588

589

590 const Decl *AnalysisEntryPoint = nullptr;

591

592

594

595

596 llvm::FoldingSet EQClasses;

597

598

599 std::vector<BugReportEquivClass *> EQClassesVector;

600

601

603

604public:

607

608

610

612 return D.getPathDiagnosticConsumers();

613 }

614

615

618 return EQClasses;

619 }

620

622

624

626

628

629

631

633 assert(EntryPoint);

634 AnalysisEntryPoint = EntryPoint;

635 }

636

637

638

639

640

641

642 virtual void emitReport(std::unique_ptr R);

643

645 StringRef BugName, StringRef BugCategory,

649

650 void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,

651 StringRef BugName, StringRef BugCategory,

652 StringRef BugStr, PathDiagnosticLocation Loc,

653 ArrayRef Ranges = {},

654 ArrayRef Fixits = {});

655

656private:

657 llvm::StringMap<std::unique_ptr> StrBugTypes;

658

659

660

661 BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,

662 StringRef category);

663

664 virtual BugReport *

665 findReportInEquivalenceClass(BugReportEquivClass &eqClass,

666 SmallVectorImpl<BugReport *> &bugReports) {

667 return eqClass.getReports()[0].get();

668 }

669

670protected:

671

672 virtual std::unique_ptr

674 ArrayRef<PathDiagnosticConsumer *> consumers,

675 ArrayRef<BugReport *> bugReports);

676};

677

678

681

682 BugReport *findReportInEquivalenceClass(

685

686

687 std::unique_ptr

688 generateDiagnosticForConsumerMap(BugReport *exampleReport,

691public:

694

695

696

698

699

700

702

703

704

705

706

707

711

712 void emitReport(std::unique_ptr R) override;

713};

714

715

718

719 virtual void anchor();

720

721public:

723

725

728

731 }

732

735 }

736

739 }

740

743 }

744};

745

746

747

748

749

750

751

752

753

755public:

757

758

760 std::vector<std::unique_ptr> Tags;

761

762 public:

763 template <class DataTagType, class... Args>

764 const DataTagType *make(Args &&... ConstructorArgs) {

765

766

767 Tags.emplace_back(

768 new DataTagType(std::forward(ConstructorArgs)...));

769 return static_cast<DataTagType *>(Tags.back().get());

770 }

771 };

772

773protected:

775};

776

777

778

780public:

783

784private:

785 static int Kind;

786

788 const bool IsPrunable;

789

791 : DataTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}

792

793public:

795 return T->getTagKind() == &Kind;

796 }

797

800 std::string Msg = Cb(BRC, R);

801 if (Msg.empty())

802 return std::nullopt;

803

804 return std::move(Msg);

805 }

806

808

809

810

811 return "Note Tag";

812 }

813

815

818};

819

820}

821

822}

823

824#endif

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

Defines the clang::Preprocessor interface.

Defines the clang::SourceLocation class and associated facilities.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

Stores options for the analyzer from the command line.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

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

This represents one expression.

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

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

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

ProgramPoints can be "tagged" as representing points specific to a given analysis entity.

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.

BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)

PathDiagnosticLocation getLocation() const override

The primary location of the bug report that points at the undesirable behavior in the code.

const Decl * getDeclWithIssue() const override

The smallest declaration that contains the bug location.

PathDiagnosticLocation getUniqueingLocation() const override

Get the location on which the report should be uniqued.

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

Reports are uniqued to ensure that we do not emit multiple diagnostics for each bug.

static bool classof(const BugReport *R)

const Decl * getUniqueingDecl() const override

Get the declaration that corresponds to (usually contains) the uniqueing location.

void setDeclWithIssue(const Decl *declWithIssue)

Specifically set the Decl where an issue occurred.

ArrayRef< std::unique_ptr< BugReport > > getReports() const

BugReportEquivClass(std::unique_ptr< BugReport > R)

void Profile(llvm::FoldingSetNodeID &ID) const

This class provides an interface through which checkers can create individual bug reports.

llvm::ArrayRef< FixItHint > getFixits() const

void addRange(SourceRange R)

Add a range to a bug report.

SmallVector< SourceRange, 4 > Ranges

std::string ShortDescription

void addNote(StringRef Msg, const PathDiagnosticLocation &Pos, ArrayRef< SourceRange > Ranges={})

Add new item to the list of additional notes that need to be attached to this report.

virtual PathDiagnosticLocation getUniqueingLocation() const =0

Get the location on which the report should be uniqued.

virtual ~BugReport()=default

virtual PathDiagnosticLocation getLocation() const =0

The primary location of the bug report that points at the undesirable behavior in the code.

virtual const Decl * getUniqueingDecl() const =0

Get the declaration that corresponds to (usually contains) the uniqueing location.

SmallVector< std::shared_ptr< PathDiagnosticNotePiece >, 4 > Notes

SmallVector< FixItHint, 4 > Fixits

ArrayRef< std::shared_ptr< PathDiagnosticNotePiece > > getNotes()

BugReport(Kind kind, const BugType &bt, StringRef desc)

void addFixItHint(const FixItHint &F)

Add a fix-it hint to the bug report.

StringRef getDescription() const

A verbose warning message that is appropriate for displaying next to the source code that introduces ...

virtual void Profile(llvm::FoldingSetNodeID &hash) const =0

Reports are uniqued to ensure that we do not emit multiple diagnostics for each bug.

const BugType & getBugType() const

StringRef getShortDescription(bool UseFallback=true) const

A short general warning message that is appropriate for displaying in the list of all reported bugs.

virtual ArrayRef< SourceRange > getRanges() const

Get the SourceRanges associated with the report.

virtual const Decl * getDeclWithIssue() const =0

The smallest declaration that contains the bug location.

BugReport(Kind K, const BugType &BT, StringRef ShortDescription, StringRef Description)

ASTContext & getASTContext() const

BugReporterContext(PathSensitiveBugReporter &br)

ProgramStateManager & getStateManager() const

const SourceManager & getSourceManager() const

PathSensitiveBugReporter & getBugReporter()

virtual ~BugReporterContext()=default

const PathSensitiveBugReporter & getBugReporter() const

const AnalyzerOptions & getAnalyzerOptions() const

virtual ASTContext & getASTContext()=0

virtual ~BugReporterData()=default

virtual AnalyzerOptions & getAnalyzerOptions()=0

virtual SourceManager & getSourceManager()=0

virtual Preprocessor & getPreprocessor()=0

virtual ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()=0

BugReporter is a utility class for generating PathDiagnostics for analysis.

virtual std::unique_ptr< DiagnosticForConsumerMapTy > generateDiagnosticForConsumerMap(BugReport *exampleReport, ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< BugReport * > bugReports)

Generate the diagnostics for the given bug report.

Preprocessor & getPreprocessor()

void FlushReports()

Generate and flush diagnostics for all bug reports.

const SourceManager & getSourceManager()

const Decl * getAnalysisEntryPoint() const

Get the top-level entry point for the issue to be reported.

llvm::iterator_range< EQClasses_iterator > equivalenceClasses()

ASTContext & getContext()

const AnalyzerOptions & getAnalyzerOptions()

void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})

virtual void emitReport(std::unique_ptr< BugReport > R)

Add the given report to the set of reports tracked by BugReporter.

llvm::FoldingSet< BugReportEquivClass >::iterator EQClasses_iterator

Iterator over the set of BugReports tracked by the BugReporter.

ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()

void setAnalysisEntryPoint(const Decl *EntryPoint)

const DataTagType * make(Args &&... ConstructorArgs)

The tag that carries some information with it.

StringRef getTagDescription() const override

MemRegion - The root abstract class for all memory regions.

The tag upon which the TagVisitor reacts.

std::function< std::string(BugReporterContext &, PathSensitiveBugReport &)> Callback

static bool classof(const ProgramPointTag *T)

StringRef getTagDescription() const override

std::optional< std::string > generateMessage(BugReporterContext &BRC, PathSensitiveBugReport &R) const

llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts

A set of location contexts that correspoind to call sites which should be considered "interesting".

void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)

Marks a symbol as interesting.

void addVisitor(Args &&... ConstructorArgs)

llvm::SmallSet< const ExplodedNode *, 4 > TrackedConditions

Conditions we're already tracking.

PathDiagnosticLocation getUniqueingLocation() const override

Get the location on which the report should be uniqued.

VisitorList Callbacks

A set of custom visitors which generate "event" diagnostics at interesting points in the path.

const Stmt * getStmt() const

std::string getCallStackMessage(PathDiagnosticPieceRef Piece, const ExplodedNode *N) const

Produce the hint for the given node.

PathDiagnosticLocation getLocation() const override

The primary location of the bug report that points at the undesirable behavior in the code.

const Decl * getDeclWithIssue() const override

The smallest declaration that contains the bug location.

std::map< PathDiagnosticPieceRef, std::unique_ptr< StackHintGenerator > > StackHints

If an event occurs in a different frame than the final diagnostic, supply a message that will be used...

std::pair< const void *, const void * > InvalidationRecord

Used to track unique reasons why a bug report might be invalid.

bool shouldPrunePath() const

Indicates whether or not any path pruning should take place when generating a PathDiagnostic from thi...

PathDiagnosticLocation UniqueingLocation

Reports with different uniqueing locations are considered to be different for the purposes of dedupli...

ArrayRef< SourceRange > getRanges() const override

Get the SourceRanges associated with the report.

visitor_iterator visitor_end()

llvm::DenseMap< SymbolRef, bugreporter::TrackingKind > InterestingSymbols

Profile to identify equivalent bug reports for error report coalescing.

const Decl * getUniqueingDecl() const override

Get the declaration containing the uniqueing location.

llvm::SmallSet< InvalidationRecord, 4 > Invalidations

If non-empty, this bug report is likely a false positive and should not be shown to the user.

const ExplodedNode * getErrorNode() const

PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)

static bool classof(const BugReport *R)

const ExplodedNode * ErrorNode

The ExplodedGraph node against which the report was thrown.

PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errorNode)

bool addTrackedCondition(const ExplodedNode *Cond)

Notes that the condition of the CFGBlock associated with Cond is being tracked.

visitor_iterator visitor_begin()

Iterators through the custom diagnostic visitors.

void addCallStackHint(PathDiagnosticPieceRef Piece, std::unique_ptr< StackHintGenerator > StackHint)

void markInvalid(const void *Tag, const void *Data)

Marks the current report as invalid, meaning that it is probably a false positive and should not be r...

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

Profile to identify equivalent bug reports for error report coalescing.

void clearVisitors()

Remove all visitors attached to this bug report.

bool hasCallStackHint(PathDiagnosticPieceRef Piece) const

void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)

Add custom or predefined bug report visitors to this report.

bool isValid() const

Returns whether or not this report should be considered valid.

std::optional< bugreporter::TrackingKind > getInterestingnessKind(SymbolRef sym) const

void markNotInteresting(SymbolRef sym)

bool DoNotPrunePath

When set, this flag disables all callstack pruning from a diagnostic path.

PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)

Create a PathSensitiveBugReport with a custom uniqueing location.

llvm::DenseMap< const MemRegion *, bugreporter::TrackingKind > InterestingRegions

A (stack of) set of regions that are registered with this report as being "interesting",...

llvm::iterator_range< visitor_iterator > visitor_range

bool isInteresting(SymbolRef sym) const

const SourceRange ErrorNodeRange

The range that corresponds to ErrorNode's program point.

VisitorList::iterator visitor_iterator

llvm::FoldingSet< BugReporterVisitor > CallbacksSet

Used for ensuring the visitors are only added once.

void disablePathPruning()

Disable all path pruning when generating a PathDiagnostic.

const Decl * UniqueingDecl

GRBugReporter is used for generating path-sensitive reports.

const ExplodedGraph & getGraph() const

getGraph - Get the exploded graph created by the analysis engine for the analyzed method or function.

std::unique_ptr< DiagnosticForConsumerMapTy > generatePathDiagnostics(ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< PathSensitiveBugReport * > &bugReports)

bugReports A set of bug reports within a single equivalence class

void emitReport(std::unique_ptr< BugReport > R) override

Add the given report to the set of reports tracked by BugReporter.

ProgramStateManager & getStateManager() const

getStateManager - Return the state manager used by the analysis engine.

PathSensitiveBugReporter(BugReporterData &d, ExprEngine &eng)

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

Constructs a Stack hint for the given symbol.

StackHintGeneratorForSymbol(SymbolRef S, StringRef M)

std::string getMessage(const ExplodedNode *N) override

Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...

virtual std::string getMessageForSymbolNotFound()

virtual std::string getMessageForReturn(const CallExpr *CallExpr)

virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)

Produces the message of the following form: 'Msg via Nth parameter'.

~StackHintGeneratorForSymbol() override=default

Interface for classes constructing Stack hints.

virtual ~StackHintGenerator()=0

virtual std::string getMessage(const ExplodedNode *N)=0

Construct the Diagnostic message for the given ExplodedNode.

The visitor detects NoteTags and displays the event notes they contain.

@ Decl

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

TrackingKind

Specifies the type of tracking for an expression.

@ Thorough

Default tracking kind – specifies that as much information should be gathered about the tracked expre...

llvm::DenseMap< PathDiagnosticConsumer *, std::unique_ptr< PathDiagnostic > > DiagnosticForConsumerMapTy

A mapping from diagnostic consumers to the diagnostics they should consume.

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

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

const FunctionProtoType * T