35 #include "llvm/ADT/ArrayRef.h" 36 #include "llvm/ADT/FoldingSet.h" 37 #include "llvm/ADT/None.h" 38 #include "llvm/ADT/Optional.h" 39 #include "llvm/ADT/STLExtras.h" 40 #include "llvm/ADT/SmallString.h" 41 #include "llvm/ADT/SmallVector.h" 42 #include "llvm/ADT/StringExtras.h" 43 #include "llvm/ADT/StringRef.h" 44 #include "llvm/Support/Casting.h" 45 #include "llvm/Support/ErrorHandling.h" 46 #include "llvm/Support/raw_ostream.h" 53 using namespace clang;
58 if (isa<PathDiagnosticEventPiece>(*
P))
60 if (
const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(
P.get()))
61 if (MP->containsEvent())
68 for (StringRef::size_type
i = s.size();
i != 0; --
i)
70 return s.substr(0,
i);
79 : kind(k), Hint(hint) {}
95 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
96 bool ShouldFlattenMacros)
const {
97 for (
auto &Piece : *
this) {
98 switch (Piece->getKind()) {
100 auto &
Call = cast<PathDiagnosticCallPiece>(*Piece);
103 Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
104 if (
auto callExit =
Call.getCallExitEvent())
105 Current.push_back(std::move(callExit));
109 auto &
Macro = cast<PathDiagnosticMacroPiece>(*Piece);
110 if (ShouldFlattenMacros) {
111 Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
113 Current.push_back(Piece);
115 Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
117 Macro.subPieces = NewPath;
125 Current.push_back(Piece);
134 StringRef CheckName,
const Decl *declWithIssue, StringRef bugtype,
135 StringRef verboseDesc, StringRef shortDesc, StringRef category,
136 PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique,
137 std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
138 : CheckName(CheckName), DeclWithIssue(declWithIssue),
143 UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
146 static PathDiagnosticCallPiece *
156 "The call piece should not be in a header file.");
162 const PathPieces &Path = CP->path;
168 if (
auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
185 if (
auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
189 CP->setAsLastInMainSourceFile();
192 const auto *ND = dyn_cast<
NamedDecl>(CP->getCallee());
195 llvm::raw_svector_ostream os(buf);
196 os <<
" (within a call to '" << ND->getDeclName() <<
"')";
197 appendToDesc(os.str());
201 DeclWithIssue = CP->getCaller();
202 Loc = CP->getLocation();
209 void PathDiagnosticConsumer::anchor() {}
213 for (
auto &
Diag : Diags)
218 std::unique_ptr<PathDiagnostic> D) {
219 if (!D || D->path.empty())
225 D->flattenLocations();
229 if (!supportsCrossFileDiagnostics()) {
232 const SourceManager &SMgr = D->path.front()->getLocation().getManager();
234 WorkList.push_back(&D->path);
236 llvm::raw_svector_ostream warning(buf);
237 warning <<
"warning: Path diagnostic report is not generated. Current " 238 <<
"output format does not support diagnostics that cross file " 239 <<
"boundaries. Refer to --analyzer-output for valid output " 242 while (!WorkList.empty()) {
243 const PathPieces &path = *WorkList.pop_back_val();
245 for (
const auto &I : path) {
252 llvm::errs() << warning.str();
258 for (
const auto &I : Ranges) {
261 llvm::errs() << warning.str();
266 llvm::errs() << warning.str();
271 if (
const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
272 WorkList.push_back(&call->path);
273 else if (
const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
274 WorkList.push_back(¯o->subPieces);
283 llvm::FoldingSetNodeID profile;
285 void *InsertPos =
nullptr;
287 if (
PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
292 const unsigned orig_size = orig->full_size();
293 const unsigned new_size = D->full_size();
294 if (orig_size <= new_size)
297 assert(orig != D.get());
298 Diags.RemoveNode(orig);
302 Diags.InsertNode(D.release());
309 const PathDiagnosticControlFlowPiece &Y) {
327 const PathDiagnosticCallPiece &Y) {
334 if (X_CEWL != Y_CEWL)
345 if (X.getKind() != Y.getKind())
346 return X.getKind() < Y.getKind();
353 if (X.getString() != Y.getString())
354 return X.getString() < Y.getString();
356 if (X.getRanges().size() != Y.getRanges().size())
357 return X.getRanges().size() < Y.getRanges().size();
361 for (
unsigned i = 0, n = X.getRanges().size();
i < n; ++
i) {
371 switch (X.getKind()) {
374 cast<PathDiagnosticControlFlowPiece>(Y));
377 cast<PathDiagnosticMacroPiece>(Y));
379 return compareCall(cast<PathDiagnosticCallPiece>(X),
380 cast<PathDiagnosticCallPiece>(Y));
386 llvm_unreachable(
"all cases handled");
390 if (X.size() != Y.size())
391 return X.size() < Y.size();
393 PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
394 PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
396 for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
418 return NameCmp == -1;
423 static bool compare(
const PathDiagnostic &X,
const PathDiagnostic &Y) {
428 if (X.getBugType() != Y.getBugType())
429 return X.getBugType() < Y.getBugType();
430 if (X.getCategory() != Y.getCategory())
431 return X.getCategory() < Y.getCategory();
432 if (X.getVerboseDescription() != Y.getVerboseDescription())
433 return X.getVerboseDescription() < Y.getVerboseDescription();
434 if (X.getShortDescription() != Y.getShortDescription())
435 return X.getShortDescription() < Y.getShortDescription();
436 if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
437 const Decl *XD = X.getDeclWithIssue();
440 const Decl *YD = Y.getDeclWithIssue();
453 if (XE - XI != YE - YI)
454 return (XE - XI) < (YE - YI);
455 for ( ; XI != XE ; ++XI, ++YI) {
457 return (*XI) < (*YI);
460 assert(b.hasValue());
471 std::vector<const PathDiagnostic *> BatchDiags;
472 for (
const auto &D : Diags)
473 BatchDiags.push_back(&D);
479 assert(*X != *Y &&
"PathDiagnostics not uniqued!");
482 assert(
compare(**Y, **X) &&
"Not a total order!");
485 array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
487 FlushDiagnosticsImpl(BatchDiags, Files);
490 for (
const auto D : BatchDiags)
499 Entry.~PDFileEntry();
503 StringRef ConsumerName,
504 StringRef FileName) {
505 llvm::FoldingSetNodeID NodeID;
508 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
512 Set.InsertNode(Entry, InsertPos);
516 char *FileName_cstr = (
char*) Alloc.Allocate(FileName.size(), 1);
517 memcpy(FileName_cstr, FileName.data(), FileName.size());
519 Entry->
files.push_back(std::make_pair(ConsumerName,
520 StringRef(FileName_cstr,
526 llvm::FoldingSetNodeID NodeID;
529 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
532 return &Entry->
files;
541 bool UseEnd =
false) {
543 assert(!LAC.isNull() &&
"A valid LocationContext or AnalysisDeclContext should " 544 "be passed to PathDiagnosticLocation upon creation.");
559 Parent = PM.getParent(Parent);
583 static PathDiagnosticLocation
613 if (
const Stmt *CallerBody = CallerInfo->
getBody())
631 llvm_unreachable(
"not yet implemented!");
634 llvm_unreachable(
"CFGElement kind should not be on callsite!");
637 llvm_unreachable(
"Unknown CFGElement kind");
640 PathDiagnosticLocation
658 if (
const auto *CS = dyn_cast<CompoundStmt>(S))
659 return createEndBrace(CS, SM);
709 if (
const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->
getDecl()->
getBody()))
710 if (!CS->body_empty()) {
728 const Stmt* S =
nullptr;
730 const CFGBlock *BSrc = BE->getSrc();
744 "TerminatorCondition and is not the enrty block of the CFG");
762 CE->getLocationContext(),
766 CEE->getLocationContext(),
769 if (
const ReturnStmt *RS = CEB->getReturnStmt())
771 CEB->getLocationContext());
773 CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
775 CFGElement BlockFront = BE->getBlock()->front();
780 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
782 llvm_unreachable(
"Unexpected CFG element at front of block");
785 FE->getLocationContext());
787 llvm_unreachable(
"Unexpected ProgramPoint");
797 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
798 while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
801 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
819 return SP->getStmt();
821 return BE->getSrc()->getTerminatorStmt();
823 return CE->getCallExpr();
825 return CEE->getCalleeContext()->getCallSite();
827 return PIPP->getInitializer()->getInit();
829 return CEB->getReturnStmt();
831 return FEP->getStmt();
838 if (
const Stmt *S = getStmt(N)) {
842 case Stmt::ChooseExprClass:
843 case Stmt::BinaryConditionalOperatorClass:
844 case Stmt::ConditionalOperatorClass:
846 case Stmt::BinaryOperatorClass: {
848 if (Op == BO_LAnd || Op == BO_LOr)
866 assert(N &&
"Cannot create a location with a null node.");
867 const Stmt *S = getStmt(N);
885 if (
const auto *ME = dyn_cast<MemberExpr>(S))
889 if (
const auto *B = dyn_cast<BinaryOperator>(S))
924 const_cast<SourceManager&>(*SM));
946 const Stmt *S = asStmt();
950 case Stmt::DeclStmtClass: {
951 const auto *DS = cast<DeclStmt>(S);
952 if (DS->isSingleDecl()) {
955 DS->getSingleDecl()->getLocation());
961 case Stmt::IfStmtClass:
962 case Stmt::WhileStmtClass:
963 case Stmt::DoStmtClass:
964 case Stmt::ForStmtClass:
965 case Stmt::ChooseExprClass:
966 case Stmt::IndirectGotoStmtClass:
967 case Stmt::SwitchStmtClass:
968 case Stmt::BinaryConditionalOperatorClass:
969 case Stmt::ConditionalOperatorClass:
970 case Stmt::ObjCForCollectionStmtClass: {
981 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D))
982 return MD->getSourceRange();
983 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
984 if (
Stmt *Body = FD->getBody())
985 return Body->getSourceRange();
1002 else if (K == DeclK) {
1013 std::shared_ptr<PathDiagnosticCallPiece>
1020 return std::shared_ptr<PathDiagnosticCallPiece>(
1026 const Decl *caller) {
1027 std::shared_ptr<PathDiagnosticCallPiece> C(
1031 path.push_front(std::move(C));
1038 Callee = CalleeCtx->
getDecl();
1049 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1050 IsCalleeAnAutosynthesizedPropertyAccessor = (
1051 MD->isPropertyAccessor() &&
1058 StringRef Prefix = StringRef(),
1059 StringRef Postfix = StringRef());
1065 if (TArg.
getKind() == TemplateArgument::ArgKind::Pack) {
1073 const ArrayRef<TemplateArgument> TAList,
1075 StringRef Prefix, StringRef Postfix) {
1080 for (
int I = 0,
Last = TAList.size() - 1; I !=
Last; ++I) {
1089 StringRef Prefix = StringRef()) {
1092 Out << Prefix <<
'\'' << *D;
1093 if (
const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1095 D->getASTContext().getLangOpts(),
"<",
">");
1101 bool ExtendedDescription,
1102 StringRef Prefix = StringRef()) {
1106 if (isa<BlockDecl>(D)) {
1107 if (ExtendedDescription)
1108 Out << Prefix <<
"anonymous block";
1109 return ExtendedDescription;
1112 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1114 if (ExtendedDescription && !MD->isUserProvided()) {
1115 if (MD->isExplicitlyDefaulted())
1116 Out <<
"defaulted ";
1121 if (
const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1122 if (CD->isDefaultConstructor())
1124 else if (CD->isCopyConstructor())
1126 else if (CD->isMoveConstructor())
1129 Out <<
"constructor";
1131 }
else if (isa<CXXDestructorDecl>(MD)) {
1132 if (!MD->isUserProvided()) {
1133 Out <<
"destructor";
1137 Out <<
"'" << *MD <<
"'";
1139 }
else if (MD->isCopyAssignmentOperator()) {
1140 Out <<
"copy assignment operator";
1142 }
else if (MD->isMoveAssignmentOperator()) {
1143 Out <<
"move assignment operator";
1146 if (MD->getParent()->getIdentifier())
1147 Out <<
"'" << *MD->getParent() <<
"::" << *MD <<
"'";
1149 Out <<
"'" << *MD <<
"'";
1155 Out << Prefix << '\'' << cast<NamedDecl>(*D);
1158 if (
const auto FD = dyn_cast<FunctionDecl>(D))
1160 FD->getTemplateSpecializationArgs())
1162 FD->getASTContext().getLangOpts(),
"<",
">");
1168 std::shared_ptr<PathDiagnosticEventPiece>
1174 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1178 llvm::raw_svector_ostream Out(buf);
1183 assert(callEnter.asLocation().isValid());
1184 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1187 std::shared_ptr<PathDiagnosticEventPiece>
1189 if (!callEnterWithin.asLocation().isValid())
1191 if (Callee->isImplicit() || !Callee->hasBody())
1193 if (
const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1194 if (MD->isDefaulted())
1198 llvm::raw_svector_ostream Out(buf);
1200 Out <<
"Entered call";
1203 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1206 std::shared_ptr<PathDiagnosticEventPiece>
1212 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1216 llvm::raw_svector_ostream Out(buf);
1218 if (!CallStackMessage.empty()) {
1219 Out << CallStackMessage;
1225 Out <<
"Returning to caller";
1228 assert(callReturn.asLocation().isValid());
1229 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1233 for (
const auto &I : pieces) {
1235 if (
const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1253 ID.AddInteger(
Range.getBegin().getRawEncoding());
1254 ID.AddInteger(
Range.getEnd().getRawEncoding());
1255 ID.AddInteger(
Loc.getRawEncoding());
1259 ID.AddInteger((
unsigned)
getKind());
1264 for (
const auto &I : Ranges) {
1265 ID.AddInteger(I.getBegin().getRawEncoding());
1266 ID.AddInteger(I.getEnd().getRawEncoding());
1272 for (
const auto &I : path)
1283 for (
const auto &I : *
this)
1304 ID.AddString(VerboseDesc);
1310 for (
const auto &I : path)
1312 for (
meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1320 return getMessageForSymbolNotFound();
1327 const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1332 unsigned ArgIndex = 0;
1334 E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1340 return getMessageForArg(*I, ArgIndex);
1346 if ((*I)->getType()->isVoidPointerType())
1351 return getMessageForArg(*I, ArgIndex);
1359 if (RetSym == Sym) {
1360 return getMessageForReturn(CE);
1363 return getMessageForSymbolNotFound();
1367 unsigned ArgIndex) {
1372 llvm::raw_svector_ostream os(buf);
1374 os << Msg <<
" via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1382 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1383 llvm::errs() <<
"[" << index++ <<
"] ";
1385 llvm::errs() <<
"\n";
1390 llvm::errs() <<
"CALL\n--------------\n";
1394 else if (
const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1395 llvm::errs() << *ND <<
"\n";
1401 llvm::errs() <<
"EVENT\n--------------\n";
1403 llvm::errs() <<
" ---- at ----\n";
1408 llvm::errs() <<
"CONTROL\n--------------\n";
1409 getStartLocation().dump();
1410 llvm::errs() <<
" ---- to ----\n";
1411 getEndLocation().dump();
1415 llvm::errs() <<
"MACRO\n--------------\n";
1420 llvm::errs() <<
"NOTE\n--------------\n";
1422 llvm::errs() <<
" ---- at ----\n";
1427 llvm::errs() <<
"POP-UP\n--------------\n";
1429 llvm::errs() <<
" ---- at ----\n";
1435 llvm::errs() <<
"<INVALID>\n";
1442 llvm::errs() <<
"<range>\n";
1445 asLocation().dump();
1446 llvm::errs() <<
"\n";
1452 llvm::errs() <<
"<NULL STMT>\n";
1455 if (
const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1456 llvm::errs() << *ND <<
"\n";
1457 else if (isa<BlockDecl>(D))
1459 llvm::errs() <<
"<block>\n";
1461 llvm::errs() <<
"<unknown decl>\n";
1463 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)
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.
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)
const StackFrameContext * getCalleeContext() const
StmtClass getStmtClass() const
bool isVirtualBaseBranch() 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.
Iterator for iterating over Stmt * arrays that contain only T *.
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
SourceLocation getBeginLoc() const LLVM_READONLY
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...
CFGTerminator getTerminator() const
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