clang API Documentation
00001 //===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the PathDiagnostic-related interfaces. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H 00015 #define LLVM_CLANG_PATH_DIAGNOSTIC_H 00016 00017 #include "clang/Basic/SourceLocation.h" 00018 #include "clang/Analysis/ProgramPoint.h" 00019 #include "llvm/ADT/FoldingSet.h" 00020 #include "llvm/ADT/IntrusiveRefCntPtr.h" 00021 #include "llvm/ADT/PointerUnion.h" 00022 #include "llvm/ADT/Optional.h" 00023 #include <deque> 00024 #include <iterator> 00025 #include <string> 00026 #include <vector> 00027 00028 namespace clang { 00029 00030 class AnalysisDeclContext; 00031 class BinaryOperator; 00032 class CompoundStmt; 00033 class Decl; 00034 class LocationContext; 00035 class MemberExpr; 00036 class ParentMap; 00037 class ProgramPoint; 00038 class SourceManager; 00039 class Stmt; 00040 00041 namespace ento { 00042 00043 class ExplodedNode; 00044 class SymExpr; 00045 typedef const SymExpr* SymbolRef; 00046 00047 //===----------------------------------------------------------------------===// 00048 // High-level interface for handlers of path-sensitive diagnostics. 00049 //===----------------------------------------------------------------------===// 00050 00051 class PathDiagnostic; 00052 00053 class PathDiagnosticConsumer { 00054 virtual void anchor(); 00055 public: 00056 PathDiagnosticConsumer() : flushed(false) {} 00057 virtual ~PathDiagnosticConsumer(); 00058 00059 void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade); 00060 00061 virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, 00062 SmallVectorImpl<std::string> *FilesMade) 00063 = 0; 00064 00065 virtual StringRef getName() const = 0; 00066 00067 void HandlePathDiagnostic(PathDiagnostic *D); 00068 00069 enum PathGenerationScheme { Minimal, Extensive }; 00070 virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } 00071 virtual bool supportsLogicalOpControlFlow() const { return false; } 00072 virtual bool supportsAllBlockEdges() const { return false; } 00073 virtual bool useVerboseDescription() const { return true; } 00074 00075 /// Return true if the PathDiagnosticConsumer supports individual 00076 /// PathDiagnostics that span multiple files. 00077 virtual bool supportsCrossFileDiagnostics() const { return false; } 00078 00079 protected: 00080 bool flushed; 00081 llvm::FoldingSet<PathDiagnostic> Diags; 00082 }; 00083 00084 //===----------------------------------------------------------------------===// 00085 // Path-sensitive diagnostics. 00086 //===----------------------------------------------------------------------===// 00087 00088 class PathDiagnosticRange : public SourceRange { 00089 public: 00090 bool isPoint; 00091 00092 PathDiagnosticRange(const SourceRange &R, bool isP = false) 00093 : SourceRange(R), isPoint(isP) {} 00094 00095 PathDiagnosticRange() : isPoint(false) {} 00096 }; 00097 00098 typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*> 00099 LocationOrAnalysisDeclContext; 00100 00101 class PathDiagnosticLocation { 00102 private: 00103 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K; 00104 const Stmt *S; 00105 const Decl *D; 00106 const SourceManager *SM; 00107 FullSourceLoc Loc; 00108 PathDiagnosticRange Range; 00109 00110 PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, 00111 Kind kind) 00112 : K(kind), S(0), D(0), SM(&sm), 00113 Loc(genLocation(L)), Range(genRange()) { 00114 assert(Loc.isValid()); 00115 assert(Range.isValid()); 00116 } 00117 00118 FullSourceLoc 00119 genLocation(SourceLocation L = SourceLocation(), 00120 LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; 00121 00122 PathDiagnosticRange 00123 genRange(LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; 00124 00125 public: 00126 /// Create an invalid location. 00127 PathDiagnosticLocation() 00128 : K(SingleLocK), S(0), D(0), SM(0) {} 00129 00130 /// Create a location corresponding to the given statement. 00131 PathDiagnosticLocation(const Stmt *s, 00132 const SourceManager &sm, 00133 LocationOrAnalysisDeclContext lac) 00134 : K(StmtK), S(s), D(0), SM(&sm), 00135 Loc(genLocation(SourceLocation(), lac)), 00136 Range(genRange(lac)) { 00137 assert(S); 00138 assert(Loc.isValid()); 00139 assert(Range.isValid()); 00140 } 00141 00142 /// Create a location corresponding to the given declaration. 00143 PathDiagnosticLocation(const Decl *d, const SourceManager &sm) 00144 : K(DeclK), S(0), D(d), SM(&sm), 00145 Loc(genLocation()), Range(genRange()) { 00146 assert(D); 00147 assert(Loc.isValid()); 00148 assert(Range.isValid()); 00149 } 00150 00151 /// Create a location corresponding to the given declaration. 00152 static PathDiagnosticLocation create(const Decl *D, 00153 const SourceManager &SM) { 00154 return PathDiagnosticLocation(D, SM); 00155 } 00156 00157 /// Create a location for the beginning of the declaration. 00158 static PathDiagnosticLocation createBegin(const Decl *D, 00159 const SourceManager &SM); 00160 00161 /// Create a location for the beginning of the statement. 00162 static PathDiagnosticLocation createBegin(const Stmt *S, 00163 const SourceManager &SM, 00164 const LocationOrAnalysisDeclContext LAC); 00165 00166 /// Create the location for the operator of the binary expression. 00167 /// Assumes the statement has a valid location. 00168 static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, 00169 const SourceManager &SM); 00170 00171 /// For member expressions, return the location of the '.' or '->'. 00172 /// Assumes the statement has a valid location. 00173 static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, 00174 const SourceManager &SM); 00175 00176 /// Create a location for the beginning of the compound statement. 00177 /// Assumes the statement has a valid location. 00178 static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, 00179 const SourceManager &SM); 00180 00181 /// Create a location for the end of the compound statement. 00182 /// Assumes the statement has a valid location. 00183 static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, 00184 const SourceManager &SM); 00185 00186 /// Create a location for the beginning of the enclosing declaration body. 00187 /// Defaults to the beginning of the first statement in the declaration body. 00188 static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, 00189 const SourceManager &SM); 00190 00191 /// Constructs a location for the end of the enclosing declaration body. 00192 /// Defaults to the end of brace. 00193 static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, 00194 const SourceManager &SM); 00195 00196 /// Create a location corresponding to the given valid ExplodedNode. 00197 static PathDiagnosticLocation create(const ProgramPoint& P, 00198 const SourceManager &SMng); 00199 00200 /// Create a location corresponding to the next valid ExplodedNode as end 00201 /// of path location. 00202 static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N, 00203 const SourceManager &SM); 00204 00205 /// Convert the given location into a single kind location. 00206 static PathDiagnosticLocation createSingleLocation( 00207 const PathDiagnosticLocation &PDL); 00208 00209 bool operator==(const PathDiagnosticLocation &X) const { 00210 return K == X.K && Loc == X.Loc && Range == X.Range; 00211 } 00212 00213 bool operator!=(const PathDiagnosticLocation &X) const { 00214 return !(*this == X); 00215 } 00216 00217 bool isValid() const { 00218 return SM != 0; 00219 } 00220 00221 FullSourceLoc asLocation() const { 00222 return Loc; 00223 } 00224 00225 PathDiagnosticRange asRange() const { 00226 return Range; 00227 } 00228 00229 const Stmt *asStmt() const { assert(isValid()); return S; } 00230 const Decl *asDecl() const { assert(isValid()); return D; } 00231 00232 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; } 00233 00234 void invalidate() { 00235 *this = PathDiagnosticLocation(); 00236 } 00237 00238 void flatten(); 00239 00240 const SourceManager& getManager() const { assert(isValid()); return *SM; } 00241 00242 void Profile(llvm::FoldingSetNodeID &ID) const; 00243 }; 00244 00245 class PathDiagnosticLocationPair { 00246 private: 00247 PathDiagnosticLocation Start, End; 00248 public: 00249 PathDiagnosticLocationPair(const PathDiagnosticLocation &start, 00250 const PathDiagnosticLocation &end) 00251 : Start(start), End(end) {} 00252 00253 const PathDiagnosticLocation &getStart() const { return Start; } 00254 const PathDiagnosticLocation &getEnd() const { return End; } 00255 00256 void flatten() { 00257 Start.flatten(); 00258 End.flatten(); 00259 } 00260 00261 void Profile(llvm::FoldingSetNodeID &ID) const { 00262 Start.Profile(ID); 00263 End.Profile(ID); 00264 } 00265 }; 00266 00267 //===----------------------------------------------------------------------===// 00268 // Path "pieces" for path-sensitive diagnostics. 00269 //===----------------------------------------------------------------------===// 00270 00271 class PathDiagnosticPiece : public RefCountedBaseVPTR { 00272 public: 00273 enum Kind { ControlFlow, Event, Macro, Call }; 00274 enum DisplayHint { Above, Below }; 00275 00276 private: 00277 const std::string str; 00278 const Kind kind; 00279 const DisplayHint Hint; 00280 std::vector<SourceRange> ranges; 00281 00282 // Do not implement: 00283 PathDiagnosticPiece(); 00284 PathDiagnosticPiece(const PathDiagnosticPiece &P); 00285 PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); 00286 00287 protected: 00288 PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below); 00289 00290 PathDiagnosticPiece(Kind k, DisplayHint hint = Below); 00291 00292 public: 00293 virtual ~PathDiagnosticPiece(); 00294 00295 const std::string& getString() const { return str; } 00296 00297 /// getDisplayHint - Return a hint indicating where the diagnostic should 00298 /// be displayed by the PathDiagnosticConsumer. 00299 DisplayHint getDisplayHint() const { return Hint; } 00300 00301 virtual PathDiagnosticLocation getLocation() const = 0; 00302 virtual void flattenLocations() = 0; 00303 00304 Kind getKind() const { return kind; } 00305 00306 void addRange(SourceRange R) { 00307 if (!R.isValid()) 00308 return; 00309 ranges.push_back(R); 00310 } 00311 00312 void addRange(SourceLocation B, SourceLocation E) { 00313 if (!B.isValid() || !E.isValid()) 00314 return; 00315 ranges.push_back(SourceRange(B,E)); 00316 } 00317 00318 typedef const SourceRange* range_iterator; 00319 00320 range_iterator ranges_begin() const { 00321 return ranges.empty() ? NULL : &ranges[0]; 00322 } 00323 00324 range_iterator ranges_end() const { 00325 return ranges_begin() + ranges.size(); 00326 } 00327 00328 static inline bool classof(const PathDiagnosticPiece *P) { 00329 return true; 00330 } 00331 00332 virtual void Profile(llvm::FoldingSetNodeID &ID) const; 00333 }; 00334 00335 00336 class PathPieces : 00337 public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > { 00338 public: 00339 ~PathPieces(); 00340 }; 00341 00342 class PathDiagnosticSpotPiece : public PathDiagnosticPiece { 00343 private: 00344 PathDiagnosticLocation Pos; 00345 public: 00346 PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, 00347 StringRef s, 00348 PathDiagnosticPiece::Kind k, 00349 bool addPosRange = true) 00350 : PathDiagnosticPiece(s, k), Pos(pos) { 00351 assert(Pos.isValid() && Pos.asLocation().isValid() && 00352 "PathDiagnosticSpotPiece's must have a valid location."); 00353 if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); 00354 } 00355 00356 PathDiagnosticLocation getLocation() const { return Pos; } 00357 virtual void flattenLocations() { Pos.flatten(); } 00358 00359 virtual void Profile(llvm::FoldingSetNodeID &ID) const; 00360 }; 00361 00362 /// \brief Interface for classes constructing Stack hints. 00363 /// 00364 /// If a PathDiagnosticEvent occurs in a different frame than the final 00365 /// diagnostic the hints can be used to summarize the effect of the call. 00366 class StackHintGenerator { 00367 public: 00368 virtual ~StackHintGenerator() = 0; 00369 00370 /// \brief Construct the Diagnostic message for the given ExplodedNode. 00371 virtual std::string getMessage(const ExplodedNode *N) = 0; 00372 }; 00373 00374 /// \brief Constructs a Stack hint for the given symbol. 00375 /// 00376 /// The class knows how to construct the stack hint message based on 00377 /// traversing the CallExpr associated with the call and checking if the given 00378 /// symbol is returned or is one of the arguments. 00379 /// The hint can be customized by redefining 'getMessageForX()' methods. 00380 class StackHintGeneratorForSymbol : public StackHintGenerator { 00381 private: 00382 SymbolRef Sym; 00383 std::string Msg; 00384 00385 public: 00386 StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} 00387 virtual ~StackHintGeneratorForSymbol() {} 00388 00389 /// \brief Search the call expression for the symbol Sym and dispatch the 00390 /// 'getMessageForX()' methods to construct a specific message. 00391 virtual std::string getMessage(const ExplodedNode *N); 00392 00393 /// Prints the ordinal form of the given integer, 00394 /// only valid for ValNo : ValNo > 0. 00395 void printOrdinal(unsigned ValNo, llvm::raw_svector_ostream &Out); 00396 00397 /// Produces the message of the following form: 00398 /// 'Msg via Nth parameter' 00399 virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); 00400 virtual std::string getMessageForReturn(const CallExpr *CallExpr) { 00401 return Msg; 00402 } 00403 virtual std::string getMessageForSymbolNotFound() { 00404 return Msg; 00405 } 00406 }; 00407 00408 class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { 00409 llvm::Optional<bool> IsPrunable; 00410 00411 /// If the event occurs in a different frame than the final diagnostic, 00412 /// supply a message that will be used to construct an extra hint on the 00413 /// returns from all the calls on the stack from this event to the final 00414 /// diagnostic. 00415 llvm::OwningPtr<StackHintGenerator> CallStackHint; 00416 00417 public: 00418 PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, 00419 StringRef s, bool addPosRange = true, 00420 StackHintGenerator *stackHint = 0) 00421 : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), 00422 CallStackHint(stackHint) {} 00423 00424 ~PathDiagnosticEventPiece(); 00425 00426 /// Mark the diagnostic piece as being potentially prunable. This 00427 /// flag may have been previously set, at which point it will not 00428 /// be reset unless one specifies to do so. 00429 void setPrunable(bool isPrunable, bool override = false) { 00430 if (IsPrunable.hasValue() && !override) 00431 return; 00432 IsPrunable = isPrunable; 00433 } 00434 00435 /// Return true if the diagnostic piece is prunable. 00436 bool isPrunable() const { 00437 return IsPrunable.hasValue() ? IsPrunable.getValue() : false; 00438 } 00439 00440 bool hasCallStackHint() { 00441 return (CallStackHint != 0); 00442 } 00443 00444 /// Produce the hint for the given node. The node contains 00445 /// information about the call for which the diagnostic can be generated. 00446 std::string getCallStackMessage(const ExplodedNode *N) { 00447 if (CallStackHint) 00448 return CallStackHint->getMessage(N); 00449 return ""; 00450 } 00451 00452 static inline bool classof(const PathDiagnosticPiece *P) { 00453 return P->getKind() == Event; 00454 } 00455 }; 00456 00457 class PathDiagnosticCallPiece : public PathDiagnosticPiece { 00458 PathDiagnosticCallPiece(const Decl *callerD, 00459 const PathDiagnosticLocation &callReturnPos) 00460 : PathDiagnosticPiece(Call), Caller(callerD), Callee(0), 00461 NoExit(false), callReturn(callReturnPos) {} 00462 00463 PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) 00464 : PathDiagnosticPiece(Call), Caller(caller), Callee(0), 00465 NoExit(true), path(oldPath) {} 00466 00467 const Decl *Caller; 00468 const Decl *Callee; 00469 00470 // Flag signifying that this diagnostic has only call enter and no matching 00471 // call exit. 00472 bool NoExit; 00473 00474 // The custom string, which should appear after the call Return Diagnostic. 00475 // TODO: Should we allow multiple diagnostics? 00476 std::string CallStackMessage; 00477 00478 public: 00479 PathDiagnosticLocation callEnter; 00480 PathDiagnosticLocation callEnterWithin; 00481 PathDiagnosticLocation callReturn; 00482 PathPieces path; 00483 00484 virtual ~PathDiagnosticCallPiece(); 00485 00486 const Decl *getCaller() const { return Caller; } 00487 00488 const Decl *getCallee() const { return Callee; } 00489 void setCallee(const CallEnter &CE, const SourceManager &SM); 00490 00491 bool hasCallStackMessage() { return !CallStackMessage.empty(); } 00492 void setCallStackMessage(StringRef st) { 00493 CallStackMessage = st; 00494 } 00495 00496 virtual PathDiagnosticLocation getLocation() const { 00497 return callEnter; 00498 } 00499 00500 IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const; 00501 IntrusiveRefCntPtr<PathDiagnosticEventPiece> 00502 getCallEnterWithinCallerEvent() const; 00503 IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const; 00504 00505 virtual void flattenLocations() { 00506 callEnter.flatten(); 00507 callReturn.flatten(); 00508 for (PathPieces::iterator I = path.begin(), 00509 E = path.end(); I != E; ++I) (*I)->flattenLocations(); 00510 } 00511 00512 static PathDiagnosticCallPiece *construct(const ExplodedNode *N, 00513 const CallExitEnd &CE, 00514 const SourceManager &SM); 00515 00516 static PathDiagnosticCallPiece *construct(PathPieces &pieces, 00517 const Decl *caller); 00518 00519 virtual void Profile(llvm::FoldingSetNodeID &ID) const; 00520 00521 static inline bool classof(const PathDiagnosticPiece *P) { 00522 return P->getKind() == Call; 00523 } 00524 }; 00525 00526 class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { 00527 std::vector<PathDiagnosticLocationPair> LPairs; 00528 public: 00529 PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, 00530 const PathDiagnosticLocation &endPos, 00531 StringRef s) 00532 : PathDiagnosticPiece(s, ControlFlow) { 00533 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); 00534 } 00535 00536 PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, 00537 const PathDiagnosticLocation &endPos) 00538 : PathDiagnosticPiece(ControlFlow) { 00539 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); 00540 } 00541 00542 ~PathDiagnosticControlFlowPiece(); 00543 00544 PathDiagnosticLocation getStartLocation() const { 00545 assert(!LPairs.empty() && 00546 "PathDiagnosticControlFlowPiece needs at least one location."); 00547 return LPairs[0].getStart(); 00548 } 00549 00550 PathDiagnosticLocation getEndLocation() const { 00551 assert(!LPairs.empty() && 00552 "PathDiagnosticControlFlowPiece needs at least one location."); 00553 return LPairs[0].getEnd(); 00554 } 00555 00556 void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); } 00557 00558 virtual PathDiagnosticLocation getLocation() const { 00559 return getStartLocation(); 00560 } 00561 00562 typedef std::vector<PathDiagnosticLocationPair>::iterator iterator; 00563 iterator begin() { return LPairs.begin(); } 00564 iterator end() { return LPairs.end(); } 00565 00566 virtual void flattenLocations() { 00567 for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); 00568 } 00569 00570 typedef std::vector<PathDiagnosticLocationPair>::const_iterator 00571 const_iterator; 00572 const_iterator begin() const { return LPairs.begin(); } 00573 const_iterator end() const { return LPairs.end(); } 00574 00575 static inline bool classof(const PathDiagnosticPiece *P) { 00576 return P->getKind() == ControlFlow; 00577 } 00578 00579 virtual void Profile(llvm::FoldingSetNodeID &ID) const; 00580 }; 00581 00582 class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { 00583 public: 00584 PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos) 00585 : PathDiagnosticSpotPiece(pos, "", Macro) {} 00586 00587 ~PathDiagnosticMacroPiece(); 00588 00589 PathPieces subPieces; 00590 00591 bool containsEvent() const; 00592 00593 virtual void flattenLocations() { 00594 PathDiagnosticSpotPiece::flattenLocations(); 00595 for (PathPieces::iterator I = subPieces.begin(), 00596 E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); 00597 } 00598 00599 static inline bool classof(const PathDiagnosticPiece *P) { 00600 return P->getKind() == Macro; 00601 } 00602 00603 virtual void Profile(llvm::FoldingSetNodeID &ID) const; 00604 }; 00605 00606 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive 00607 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces, 00608 /// each which represent the pieces of the path. 00609 class PathDiagnostic : public llvm::FoldingSetNode { 00610 const Decl *DeclWithIssue; 00611 std::string BugType; 00612 std::string Desc; 00613 std::string Category; 00614 std::deque<std::string> OtherDesc; 00615 PathPieces pathImpl; 00616 llvm::SmallVector<PathPieces *, 3> pathStack; 00617 00618 PathDiagnostic(); // Do not implement. 00619 public: 00620 const PathPieces &path; 00621 00622 /// Return the path currently used by builders for constructing the 00623 /// PathDiagnostic. 00624 PathPieces &getActivePath() { 00625 if (pathStack.empty()) 00626 return pathImpl; 00627 return *pathStack.back(); 00628 } 00629 00630 /// Return a mutable version of 'path'. 00631 PathPieces &getMutablePieces() { 00632 return pathImpl; 00633 } 00634 00635 /// Return the unrolled size of the path. 00636 unsigned full_size(); 00637 00638 void pushActivePath(PathPieces *p) { pathStack.push_back(p); } 00639 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); } 00640 00641 // PathDiagnostic(); 00642 PathDiagnostic(const Decl *DeclWithIssue, 00643 StringRef bugtype, 00644 StringRef desc, 00645 StringRef category); 00646 00647 ~PathDiagnostic(); 00648 00649 StringRef getDescription() const { return Desc; } 00650 StringRef getBugType() const { return BugType; } 00651 StringRef getCategory() const { return Category; } 00652 00653 /// Return the semantic context where an issue occurred. If the 00654 /// issue occurs along a path, this represents the "central" area 00655 /// where the bug manifests. 00656 const Decl *getDeclWithIssue() const { return DeclWithIssue; } 00657 00658 typedef std::deque<std::string>::const_iterator meta_iterator; 00659 meta_iterator meta_begin() const { return OtherDesc.begin(); } 00660 meta_iterator meta_end() const { return OtherDesc.end(); } 00661 void addMeta(StringRef s) { OtherDesc.push_back(s); } 00662 00663 PathDiagnosticLocation getLocation() const; 00664 00665 void flattenLocations() { 00666 for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); 00667 I != E; ++I) (*I)->flattenLocations(); 00668 } 00669 00670 void Profile(llvm::FoldingSetNodeID &ID) const; 00671 00672 void FullProfile(llvm::FoldingSetNodeID &ID) const; 00673 }; 00674 00675 } // end GR namespace 00676 00677 } //end clang namespace 00678 00679 #endif