File indexing completed on 2026-05-10 08:36:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
0014 #define LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
0015
0016 #include "clang/AST/Stmt.h"
0017 #include "clang/Analysis/AnalysisDeclContext.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "clang/Basic/SourceLocation.h"
0020 #include "llvm/ADT/ArrayRef.h"
0021 #include "llvm/ADT/FoldingSet.h"
0022 #include "llvm/ADT/PointerUnion.h"
0023 #include "llvm/ADT/SmallVector.h"
0024 #include "llvm/ADT/StringRef.h"
0025 #include "llvm/Support/Allocator.h"
0026 #include <cassert>
0027 #include <deque>
0028 #include <iterator>
0029 #include <list>
0030 #include <map>
0031 #include <memory>
0032 #include <optional>
0033 #include <set>
0034 #include <string>
0035 #include <utility>
0036 #include <vector>
0037
0038 namespace clang {
0039
0040 class AnalysisDeclContext;
0041 class BinaryOperator;
0042 class CallEnter;
0043 class CallExitEnd;
0044 class ConditionalOperator;
0045 class Decl;
0046 class LocationContext;
0047 class MemberExpr;
0048 class ProgramPoint;
0049 class SourceManager;
0050
0051 namespace ento {
0052
0053
0054
0055
0056
0057 class PathDiagnostic;
0058
0059
0060
0061 struct PathDiagnosticConsumerOptions {
0062
0063
0064 std::string ToolInvocation;
0065
0066
0067
0068
0069 bool ShouldDisplayMacroExpansions = false;
0070
0071
0072
0073 bool ShouldSerializeStats = false;
0074
0075
0076
0077 bool ShouldWriteVerboseReportFilename = false;
0078
0079
0080
0081 bool ShouldDisplayWarningsAsErrors = false;
0082
0083
0084
0085 bool ShouldApplyFixIts = false;
0086
0087
0088
0089 bool ShouldDisplayDiagnosticName = false;
0090 };
0091
0092 class PathDiagnosticConsumer {
0093 public:
0094 class PDFileEntry : public llvm::FoldingSetNode {
0095 public:
0096 PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
0097
0098 using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
0099
0100
0101 ConsumerFiles files;
0102
0103
0104 const llvm::FoldingSetNodeID NodeID;
0105
0106
0107 void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
0108 };
0109
0110 class FilesMade {
0111 llvm::BumpPtrAllocator Alloc;
0112 llvm::FoldingSet<PDFileEntry> Set;
0113
0114 public:
0115 ~FilesMade();
0116
0117 bool empty() const { return Set.empty(); }
0118
0119 void addDiagnostic(const PathDiagnostic &PD,
0120 StringRef ConsumerName,
0121 StringRef fileName);
0122
0123 PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
0124 };
0125
0126 private:
0127 virtual void anchor();
0128
0129 public:
0130 PathDiagnosticConsumer() = default;
0131 virtual ~PathDiagnosticConsumer();
0132
0133 void FlushDiagnostics(FilesMade *FilesMade);
0134
0135 virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
0136 FilesMade *filesMade) = 0;
0137
0138 virtual StringRef getName() const = 0;
0139
0140 void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
0141
0142 enum PathGenerationScheme {
0143
0144 None,
0145
0146
0147 Minimal,
0148
0149
0150 Extensive,
0151
0152
0153 Everything
0154 };
0155
0156 virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
0157
0158 bool shouldGenerateDiagnostics() const {
0159 return getGenerationScheme() != None;
0160 }
0161
0162 bool shouldAddPathEdges() const { return getGenerationScheme() >= Extensive; }
0163 bool shouldAddControlNotes() const {
0164 return getGenerationScheme() == Minimal ||
0165 getGenerationScheme() == Everything;
0166 }
0167
0168 virtual bool supportsLogicalOpControlFlow() const { return false; }
0169
0170
0171
0172 virtual bool supportsCrossFileDiagnostics() const { return false; }
0173
0174 protected:
0175 bool flushed = false;
0176 llvm::FoldingSet<PathDiagnostic> Diags;
0177 };
0178
0179
0180
0181
0182
0183 class PathDiagnosticRange : public SourceRange {
0184 public:
0185 bool isPoint = false;
0186
0187 PathDiagnosticRange(SourceRange R, bool isP = false)
0188 : SourceRange(R), isPoint(isP) {}
0189 PathDiagnosticRange() = default;
0190 };
0191
0192 using LocationOrAnalysisDeclContext =
0193 llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
0194
0195 class PathDiagnosticLocation {
0196 private:
0197 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
0198
0199 const Stmt *S = nullptr;
0200 const Decl *D = nullptr;
0201 const SourceManager *SM = nullptr;
0202 FullSourceLoc Loc;
0203 PathDiagnosticRange Range;
0204
0205 PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind)
0206 : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
0207
0208 FullSourceLoc genLocation(
0209 SourceLocation L = SourceLocation(),
0210 LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
0211
0212 PathDiagnosticRange genRange(
0213 LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
0214
0215 public:
0216
0217 PathDiagnosticLocation() = default;
0218
0219
0220 PathDiagnosticLocation(const Stmt *s, const SourceManager &sm,
0221 LocationOrAnalysisDeclContext lac)
0222 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
0223 S(K == StmtK ? s : nullptr), SM(&sm),
0224 Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
0225 assert(K == SingleLocK || S);
0226 assert(K == SingleLocK || Loc.isValid());
0227 assert(K == SingleLocK || Range.isValid());
0228 }
0229
0230
0231 PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
0232 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
0233 assert(D);
0234 assert(Loc.isValid());
0235 assert(Range.isValid());
0236 }
0237
0238
0239
0240
0241 PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
0242 : SM(&sm), Loc(loc, sm), Range(genRange()) {
0243 assert(Loc.isValid());
0244 assert(Range.isValid());
0245 }
0246
0247
0248 static PathDiagnosticLocation create(const Decl *D,
0249 const SourceManager &SM) {
0250 return PathDiagnosticLocation(D, SM);
0251 }
0252
0253
0254 static PathDiagnosticLocation createBegin(const Decl *D,
0255 const SourceManager &SM);
0256
0257
0258
0259
0260 static PathDiagnosticLocation
0261 createBegin(const Decl *D, const SourceManager &SM,
0262 const LocationOrAnalysisDeclContext LAC) {
0263 return createBegin(D, SM);
0264 }
0265
0266
0267 static PathDiagnosticLocation createBegin(const Stmt *S,
0268 const SourceManager &SM,
0269 const LocationOrAnalysisDeclContext LAC);
0270
0271
0272
0273
0274
0275 static PathDiagnosticLocation createEnd(const Stmt *S,
0276 const SourceManager &SM,
0277 const LocationOrAnalysisDeclContext LAC);
0278
0279
0280
0281 static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
0282 const SourceManager &SM);
0283 static PathDiagnosticLocation createConditionalColonLoc(
0284 const ConditionalOperator *CO,
0285 const SourceManager &SM);
0286
0287
0288
0289 static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
0290 const SourceManager &SM);
0291
0292
0293
0294 static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
0295 const SourceManager &SM);
0296
0297
0298
0299 static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
0300 const SourceManager &SM);
0301
0302
0303
0304 static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
0305 const SourceManager &SM);
0306
0307
0308
0309 static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
0310 const SourceManager &SM);
0311
0312
0313 static PathDiagnosticLocation create(const ProgramPoint &P,
0314 const SourceManager &SMng);
0315
0316
0317 static PathDiagnosticLocation createSingleLocation(
0318 const PathDiagnosticLocation &PDL);
0319
0320
0321
0322
0323 static SourceLocation
0324 getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC,
0325 bool UseEndOfStatement = false);
0326
0327 bool operator==(const PathDiagnosticLocation &X) const {
0328 return K == X.K && Loc == X.Loc && Range == X.Range;
0329 }
0330
0331 bool operator!=(const PathDiagnosticLocation &X) const {
0332 return !(*this == X);
0333 }
0334
0335 bool isValid() const {
0336 return SM != nullptr;
0337 }
0338
0339 FullSourceLoc asLocation() const {
0340 return Loc;
0341 }
0342
0343 PathDiagnosticRange asRange() const {
0344 return Range;
0345 }
0346
0347 const Stmt *asStmt() const { assert(isValid()); return S; }
0348 const Stmt *getStmtOrNull() const {
0349 if (!isValid())
0350 return nullptr;
0351 return asStmt();
0352 }
0353
0354 const Decl *asDecl() const { assert(isValid()); return D; }
0355
0356 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
0357
0358 bool hasValidLocation() const { return asLocation().isValid(); }
0359
0360 void invalidate() {
0361 *this = PathDiagnosticLocation();
0362 }
0363
0364 void flatten();
0365
0366 const SourceManager& getManager() const { assert(isValid()); return *SM; }
0367
0368 void Profile(llvm::FoldingSetNodeID &ID) const;
0369
0370 void dump() const;
0371 };
0372
0373 class PathDiagnosticLocationPair {
0374 private:
0375 PathDiagnosticLocation Start, End;
0376
0377 public:
0378 PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
0379 const PathDiagnosticLocation &end)
0380 : Start(start), End(end) {}
0381
0382 const PathDiagnosticLocation &getStart() const { return Start; }
0383 const PathDiagnosticLocation &getEnd() const { return End; }
0384
0385 void setStart(const PathDiagnosticLocation &L) { Start = L; }
0386 void setEnd(const PathDiagnosticLocation &L) { End = L; }
0387
0388 void flatten() {
0389 Start.flatten();
0390 End.flatten();
0391 }
0392
0393 void Profile(llvm::FoldingSetNodeID &ID) const {
0394 Start.Profile(ID);
0395 End.Profile(ID);
0396 }
0397 };
0398
0399
0400
0401
0402
0403 class PathDiagnosticPiece: public llvm::FoldingSetNode {
0404 public:
0405 enum Kind { ControlFlow, Event, Macro, Call, Note, PopUp };
0406 enum DisplayHint { Above, Below };
0407
0408 private:
0409 const std::string str;
0410 const Kind kind;
0411 const DisplayHint Hint;
0412
0413
0414
0415 bool LastInMainSourceFile = false;
0416
0417
0418
0419
0420
0421 StringRef Tag;
0422
0423 std::vector<SourceRange> ranges;
0424 std::vector<FixItHint> fixits;
0425
0426 protected:
0427 PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
0428 PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
0429
0430 public:
0431 PathDiagnosticPiece() = delete;
0432 PathDiagnosticPiece(const PathDiagnosticPiece &) = delete;
0433 PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete;
0434 virtual ~PathDiagnosticPiece();
0435
0436 StringRef getString() const { return str; }
0437
0438
0439 void setTag(const char *tag) { Tag = tag; }
0440
0441
0442 const void *getTag() const { return Tag.data(); }
0443
0444
0445
0446 StringRef getTagStr() const { return Tag; }
0447
0448
0449
0450 DisplayHint getDisplayHint() const { return Hint; }
0451
0452 virtual PathDiagnosticLocation getLocation() const = 0;
0453 virtual void flattenLocations() = 0;
0454
0455 Kind getKind() const { return kind; }
0456
0457 void addRange(SourceRange R) {
0458 if (!R.isValid())
0459 return;
0460 ranges.push_back(R);
0461 }
0462
0463 void addRange(SourceLocation B, SourceLocation E) {
0464 if (!B.isValid() || !E.isValid())
0465 return;
0466 ranges.push_back(SourceRange(B,E));
0467 }
0468
0469 void addFixit(FixItHint F) {
0470 fixits.push_back(F);
0471 }
0472
0473
0474 ArrayRef<SourceRange> getRanges() const { return ranges; }
0475
0476
0477 ArrayRef<FixItHint> getFixits() const { return fixits; }
0478
0479 virtual void Profile(llvm::FoldingSetNodeID &ID) const;
0480
0481 void setAsLastInMainSourceFile() {
0482 LastInMainSourceFile = true;
0483 }
0484
0485 bool isLastInMainSourceFile() const {
0486 return LastInMainSourceFile;
0487 }
0488
0489 virtual void dump() const = 0;
0490 };
0491
0492 using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
0493
0494 class PathPieces : public std::list<PathDiagnosticPieceRef> {
0495 void flattenTo(PathPieces &Primary, PathPieces &Current,
0496 bool ShouldFlattenMacros) const;
0497
0498 public:
0499 PathPieces flatten(bool ShouldFlattenMacros) const {
0500 PathPieces Result;
0501 flattenTo(Result, Result, ShouldFlattenMacros);
0502 return Result;
0503 }
0504
0505 void dump() const;
0506 };
0507
0508 class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
0509 private:
0510 PathDiagnosticLocation Pos;
0511
0512 public:
0513 PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
0514 StringRef s,
0515 PathDiagnosticPiece::Kind k,
0516 bool addPosRange = true)
0517 : PathDiagnosticPiece(s, k), Pos(pos) {
0518 assert(Pos.isValid() && Pos.hasValidLocation() &&
0519 "PathDiagnosticSpotPiece's must have a valid location.");
0520 if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
0521 }
0522
0523 PathDiagnosticLocation getLocation() const override { return Pos; }
0524 void flattenLocations() override { Pos.flatten(); }
0525
0526 void Profile(llvm::FoldingSetNodeID &ID) const override;
0527
0528 static bool classof(const PathDiagnosticPiece *P) {
0529 return P->getKind() == Event || P->getKind() == Macro ||
0530 P->getKind() == Note || P->getKind() == PopUp;
0531 }
0532 };
0533
0534 class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
0535 std::optional<bool> IsPrunable;
0536
0537 public:
0538 PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
0539 StringRef s, bool addPosRange = true)
0540 : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
0541 ~PathDiagnosticEventPiece() override;
0542
0543
0544
0545
0546 void setPrunable(bool isPrunable, bool override = false) {
0547 if (IsPrunable && !override)
0548 return;
0549 IsPrunable = isPrunable;
0550 }
0551
0552
0553 bool isPrunable() const { return IsPrunable.value_or(false); }
0554
0555 void dump() const override;
0556
0557 static bool classof(const PathDiagnosticPiece *P) {
0558 return P->getKind() == Event;
0559 }
0560 };
0561
0562 class PathDiagnosticCallPiece : public PathDiagnosticPiece {
0563 const Decl *Caller;
0564 const Decl *Callee = nullptr;
0565
0566
0567
0568 bool NoExit;
0569
0570
0571
0572 bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
0573
0574
0575
0576 std::string CallStackMessage;
0577
0578 PathDiagnosticCallPiece(const Decl *callerD,
0579 const PathDiagnosticLocation &callReturnPos)
0580 : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
0581 callReturn(callReturnPos) {}
0582 PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
0583 : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
0584 path(oldPath) {}
0585
0586 public:
0587 PathDiagnosticLocation callEnter;
0588 PathDiagnosticLocation callEnterWithin;
0589 PathDiagnosticLocation callReturn;
0590 PathPieces path;
0591
0592 ~PathDiagnosticCallPiece() override;
0593
0594 const Decl *getCaller() const { return Caller; }
0595
0596 const Decl *getCallee() const { return Callee; }
0597 void setCallee(const CallEnter &CE, const SourceManager &SM);
0598
0599 bool hasCallStackMessage() { return !CallStackMessage.empty(); }
0600 void setCallStackMessage(StringRef st) { CallStackMessage = std::string(st); }
0601
0602 PathDiagnosticLocation getLocation() const override { return callEnter; }
0603
0604 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
0605 std::shared_ptr<PathDiagnosticEventPiece>
0606 getCallEnterWithinCallerEvent() const;
0607 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
0608
0609 void flattenLocations() override {
0610 callEnter.flatten();
0611 callReturn.flatten();
0612 for (const auto &I : path)
0613 I->flattenLocations();
0614 }
0615
0616 static std::shared_ptr<PathDiagnosticCallPiece>
0617 construct(const CallExitEnd &CE,
0618 const SourceManager &SM);
0619
0620 static PathDiagnosticCallPiece *construct(PathPieces &pieces,
0621 const Decl *caller);
0622
0623 void dump() const override;
0624
0625 void Profile(llvm::FoldingSetNodeID &ID) const override;
0626
0627 static bool classof(const PathDiagnosticPiece *P) {
0628 return P->getKind() == Call;
0629 }
0630 };
0631
0632 class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
0633 std::vector<PathDiagnosticLocationPair> LPairs;
0634
0635 public:
0636 PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
0637 const PathDiagnosticLocation &endPos,
0638 StringRef s)
0639 : PathDiagnosticPiece(s, ControlFlow) {
0640 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
0641 }
0642
0643 PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
0644 const PathDiagnosticLocation &endPos)
0645 : PathDiagnosticPiece(ControlFlow) {
0646 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
0647 }
0648
0649 ~PathDiagnosticControlFlowPiece() override;
0650
0651 PathDiagnosticLocation getStartLocation() const {
0652 assert(!LPairs.empty() &&
0653 "PathDiagnosticControlFlowPiece needs at least one location.");
0654 return LPairs[0].getStart();
0655 }
0656
0657 PathDiagnosticLocation getEndLocation() const {
0658 assert(!LPairs.empty() &&
0659 "PathDiagnosticControlFlowPiece needs at least one location.");
0660 return LPairs[0].getEnd();
0661 }
0662
0663 void setStartLocation(const PathDiagnosticLocation &L) {
0664 LPairs[0].setStart(L);
0665 }
0666
0667 void setEndLocation(const PathDiagnosticLocation &L) {
0668 LPairs[0].setEnd(L);
0669 }
0670
0671 void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
0672
0673 PathDiagnosticLocation getLocation() const override {
0674 return getStartLocation();
0675 }
0676
0677 using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
0678
0679 iterator begin() { return LPairs.begin(); }
0680 iterator end() { return LPairs.end(); }
0681
0682 void flattenLocations() override {
0683 for (auto &I : *this)
0684 I.flatten();
0685 }
0686
0687 using const_iterator =
0688 std::vector<PathDiagnosticLocationPair>::const_iterator;
0689
0690 const_iterator begin() const { return LPairs.begin(); }
0691 const_iterator end() const { return LPairs.end(); }
0692
0693 static bool classof(const PathDiagnosticPiece *P) {
0694 return P->getKind() == ControlFlow;
0695 }
0696
0697 void dump() const override;
0698
0699 void Profile(llvm::FoldingSetNodeID &ID) const override;
0700 };
0701
0702 class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
0703 public:
0704 PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
0705 : PathDiagnosticSpotPiece(pos, "", Macro) {}
0706 ~PathDiagnosticMacroPiece() override;
0707
0708 PathPieces subPieces;
0709
0710 void flattenLocations() override {
0711 PathDiagnosticSpotPiece::flattenLocations();
0712 for (const auto &I : subPieces)
0713 I->flattenLocations();
0714 }
0715
0716 static bool classof(const PathDiagnosticPiece *P) {
0717 return P->getKind() == Macro;
0718 }
0719
0720 void dump() const override;
0721
0722 void Profile(llvm::FoldingSetNodeID &ID) const override;
0723 };
0724
0725 class PathDiagnosticNotePiece: public PathDiagnosticSpotPiece {
0726 public:
0727 PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S,
0728 bool AddPosRange = true)
0729 : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
0730 ~PathDiagnosticNotePiece() override;
0731
0732 static bool classof(const PathDiagnosticPiece *P) {
0733 return P->getKind() == Note;
0734 }
0735
0736 void dump() const override;
0737
0738 void Profile(llvm::FoldingSetNodeID &ID) const override;
0739 };
0740
0741 class PathDiagnosticPopUpPiece: public PathDiagnosticSpotPiece {
0742 public:
0743 PathDiagnosticPopUpPiece(const PathDiagnosticLocation &Pos, StringRef S,
0744 bool AddPosRange = true)
0745 : PathDiagnosticSpotPiece(Pos, S, PopUp, AddPosRange) {}
0746 ~PathDiagnosticPopUpPiece() override;
0747
0748 static bool classof(const PathDiagnosticPiece *P) {
0749 return P->getKind() == PopUp;
0750 }
0751
0752 void dump() const override;
0753
0754 void Profile(llvm::FoldingSetNodeID &ID) const override;
0755 };
0756
0757
0758 using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
0759
0760
0761
0762
0763 class PathDiagnostic : public llvm::FoldingSetNode {
0764 std::string CheckerName;
0765 const Decl *DeclWithIssue;
0766 std::string BugType;
0767 std::string VerboseDesc;
0768 std::string ShortDesc;
0769 std::string Category;
0770 std::deque<std::string> OtherDesc;
0771
0772
0773 PathDiagnosticLocation Loc;
0774
0775 PathPieces pathImpl;
0776 SmallVector<PathPieces *, 3> pathStack;
0777
0778
0779
0780 PathDiagnosticLocation UniqueingLoc;
0781 const Decl *UniqueingDecl;
0782
0783
0784 const Decl *AnalysisEntryPoint = nullptr;
0785
0786
0787 std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
0788
0789 public:
0790 PathDiagnostic() = delete;
0791 PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
0792 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
0793 StringRef category, PathDiagnosticLocation LocationToUnique,
0794 const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
0795 std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
0796 ~PathDiagnostic();
0797
0798 const PathPieces &path;
0799
0800
0801
0802 PathPieces &getActivePath() {
0803 if (pathStack.empty())
0804 return pathImpl;
0805 return *pathStack.back();
0806 }
0807
0808
0809 PathPieces &getMutablePieces() {
0810 return pathImpl;
0811 }
0812
0813
0814 unsigned full_size();
0815
0816 void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
0817 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
0818
0819 bool isWithinCall() const { return !pathStack.empty(); }
0820
0821 void setEndOfPath(PathDiagnosticPieceRef EndPiece) {
0822 assert(!Loc.isValid() && "End location already set!");
0823 Loc = EndPiece->getLocation();
0824 assert(Loc.isValid() && "Invalid location for end-of-path piece");
0825 getActivePath().push_back(std::move(EndPiece));
0826 }
0827
0828 void appendToDesc(StringRef S) {
0829 if (!ShortDesc.empty())
0830 ShortDesc += S;
0831 VerboseDesc += S;
0832 }
0833
0834 StringRef getVerboseDescription() const { return VerboseDesc; }
0835
0836 StringRef getShortDescription() const {
0837 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
0838 }
0839
0840 StringRef getCheckerName() const { return CheckerName; }
0841 StringRef getBugType() const { return BugType; }
0842 StringRef getCategory() const { return Category; }
0843
0844 using meta_iterator = std::deque<std::string>::const_iterator;
0845
0846 meta_iterator meta_begin() const { return OtherDesc.begin(); }
0847 meta_iterator meta_end() const { return OtherDesc.end(); }
0848 void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }
0849
0850 const FilesToLineNumsMap &getExecutedLines() const {
0851 return *ExecutedLines;
0852 }
0853
0854 FilesToLineNumsMap &getExecutedLines() {
0855 return *ExecutedLines;
0856 }
0857
0858
0859 const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }
0860
0861
0862
0863
0864 const Decl *getDeclWithIssue() const { return DeclWithIssue; }
0865
0866 void setDeclWithIssue(const Decl *D) {
0867 DeclWithIssue = D;
0868 }
0869
0870 PathDiagnosticLocation getLocation() const {
0871 return Loc;
0872 }
0873
0874 void setLocation(PathDiagnosticLocation NewLoc) {
0875 Loc = NewLoc;
0876 }
0877
0878
0879 PathDiagnosticLocation getUniqueingLoc() const {
0880 return UniqueingLoc;
0881 }
0882
0883
0884 const Decl *getUniqueingDecl() const {
0885 return UniqueingDecl;
0886 }
0887
0888 void flattenLocations() {
0889 Loc.flatten();
0890 for (const auto &I : pathImpl)
0891 I->flattenLocations();
0892 }
0893
0894
0895
0896
0897
0898 void Profile(llvm::FoldingSetNodeID &ID) const;
0899
0900
0901
0902
0903
0904 void FullProfile(llvm::FoldingSetNodeID &ID) const;
0905 };
0906
0907 }
0908 }
0909
0910 #endif