36 #include "llvm/ADT/ArrayRef.h" 37 #include "llvm/ADT/FoldingSet.h" 38 #include "llvm/ADT/None.h" 39 #include "llvm/ADT/Optional.h" 40 #include "llvm/ADT/STLExtras.h" 41 #include "llvm/ADT/SmallString.h" 42 #include "llvm/ADT/SmallVector.h" 43 #include "llvm/ADT/StringExtras.h" 44 #include "llvm/ADT/StringRef.h" 45 #include "llvm/Support/Casting.h" 46 #include "llvm/Support/ErrorHandling.h" 47 #include "llvm/Support/raw_ostream.h" 54 using namespace clang;
59 if (isa<PathDiagnosticEventPiece>(*
P))
61 if (
const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(
P.get()))
62 if (MP->containsEvent())
69 for (StringRef::size_type i = s.size(); i != 0; --i)
71 return s.substr(0, i);
80 : kind(k), Hint(hint) {}
94 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
95 bool ShouldFlattenMacros)
const {
96 for (
auto &Piece : *
this) {
97 switch (Piece->getKind()) {
99 auto &
Call = cast<PathDiagnosticCallPiece>(*Piece);
102 Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
103 if (
auto callExit =
Call.getCallExitEvent())
104 Current.push_back(std::move(callExit));
108 auto &
Macro = cast<PathDiagnosticMacroPiece>(*Piece);
109 if (ShouldFlattenMacros) {
110 Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
112 Current.push_back(Piece);
114 Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
116 Macro.subPieces = NewPath;
123 Current.push_back(Piece);
132 StringRef CheckName,
const Decl *declWithIssue, StringRef bugtype,
133 StringRef verboseDesc, StringRef shortDesc, StringRef category,
134 PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique,
135 std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
136 : CheckName(CheckName), DeclWithIssue(declWithIssue),
141 UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
144 static PathDiagnosticCallPiece *
154 "The call piece should not be in a header file.");
160 const PathPieces &Path = CP->path;
166 if (
auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
183 if (
auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
187 CP->setAsLastInMainSourceFile();
190 const auto *ND = dyn_cast<
NamedDecl>(CP->getCallee());
193 llvm::raw_svector_ostream os(buf);
194 os <<
" (within a call to '" << ND->getDeclName() <<
"')";
195 appendToDesc(os.str());
199 DeclWithIssue = CP->getCaller();
200 Loc = CP->getLocation();
207 void PathDiagnosticConsumer::anchor() {}
211 for (
auto &
Diag : Diags)
216 std::unique_ptr<PathDiagnostic> D) {
217 if (!D || D->path.empty())
223 D->flattenLocations();
227 if (!supportsCrossFileDiagnostics()) {
230 const SourceManager &SMgr = D->path.front()->getLocation().getManager();
232 WorkList.push_back(&D->path);
234 llvm::raw_svector_ostream warning(buf);
235 warning <<
"warning: Path diagnostic report is not generated. Current " 236 <<
"output format does not support diagnostics that cross file " 237 <<
"boundaries. Refer to --analyzer-output for valid output " 240 while (!WorkList.empty()) {
241 const PathPieces &path = *WorkList.pop_back_val();
243 for (
const auto &I : path) {
250 llvm::errs() << warning.str();
256 for (
const auto &I : Ranges) {
259 llvm::errs() << warning.str();
264 llvm::errs() << warning.str();
269 if (
const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
270 WorkList.push_back(&call->path);
271 else if (
const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
272 WorkList.push_back(¯o->subPieces);
281 llvm::FoldingSetNodeID profile;
283 void *InsertPos =
nullptr;
285 if (
PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
290 const unsigned orig_size = orig->full_size();
291 const unsigned new_size = D->full_size();
292 if (orig_size <= new_size)
295 assert(orig != D.get());
296 Diags.RemoveNode(orig);
300 Diags.InsertNode(D.release());
307 const PathDiagnosticControlFlowPiece &Y) {
325 const PathDiagnosticCallPiece &Y) {
332 if (X_CEWL != Y_CEWL)
343 if (X.getKind() != Y.getKind())
344 return X.getKind() < Y.getKind();
351 if (X.getString() != Y.getString())
352 return X.getString() < Y.getString();
354 if (X.getRanges().size() != Y.getRanges().size())
355 return X.getRanges().size() < Y.getRanges().size();
359 for (
unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
369 switch (X.getKind()) {
372 cast<PathDiagnosticControlFlowPiece>(Y));
378 cast<PathDiagnosticMacroPiece>(Y));
380 return compareCall(cast<PathDiagnosticCallPiece>(X),
381 cast<PathDiagnosticCallPiece>(Y));
383 llvm_unreachable(
"all cases handled");
387 if (X.size() != Y.size())
388 return X.size() < Y.size();
390 PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
391 PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
393 for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
415 return NameCmp == -1;
420 static bool compare(
const PathDiagnostic &X,
const PathDiagnostic &Y) {
425 if (X.getBugType() != Y.getBugType())
426 return X.getBugType() < Y.getBugType();
427 if (X.getCategory() != Y.getCategory())
428 return X.getCategory() < Y.getCategory();
429 if (X.getVerboseDescription() != Y.getVerboseDescription())
430 return X.getVerboseDescription() < Y.getVerboseDescription();
431 if (X.getShortDescription() != Y.getShortDescription())
432 return X.getShortDescription() < Y.getShortDescription();
433 if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
434 const Decl *XD = X.getDeclWithIssue();
437 const Decl *YD = Y.getDeclWithIssue();
450 if (XE - XI != YE - YI)
451 return (XE - XI) < (YE - YI);
452 for ( ; XI != XE ; ++XI, ++YI) {
454 return (*XI) < (*YI);
457 assert(b.hasValue());
468 std::vector<const PathDiagnostic *> BatchDiags;
469 for (
const auto &D : Diags)
470 BatchDiags.push_back(&D);
476 assert(*X != *Y &&
"PathDiagnostics not uniqued!");
479 assert(
compare(**Y, **X) &&
"Not a total order!");
482 array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
484 FlushDiagnosticsImpl(BatchDiags, Files);
487 for (
const auto D : BatchDiags)
496 Entry.~PDFileEntry();
500 StringRef ConsumerName,
501 StringRef FileName) {
502 llvm::FoldingSetNodeID
NodeID;
505 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
509 Set.InsertNode(Entry, InsertPos);
513 char *FileName_cstr = (
char*) Alloc.Allocate(FileName.size(), 1);
514 memcpy(FileName_cstr, FileName.data(), FileName.size());
516 Entry->
files.push_back(std::make_pair(ConsumerName,
517 StringRef(FileName_cstr,
523 llvm::FoldingSetNodeID
NodeID;
526 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
529 return &Entry->
files;
538 bool UseEnd =
false) {
540 assert(!LAC.isNull() &&
"A valid LocationContext or AnalysisDeclContext should " 541 "be passed to PathDiagnosticLocation upon creation.");
556 Parent = PM.getParent(Parent);
578 static PathDiagnosticLocation
608 if (
const Stmt *CallerBody = CallerInfo->
getBody())
626 llvm_unreachable(
"not yet implemented!");
629 llvm_unreachable(
"CFGElement kind should not be on callsite!");
632 llvm_unreachable(
"Unknown CFGElement kind");
635 PathDiagnosticLocation
653 if (
const auto *CS = dyn_cast<CompoundStmt>(S))
654 return createEndBrace(CS, SM);
696 if (
const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->
getDecl()->
getBody()))
697 if (!CS->body_empty()) {
715 const Stmt* S =
nullptr;
717 const CFGBlock *BSrc = BE->getSrc();
732 CE->getLocationContext(),
736 CEE->getLocationContext(),
739 CFGElement BlockFront = BE->getBlock()->front();
744 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
746 llvm_unreachable(
"Unexpected CFG element at front of block");
748 llvm_unreachable(
"Unexpected ProgramPoint");
758 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
759 while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
762 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
780 return SP->getStmt();
782 return BE->getSrc()->getTerminator();
784 return CE->getCallExpr();
786 return CEE->getCalleeContext()->getCallSite();
788 return PIPP->getInitializer()->getInit();
790 return CEB->getReturnStmt();
792 return FEP->getStmt();
799 if (
const Stmt *S = getStmt(N)) {
803 case Stmt::ChooseExprClass:
804 case Stmt::BinaryConditionalOperatorClass:
805 case Stmt::ConditionalOperatorClass:
807 case Stmt::BinaryOperatorClass: {
809 if (Op == BO_LAnd || Op == BO_LOr)
827 assert(N &&
"Cannot create a location with a null node.");
828 const Stmt *S = getStmt(N);
846 if (
const auto *ME = dyn_cast<MemberExpr>(S))
850 if (
const auto *B = dyn_cast<BinaryOperator>(S))
885 const_cast<SourceManager&>(*SM));
907 const Stmt *S = asStmt();
911 case Stmt::DeclStmtClass: {
912 const auto *DS = cast<DeclStmt>(S);
913 if (DS->isSingleDecl()) {
916 DS->getSingleDecl()->getLocation());
922 case Stmt::IfStmtClass:
923 case Stmt::WhileStmtClass:
924 case Stmt::DoStmtClass:
925 case Stmt::ForStmtClass:
926 case Stmt::ChooseExprClass:
927 case Stmt::IndirectGotoStmtClass:
928 case Stmt::SwitchStmtClass:
929 case Stmt::BinaryConditionalOperatorClass:
930 case Stmt::ConditionalOperatorClass:
931 case Stmt::ObjCForCollectionStmtClass: {
942 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
943 return MD->getSourceRange();
944 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
945 if (
Stmt *Body = FD->getBody())
946 return Body->getSourceRange();
963 else if (K == DeclK) {
974 std::shared_ptr<PathDiagnosticCallPiece>
981 return std::shared_ptr<PathDiagnosticCallPiece>(
987 const Decl *caller) {
988 std::shared_ptr<PathDiagnosticCallPiece> C(
992 path.push_front(std::move(C));
1010 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1011 IsCalleeAnAutosynthesizedPropertyAccessor = (
1012 MD->isPropertyAccessor() &&
1019 StringRef Prefix = StringRef(),
1020 StringRef Postfix = StringRef());
1026 if (TArg.
getKind() == TemplateArgument::ArgKind::Pack) {
1036 StringRef Prefix, StringRef Postfix) {
1041 for (
int I = 0,
Last = TAList.size() - 1; I !=
Last; ++I) {
1050 StringRef Prefix = StringRef()) {
1053 Out << Prefix <<
'\'' << *D;
1054 if (
const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1056 D->getASTContext().getLangOpts(),
"<",
">");
1062 bool ExtendedDescription,
1063 StringRef Prefix = StringRef()) {
1067 if (isa<BlockDecl>(D)) {
1068 if (ExtendedDescription)
1069 Out << Prefix <<
"anonymous block";
1070 return ExtendedDescription;
1073 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1075 if (ExtendedDescription && !MD->isUserProvided()) {
1076 if (MD->isExplicitlyDefaulted())
1077 Out <<
"defaulted ";
1082 if (
const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1083 if (CD->isDefaultConstructor())
1085 else if (CD->isCopyConstructor())
1087 else if (CD->isMoveConstructor())
1090 Out <<
"constructor";
1092 }
else if (isa<CXXDestructorDecl>(MD)) {
1093 if (!MD->isUserProvided()) {
1094 Out <<
"destructor";
1098 Out <<
"'" << *MD <<
"'";
1100 }
else if (MD->isCopyAssignmentOperator()) {
1101 Out <<
"copy assignment operator";
1103 }
else if (MD->isMoveAssignmentOperator()) {
1104 Out <<
"move assignment operator";
1107 if (MD->getParent()->getIdentifier())
1108 Out <<
"'" << *MD->getParent() <<
"::" << *MD <<
"'";
1110 Out <<
"'" << *MD <<
"'";
1116 Out << Prefix << '\'' << cast<NamedDecl>(*D);
1119 if (
const auto FD = dyn_cast<FunctionDecl>(D))
1121 FD->getTemplateSpecializationArgs())
1123 FD->getASTContext().getLangOpts(),
"<",
">");
1129 std::shared_ptr<PathDiagnosticEventPiece>
1135 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1139 llvm::raw_svector_ostream Out(buf);
1144 assert(callEnter.asLocation().isValid());
1145 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1148 std::shared_ptr<PathDiagnosticEventPiece>
1150 if (!callEnterWithin.asLocation().isValid())
1152 if (Callee->isImplicit() || !Callee->hasBody())
1154 if (
const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1155 if (MD->isDefaulted())
1159 llvm::raw_svector_ostream Out(buf);
1161 Out <<
"Entered call";
1164 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1167 std::shared_ptr<PathDiagnosticEventPiece>
1173 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1177 llvm::raw_svector_ostream Out(buf);
1179 if (!CallStackMessage.empty()) {
1180 Out << CallStackMessage;
1186 Out <<
"Returning to caller";
1189 assert(callReturn.asLocation().isValid());
1190 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1194 for (
const auto &I : pieces) {
1196 if (
const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1214 ID.AddInteger(
Range.getBegin().getRawEncoding());
1215 ID.AddInteger(
Range.getEnd().getRawEncoding());
1216 ID.AddInteger(
Loc.getRawEncoding());
1220 ID.AddInteger((
unsigned)
getKind());
1225 for (
const auto &I : Ranges) {
1226 ID.AddInteger(I.getBegin().getRawEncoding());
1227 ID.AddInteger(I.getEnd().getRawEncoding());
1233 for (
const auto &I : path)
1244 for (
const auto &I : *
this)
1261 ID.AddString(VerboseDesc);
1267 for (
const auto &I : path)
1269 for (
meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1277 return getMessageForSymbolNotFound();
1284 const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1289 unsigned ArgIndex = 0;
1291 E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1297 return getMessageForArg(*I, ArgIndex);
1303 if ((*I)->getType()->isVoidPointerType())
1308 return getMessageForArg(*I, ArgIndex);
1316 if (RetSym == Sym) {
1317 return getMessageForReturn(CE);
1320 return getMessageForSymbolNotFound();
1324 unsigned ArgIndex) {
1329 llvm::raw_svector_ostream os(buf);
1331 os << Msg <<
" via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1339 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1340 llvm::errs() <<
"[" << index++ <<
"] ";
1342 llvm::errs() <<
"\n";
1347 llvm::errs() <<
"CALL\n--------------\n";
1351 else if (
const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1352 llvm::errs() << *ND <<
"\n";
1358 llvm::errs() <<
"EVENT\n--------------\n";
1360 llvm::errs() <<
" ---- at ----\n";
1365 llvm::errs() <<
"CONTROL\n--------------\n";
1366 getStartLocation().dump();
1367 llvm::errs() <<
" ---- to ----\n";
1368 getEndLocation().dump();
1372 llvm::errs() <<
"MACRO\n--------------\n";
1377 llvm::errs() <<
"NOTE\n--------------\n";
1379 llvm::errs() <<
" ---- at ----\n";
1385 llvm::errs() <<
"<INVALID>\n";
1392 llvm::errs() <<
"<range>\n";
1395 asLocation().dump();
1396 llvm::errs() <<
"\n";
1402 llvm::errs() <<
"<NULL STMT>\n";
1405 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1406 llvm::errs() << *ND <<
"\n";
1407 else if (isa<BlockDecl>(D))
1409 llvm::errs() <<
"<block>\n";
1411 llvm::errs() <<
"<unknown decl>\n";
1413 llvm::errs() <<
"<NULL DECL>\n";
SourceLocation getRBracLoc() const
Represents C++ allocator call.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Expr * getInit() const
Get the initializer.
static Optional< bool > compareMacro(const PathDiagnosticMacroPiece &X, const PathDiagnosticMacroPiece &Y)
const Stmt * getStmt() const
Stmt * getBody() const
Get the body of the Declaration.
ArrayRef< TemplateArgument > getPackAsArray() const
Return the array of arguments in this template argument pack.
Defines the clang::FileManager interface and associated types.
~PathDiagnosticMacroPiece() override
static void compute_path_size(const PathPieces &pieces, unsigned &size)
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
FullSourceLoc getExpansionLoc() const
Stmt - This represents one statement.
virtual ~PathDiagnosticPiece()
C Language Family Type Representation.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Represents a point when we begin processing an inlined call.
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
SourceLocation getBeginLoc() const LLVM_READONLY
~PathDiagnosticEventPiece() override
Defines the C++ template declaration subclasses.
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Represents C++ object destructor generated from a call to delete.
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: 'Msg via Nth parameter'.
void Profile(llvm::FoldingSetNodeID &ID) const
A Range represents the closed range [from, to].
Represents a program point just before an implicit call event.
SourceLocation getEndLoc() const LLVM_READONLY
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
virtual ~StackHintGenerator()=0
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
const ProgramStateRef & getState() const
void dump() const override
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
SourceLocation getColonLoc() const
const Stmt * getTriggerStmt() const
Describes how types, statements, expressions, and declarations should be printed. ...
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
Defines the clang::Expr interface and subclasses for C++ expressions.
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
SourceLocation getBeginLoc() const LLVM_READONLY
AnalysisDeclContext contains the context data for the function or method under analysis.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
void dump() const override
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
~PathDiagnosticControlFlowPiece() override
static bool isInCodeFile(SourceLocation SL, const SourceManager &SM)
virtual ~PathDiagnosticConsumer()
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Represents a point when we start the call exit sequence (for inlined call).
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
llvm::DOTGraphTraits< ExplodedGraph * > DefaultDOTGraphTraits const ExplodedNode const ExplodedNode *Out<< "\l\|";Out<< "StateID: ST"<< State-> NodeID
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
SourceLocation getLBracLoc() const
void Profile(llvm::FoldingSetNodeID &ID) const override
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
A builtin binary operation expression such as "x + y" or "x <= y".
void dump() const override
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...
Represents a point after we ran remove dead bindings AFTER processing the given statement.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static Optional< bool > comparePath(const PathPieces &X, const PathPieces &Y)
virtual PathDiagnosticLocation getLocation() const =0
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEnd=false)
const CFGBlock * getCallSiteBlock() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
CXXCtorInitializer * getInitializer() const
void print(const PrintingPolicy &Policy, raw_ostream &Out) const
Print this template argument to the given output stream.
ConditionalOperator - The ?: ternary operator.
Const iterator for iterating over Stmt * arrays that contain only Expr *.
CompoundStmt - This represents a group of statements like { stmt stmt }.
const Stmt * getCallSite() const
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
Represents a single basic block in a source-level CFG.
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
Represents a point when we finish the call exit sequence (for inlined call).
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
This represents one expression.
Stmt * getTerminatorCondition(bool StripParens=true)
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
std::pair< FileID, unsigned > getDecomposedLoc() const
Decompose the specified location into a raw FileID + Offset pair.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
ExplodedNode * getFirstSucc()
const SourceManager & getManager() const
const SourceManager & getManager() const
static PathDiagnosticLocation getLocationForCaller(const StackFrameContext *SFC, const LocationContext *CallerCtx, const SourceManager &SM)
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
static void describeTemplateParameters(raw_ostream &Out, const ArrayRef< TemplateArgument > TAList, const LangOptions &LO, StringRef Prefix=StringRef(), StringRef Postfix=StringRef())
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
SourceLocation getEnd() const
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'...
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
PathDiagnosticPiece()=delete
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
SourceLocation getEndLoc() const LLVM_READONLY
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
~PathDiagnosticCallPiece() override
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
Encodes a location in the source.
SourceLocation getOperatorLoc() const
StringRef getName() const
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
void setCallee(const CallEnter &CE, const SourceManager &SM)
Cached information about one file (either on disk or in the virtual file system). ...
std::deque< std::string >::const_iterator meta_iterator
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
std::pair< bool, bool > isInTheSameTranslationUnit(std::pair< FileID, unsigned > &LOffs, std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
static bool describeCodeDecl(raw_ostream &Out, const Decl *D, bool ExtendedDescription, StringRef Prefix=StringRef())
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const Decl * getDecl() const
FullSourceLoc asLocation() const
PathDiagnosticLocation getLocation() const override
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
void dump() const override
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a template argument.
ConsumerFiles files
A vector of <consumer,file> pairs.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
Represents a program point just after an implicit call event.
virtual void Profile(llvm::FoldingSetNodeID &ID) const
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, StringRef Prefix=StringRef())
const StackFrameContext * getCalleeContext() const
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
const StackFrameContext * getCalleeContext() const
StmtClass getStmtClass() const
static Optional< bool > compareCall(const PathDiagnosticCallPiece &X, const PathDiagnosticCallPiece &Y)
void Profile(llvm::FoldingSetNodeID &ID) const override
const Decl * getDecl() const
const CXXDeleteExpr * getDeleteExpr() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
void dump() const
Dumps the specified AST fragment and all subtrees to llvm::errs().
unsigned getIndex() const
static void describeTemplateParameter(raw_ostream &Out, const TemplateArgument &TArg, const LangOptions &LO)
const LocationContext * getLocationContext() const
void Profile(llvm::FoldingSetNodeID &ID) const override
static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)
A template argument list.
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
const CXXNewExpr * getAllocatorExpr() const
ArgKind getKind() const
Return the kind of stored template argument.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
void dump() const override
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
Represents a top-level expression in a basic block.
static StringRef StripTrailingDots(StringRef s)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
void Profile(llvm::FoldingSetNodeID &ID) const override
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
Represents C++ base or member initializer from constructor's initialization list. ...
~PathDiagnosticNotePiece() override
bool containsEvent() const
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalysisDeclContext * getAnalysisDeclContext() const
StringRef getString() const
SourceLocation getBegin() const
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
SourceLocation getLocation() const
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override