45 #include "llvm/ADT/ArrayRef.h"
46 #include "llvm/ADT/DenseMap.h"
47 #include "llvm/ADT/DenseSet.h"
48 #include "llvm/ADT/FoldingSet.h"
49 #include "llvm/ADT/None.h"
50 #include "llvm/ADT/Optional.h"
51 #include "llvm/ADT/STLExtras.h"
52 #include "llvm/ADT/SmallPtrSet.h"
53 #include "llvm/ADT/SmallString.h"
54 #include "llvm/ADT/SmallVector.h"
55 #include "llvm/ADT/Statistic.h"
56 #include "llvm/ADT/StringExtras.h"
57 #include "llvm/ADT/StringRef.h"
58 #include "llvm/ADT/iterator_range.h"
59 #include "llvm/Support/Casting.h"
60 #include "llvm/Support/Compiler.h"
61 #include "llvm/Support/ErrorHandling.h"
62 #include "llvm/Support/MemoryBuffer.h"
63 #include "llvm/Support/raw_ostream.h"
75 using namespace clang;
79 #define DEBUG_TYPE "BugReporter"
82 "The maximum number of bug reports in the same equivalence class");
84 "The maximum number of bug reports in the same equivalence class "
85 "where at least one report is valid (not suppressed)");
89 void BugReporterContext::anchor() {}
99 std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;
103 using VisitorsDiagnosticsTy =
104 llvm::DenseMap<const ExplodedNode *, std::vector<PathDiagnosticPieceRef>>;
108 using LocationContextMap =
109 llvm::DenseMap<const PathPieces *, const LocationContext *>;
114 class PathDiagnosticConstruct {
116 const PathDiagnosticConsumer *Consumer;
119 const ExplodedNode *CurrentNode;
123 LocationContextMap LCM;
130 CallWithEntryStack CallStack;
134 std::unique_ptr<PathDiagnostic> PD;
137 PathDiagnosticConstruct(
const PathDiagnosticConsumer *PDC,
138 const ExplodedNode *ErrorNode,
139 const PathSensitiveBugReport *R);
144 assert(CurrentNode &&
"Already reached the root!");
145 return CurrentNode->getLocationContext();
152 return LCM.find(&PD->getActivePath())->getSecond();
155 const ExplodedNode *getCurrentNode()
const {
return CurrentNode; }
159 bool ascendToPrevNode() {
160 CurrentNode = CurrentNode->getFirstPred();
161 return static_cast<bool>(CurrentNode);
165 return getCurrLocationContext()->getParentMap();
170 const Stmt *getParent(
const Stmt *S)
const {
171 return getParentMap().getParent(S);
174 void updateLocCtxMap(
const PathPieces *Path,
const LocationContext *LC) {
179 const LocationContext *getLocationContextFor(
const PathPieces *Path)
const {
180 assert(LCM.count(Path) &&
181 "Failed to find the context associated with these pieces!");
182 return LCM.find(Path)->getSecond();
185 bool isInLocCtxMap(
const PathPieces *Path)
const {
return LCM.count(Path); }
187 PathPieces &getActivePath() {
return PD->getActivePath(); }
188 PathPieces &getMutablePieces() {
return PD->getMutablePieces(); }
190 bool shouldAddPathEdges()
const {
return Consumer->shouldAddPathEdges(); }
191 bool shouldAddControlNotes()
const {
192 return Consumer->shouldAddControlNotes();
194 bool shouldGenerateDiagnostics()
const {
195 return Consumer->shouldGenerateDiagnostics();
197 bool supportsLogicalOpControlFlow()
const {
198 return Consumer->supportsLogicalOpControlFlow();
206 class PathDiagnosticBuilder :
public BugReporterContext {
208 std::unique_ptr<const ExplodedGraph> BugPath;
213 const PathSensitiveBugReport *R;
216 const ExplodedNode *
const ErrorNode;
219 std::unique_ptr<const VisitorsDiagnosticsTy> VisitorsDiagnostics;
227 PathSensitiveBugReporter &Reporter);
229 PathDiagnosticBuilder(
230 BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
231 PathSensitiveBugReport *r,
const ExplodedNode *ErrorNode,
232 std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics);
244 std::unique_ptr<PathDiagnostic>
245 generate(
const PathDiagnosticConsumer *PDC)
const;
249 const CallWithEntryStack &CallStack)
const;
250 void generatePathDiagnosticsForNode(PathDiagnosticConstruct &C,
251 PathDiagnosticLocation &PrevLoc)
const;
253 void generateMinimalDiagForBlockEdge(PathDiagnosticConstruct &C,
257 generateDiagForGotoOP(
const PathDiagnosticConstruct &C,
const Stmt *S,
258 PathDiagnosticLocation &Start)
const;
261 generateDiagForSwitchOP(
const PathDiagnosticConstruct &C,
const CFGBlock *Dst,
262 PathDiagnosticLocation &Start)
const;
265 generateDiagForBinaryOP(
const PathDiagnosticConstruct &C,
const Stmt *T,
268 PathDiagnosticLocation
269 ExecutionContinues(
const PathDiagnosticConstruct &C)
const;
271 PathDiagnosticLocation
272 ExecutionContinues(llvm::raw_string_ostream &os,
273 const PathDiagnosticConstruct &C)
const;
275 const PathSensitiveBugReport *getBugReport()
const {
return R; }
288 return getMessageForSymbolNotFound();
295 const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
300 unsigned ArgIndex = 0;
302 E = CE->arg_end(); I != E; ++I, ++ArgIndex){
308 return getMessageForArg(*I, ArgIndex);
314 if ((*I)->getType()->isVoidPointerType())
319 return getMessageForArg(*I, ArgIndex);
328 return getMessageForReturn(CE);
331 return getMessageForSymbolNotFound();
339 return (llvm::Twine(Msg) +
" via " + std::to_string(ArgIndex) +
340 llvm::getOrdinalSuffix(ArgIndex) +
" parameter").str();
349 PathDiagnosticEventPiece *Y) {
357 if (
X->getLocation() != Y->getLocation())
360 if (
X->getTag() == tagPreferred && Y->getTag() == tagLesser)
363 if (Y->getTag() == tagPreferred &&
X->getTag() == tagLesser)
375 unsigned N = path.size();
382 for (
unsigned i = 0; i < N; ++i) {
383 auto piece = std::move(path.front());
386 switch (piece->getKind()) {
397 if (
auto *nextEvent =
398 dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
399 auto *
event = cast<PathDiagnosticEventPiece>(piece.get());
403 if (
auto *pieceToKeep =
405 piece = std::move(pieceToKeep == event ? piece : path.front());
417 path.push_back(std::move(piece));
426 const PathSensitiveBugReport *R,
427 bool IsInteresting =
false) {
428 bool containsSomethingInteresting = IsInteresting;
429 const unsigned N = pieces.size();
431 for (
unsigned i = 0 ; i < N ; ++i) {
434 auto piece = std::move(pieces.front());
437 switch (piece->getKind()) {
439 auto &call = cast<PathDiagnosticCallPiece>(*piece);
443 R->isInteresting(C.getLocationContextFor(&call.path))))
446 containsSomethingInteresting =
true;
450 auto &
macro = cast<PathDiagnosticMacroPiece>(*piece);
453 containsSomethingInteresting =
true;
457 auto &
event = cast<PathDiagnosticEventPiece>(*piece);
461 containsSomethingInteresting |= !
event.isPrunable();
470 pieces.push_back(std::move(piece));
473 return containsSomethingInteresting;
478 for (
unsigned int i = 0; i < Path.size(); ++i) {
479 auto Piece = std::move(Path.front());
481 if (!isa<PathDiagnosticPopUpPiece>(*Piece))
482 Path.push_back(std::move(Piece));
497 PathDiagnosticLocation *LastCallLocation =
nullptr) {
498 for (
const auto &I : Pieces) {
499 auto *Call = dyn_cast<PathDiagnosticCallPiece>(I.get());
504 if (LastCallLocation) {
506 if (CallerIsImplicit || !Call->callEnter.asLocation().isValid())
507 Call->callEnter = *LastCallLocation;
508 if (CallerIsImplicit || !Call->callReturn.asLocation().isValid())
509 Call->callReturn = *LastCallLocation;
514 PathDiagnosticLocation *ThisCallLocation;
515 if (Call->callEnterWithin.asLocation().isValid() &&
517 ThisCallLocation = &Call->callEnterWithin;
519 ThisCallLocation = &Call->callEnter;
521 assert(ThisCallLocation &&
"Outermost call has an invalid location");
530 for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
531 if (
auto *C = dyn_cast<PathDiagnosticCallPiece>(I->get()))
534 if (
auto *M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))
537 if (
auto *CF = dyn_cast<PathDiagnosticControlFlowPiece>(I->get())) {
538 const Stmt *Start = CF->getStartLocation().asStmt();
539 const Stmt *
End = CF->getEndLocation().asStmt();
540 if (isa_and_nonnull<CXXDefaultInitExpr>(Start)) {
543 }
else if (isa_and_nonnull<CXXDefaultInitExpr>(
End)) {
544 PathPieces::iterator Next = std::next(I);
547 dyn_cast<PathDiagnosticControlFlowPiece>(Next->get())) {
548 NextCF->setStartLocation(CF->getStartLocation());
564 for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
565 if (
auto *C = dyn_cast<PathDiagnosticCallPiece>(I->get()))
568 if (
auto *M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))
571 if (!(*I)->getLocation().isValid() ||
572 !(*I)->getLocation().asLocation().isValid()) {
580 PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
581 const PathDiagnosticConstruct &C)
const {
582 if (
const Stmt *S =
C.getCurrentNode()->getNextStmtForDiagnostics())
583 return PathDiagnosticLocation(S, getSourceManager(),
584 C.getCurrLocationContext());
590 PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
591 llvm::raw_string_ostream &os,
const PathDiagnosticConstruct &C)
const {
593 if (os.str().empty())
596 const PathDiagnosticLocation &Loc = ExecutionContinues(C);
599 os <<
"Execution continues on line "
600 << getSourceManager().getExpansionLineNumber(Loc.asLocation())
603 os <<
"Execution jumps to the end of the ";
604 const Decl *D =
C.getCurrLocationContext()->getDecl();
605 if (isa<ObjCMethodDecl>(D))
607 else if (isa<FunctionDecl>(D))
610 assert(isa<BlockDecl>(D));
611 os <<
"anonymous block";
627 switch (
Parent->getStmtClass()) {
628 case Stmt::ForStmtClass:
629 case Stmt::DoStmtClass:
630 case Stmt::WhileStmtClass:
631 case Stmt::ObjCForCollectionStmtClass:
632 case Stmt::CXXForRangeStmtClass:
641 static PathDiagnosticLocation
643 bool allowNestedContexts =
false) {
650 switch (
Parent->getStmtClass()) {
651 case Stmt::BinaryOperatorClass: {
652 const auto *B = cast<BinaryOperator>(
Parent);
653 if (B->isLogicalOp())
654 return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
657 case Stmt::CompoundStmtClass:
658 case Stmt::StmtExprClass:
659 return PathDiagnosticLocation(S, SMgr, LC);
660 case Stmt::ChooseExprClass:
663 if (allowNestedContexts || cast<ChooseExpr>(
Parent)->getCond() == S)
664 return PathDiagnosticLocation(
Parent, SMgr, LC);
666 return PathDiagnosticLocation(S, SMgr, LC);
667 case Stmt::BinaryConditionalOperatorClass:
668 case Stmt::ConditionalOperatorClass:
671 if (allowNestedContexts ||
672 cast<AbstractConditionalOperator>(
Parent)->getCond() == S)
673 return PathDiagnosticLocation(
Parent, SMgr, LC);
675 return PathDiagnosticLocation(S, SMgr, LC);
676 case Stmt::CXXForRangeStmtClass:
677 if (cast<CXXForRangeStmt>(
Parent)->getBody() == S)
678 return PathDiagnosticLocation(S, SMgr, LC);
680 case Stmt::DoStmtClass:
681 return PathDiagnosticLocation(S, SMgr, LC);
682 case Stmt::ForStmtClass:
683 if (cast<ForStmt>(
Parent)->getBody() == S)
684 return PathDiagnosticLocation(S, SMgr, LC);
686 case Stmt::IfStmtClass:
687 if (cast<IfStmt>(
Parent)->getCond() != S)
688 return PathDiagnosticLocation(S, SMgr, LC);
690 case Stmt::ObjCForCollectionStmtClass:
691 if (cast<ObjCForCollectionStmt>(
Parent)->getBody() == S)
692 return PathDiagnosticLocation(S, SMgr, LC);
694 case Stmt::WhileStmtClass:
695 if (cast<WhileStmt>(
Parent)->getCond() != S)
696 return PathDiagnosticLocation(S, SMgr, LC);
705 assert(S &&
"Cannot have null Stmt for PathDiagnosticLocation");
707 return PathDiagnosticLocation(S, SMgr, LC);
724 void PathDiagnosticBuilder::updateStackPiecesWithMessage(
726 if (R->hasCallStackHint(
P))
727 for (
const auto &I : CallStack) {
728 PathDiagnosticCallPiece *CP = I.first;
729 const ExplodedNode *N = I.second;
735 if (!CP->hasCallStackMessage())
736 CP->setCallStackMessage(stackMsg);
744 const PathDiagnosticConstruct &C,
const CFGBlock *Dst,
745 PathDiagnosticLocation &Start)
const {
750 llvm::raw_string_ostream os(sbuf);
751 PathDiagnosticLocation
End;
754 End = PathDiagnosticLocation(S,
SM,
C.getCurrLocationContext());
756 switch (S->getStmtClass()) {
758 os <<
"No cases match in the switch statement. "
759 "Control jumps to line "
760 <<
End.asLocation().getExpansionLineNumber();
762 case Stmt::DefaultStmtClass:
763 os <<
"Control jumps to the 'default' case at line "
764 <<
End.asLocation().getExpansionLineNumber();
767 case Stmt::CaseStmtClass: {
768 os <<
"Control jumps to 'case ";
769 const auto *Case = cast<CaseStmt>(S);
773 bool GetRawInt =
true;
775 if (
const auto *DR = dyn_cast<DeclRefExpr>(LHS)) {
778 const auto *D = dyn_cast<EnumConstantDecl>(DR->getDecl());
789 os <<
":' at line " <<
End.asLocation().getExpansionLineNumber();
794 os <<
"'Default' branch taken. ";
795 End = ExecutionContinues(os, C);
797 return std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End,
802 const PathDiagnosticConstruct &C,
const Stmt *S,
803 PathDiagnosticLocation &Start)
const {
805 llvm::raw_string_ostream os(sbuf);
806 const PathDiagnosticLocation &
End =
808 os <<
"Control jumps to line " <<
End.asLocation().getExpansionLineNumber();
809 return std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End, os.str());
813 const PathDiagnosticConstruct &C,
const Stmt *T,
const CFGBlock *Src,
818 const auto *B = cast<BinaryOperator>(T);
820 llvm::raw_string_ostream os(sbuf);
821 os <<
"Left side of '";
822 PathDiagnosticLocation Start,
End;
824 if (B->getOpcode() == BO_LAnd) {
830 End = PathDiagnosticLocation(B->getLHS(),
SM,
C.getCurrLocationContext());
836 PathDiagnosticLocation(B->getLHS(),
SM,
C.getCurrLocationContext());
837 End = ExecutionContinues(C);
840 assert(B->getOpcode() == BO_LOr);
847 PathDiagnosticLocation(B->getLHS(),
SM,
C.getCurrLocationContext());
848 End = ExecutionContinues(C);
851 End = PathDiagnosticLocation(B->getLHS(),
SM,
C.getCurrLocationContext());
856 return std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End,
860 void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
861 PathDiagnosticConstruct &C,
BlockEdge BE)
const {
875 case Stmt::GotoStmtClass:
876 case Stmt::IndirectGotoStmtClass: {
877 if (
const Stmt *S =
C.getCurrentNode()->getNextStmtForDiagnostics())
878 C.getActivePath().push_front(generateDiagForGotoOP(C, S, Start));
882 case Stmt::SwitchStmtClass: {
883 C.getActivePath().push_front(generateDiagForSwitchOP(C, Dst, Start));
887 case Stmt::BreakStmtClass:
888 case Stmt::ContinueStmtClass: {
890 llvm::raw_string_ostream os(sbuf);
891 PathDiagnosticLocation
End = ExecutionContinues(os, C);
892 C.getActivePath().push_front(
893 std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End, os.str()));
898 case Stmt::BinaryConditionalOperatorClass:
899 case Stmt::ConditionalOperatorClass: {
901 llvm::raw_string_ostream os(sbuf);
902 os <<
"'?' condition is ";
909 PathDiagnosticLocation
End = ExecutionContinues(C);
911 if (
const Stmt *S =
End.asStmt())
914 C.getActivePath().push_front(
915 std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End, os.str()));
920 case Stmt::BinaryOperatorClass: {
921 if (!
C.supportsLogicalOpControlFlow())
924 C.getActivePath().push_front(generateDiagForBinaryOP(C, T, Src, Dst));
928 case Stmt::DoStmtClass:
931 llvm::raw_string_ostream os(sbuf);
933 os <<
"Loop condition is true. ";
934 PathDiagnosticLocation
End = ExecutionContinues(os, C);
936 if (
const Stmt *S =
End.asStmt())
939 C.getActivePath().push_front(
940 std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End,
943 PathDiagnosticLocation
End = ExecutionContinues(C);
945 if (
const Stmt *S =
End.asStmt())
948 C.getActivePath().push_front(
949 std::make_shared<PathDiagnosticControlFlowPiece>(
950 Start,
End,
"Loop condition is false. Exiting loop"));
954 case Stmt::WhileStmtClass:
955 case Stmt::ForStmtClass:
958 llvm::raw_string_ostream os(sbuf);
960 os <<
"Loop condition is false. ";
961 PathDiagnosticLocation
End = ExecutionContinues(os, C);
962 if (
const Stmt *S =
End.asStmt())
965 C.getActivePath().push_front(
966 std::make_shared<PathDiagnosticControlFlowPiece>(Start,
End,
969 PathDiagnosticLocation
End = ExecutionContinues(C);
970 if (
const Stmt *S =
End.asStmt())
973 C.getActivePath().push_front(
974 std::make_shared<PathDiagnosticControlFlowPiece>(
975 Start,
End,
"Loop condition is true. Entering loop body"));
980 case Stmt::IfStmtClass: {
981 PathDiagnosticLocation
End = ExecutionContinues(C);
983 if (
const Stmt *S =
End.asStmt())
987 C.getActivePath().push_front(
988 std::make_shared<PathDiagnosticControlFlowPiece>(
989 Start,
End,
"Taking false branch"));
991 C.getActivePath().push_front(
992 std::make_shared<PathDiagnosticControlFlowPiece>(
993 Start,
End,
"Taking true branch"));
1006 case Stmt::ForStmtClass:
1007 case Stmt::WhileStmtClass:
1008 case Stmt::ObjCForCollectionStmtClass:
1009 case Stmt::CXXForRangeStmtClass:
1034 const ExplodedNode *N) {
1038 const Stmt *S = SP->getStmt();
1042 N = N->getFirstPred();
1048 const Stmt *LoopBody =
nullptr;
1050 case Stmt::CXXForRangeStmtClass: {
1051 const auto *FR = cast<CXXForRangeStmt>(Term);
1056 LoopBody = FR->getBody();
1059 case Stmt::ForStmtClass: {
1060 const auto *FS = cast<ForStmt>(Term);
1063 LoopBody = FS->getBody();
1066 case Stmt::ObjCForCollectionStmtClass: {
1067 const auto *FC = cast<ObjCForCollectionStmt>(Term);
1068 LoopBody = FC->getBody();
1071 case Stmt::WhileStmtClass:
1072 LoopBody = cast<WhileStmt>(Term)->getBody();
1082 PathDiagnosticLocation &PrevLoc,
1083 PathDiagnosticLocation NewLoc) {
1084 if (!NewLoc.isValid())
1091 if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) {
1098 if (NewLoc.asStmt() && NewLoc.asStmt() == PrevLoc.asStmt())
1102 std::make_shared<PathDiagnosticControlFlowPiece>(NewLoc, PrevLoc));
1110 if (
const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(S))
1111 return FS->getElement();
1118 "Loop body skipped when range is empty";
1120 "Loop body skipped when collection is empty";
1122 static std::unique_ptr<FilesToLineNumsMap>
1125 void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
1126 PathDiagnosticConstruct &C, PathDiagnosticLocation &PrevLoc)
const {
1136 if (C.shouldAddPathEdges()) {
1152 bool VisitedEntireCall =
C.PD->isWithinCall();
1153 C.PD->popActivePath();
1155 PathDiagnosticCallPiece *
Call;
1156 if (VisitedEntireCall) {
1157 Call = cast<PathDiagnosticCallPiece>(
C.getActivePath().front().get());
1161 const Decl *Caller = CE->getLocationContext()->getDecl();
1163 assert(
C.getActivePath().size() == 1 &&
1164 C.getActivePath().front().get() == Call);
1168 assert(
C.isInLocCtxMap(&
C.getActivePath()) &&
1169 "When we ascend to a previously unvisited call, the active path's "
1170 "address shouldn't change, but rather should be compacted into "
1171 "a single CallEvent!");
1172 C.updateLocCtxMap(&
C.getActivePath(),
C.getCurrLocationContext());
1175 assert(!
C.isInLocCtxMap(&
Call->path) &&
1176 "When we ascend to a previously unvisited call, this must be the "
1177 "first time we encounter the caller context!");
1178 C.updateLocCtxMap(&
Call->path, CE->getCalleeContext());
1180 Call->setCallee(*CE,
SM);
1183 PrevLoc =
Call->getLocation();
1185 if (!
C.CallStack.empty()) {
1186 assert(
C.CallStack.back().first == Call);
1187 C.CallStack.pop_back();
1192 assert(
C.getCurrLocationContext() ==
C.getLocationContextForActivePath() &&
1193 "The current position in the bug path is out of sync with the "
1194 "location context associated with the active path!");
1203 assert(!
C.isInLocCtxMap(&
Call->path) &&
1204 "We just entered a call, this must've been the first time we "
1205 "encounter its context!");
1206 C.updateLocCtxMap(&
Call->path, CE->getCalleeContext());
1208 if (
C.shouldAddPathEdges()) {
1211 PrevLoc.invalidate();
1214 auto *
P =
Call.get();
1215 C.getActivePath().push_front(std::move(Call));
1218 C.PD->pushActivePath(&
P->path);
1219 C.CallStack.push_back(CallWithEntry(
P,
C.getCurrentNode()));
1224 if (!
C.shouldAddPathEdges())
1230 if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
1231 PathDiagnosticLocation L =
1232 PathDiagnosticLocation(PS->getStmt(),
SM,
C.getCurrLocationContext());
1238 if (
C.shouldAddControlNotes()) {
1239 generateMinimalDiagForBlockEdge(C, *BE);
1242 if (!
C.shouldAddPathEdges()) {
1248 PathDiagnosticLocation L(Loop,
SM,
C.getCurrLocationContext());
1249 const Stmt *Body =
nullptr;
1251 if (
const auto *FS = dyn_cast<ForStmt>(Loop))
1252 Body = FS->getBody();
1253 else if (
const auto *WS = dyn_cast<WhileStmt>(Loop))
1254 Body = WS->getBody();
1255 else if (
const auto *OFS = dyn_cast<ObjCForCollectionStmt>(Loop)) {
1256 Body = OFS->getBody();
1257 }
else if (
const auto *FRS = dyn_cast<CXXForRangeStmt>(Loop)) {
1258 Body = FRS->getBody();
1262 auto p = std::make_shared<PathDiagnosticEventPiece>(
1263 L,
"Looping back to the head of the loop");
1264 p->setPrunable(
true);
1268 if (!
C.shouldAddControlNotes()) {
1269 C.getActivePath().push_front(std::move(p));
1272 if (
const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
1292 if (!IsInLoopBody) {
1293 if (isa<ObjCForCollectionStmt>(Term)) {
1295 }
else if (isa<CXXForRangeStmt>(Term)) {
1306 PathDiagnosticLocation L(TermCond ? TermCond : Term,
SM,
1307 C.getCurrLocationContext());
1308 auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
1309 PE->setPrunable(
true);
1313 if (!
C.shouldAddControlNotes()) {
1314 C.getActivePath().push_front(std::move(PE));
1317 }
else if (isa<BreakStmt, ContinueStmt, GotoStmt>(Term)) {
1318 PathDiagnosticLocation L(Term,
SM,
C.getCurrLocationContext());
1325 static std::unique_ptr<PathDiagnostic>
1327 const BugType &BT = R->getBugType();
1328 return std::make_unique<PathDiagnostic>(
1329 BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(),
1330 R->getDescription(), R->getShortDescription(
false),
1331 BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
1332 std::make_unique<FilesToLineNumsMap>());
1335 static std::unique_ptr<PathDiagnostic>
1338 const BugType &BT = R->getBugType();
1339 return std::make_unique<PathDiagnostic>(
1340 BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(),
1341 R->getDescription(), R->getShortDescription(
false),
1342 BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
1356 if (isa<FullExpr, CXXBindTemporaryExpr, SubstNonTypeTemplateParmExpr>(S))
1366 switch (S->getStmtClass()) {
1367 case Stmt::BinaryOperatorClass: {
1368 const auto *BO = cast<BinaryOperator>(S);
1369 if (!BO->isLogicalOp())
1371 return BO->getLHS() == Cond || BO->getRHS() == Cond;
1373 case Stmt::IfStmtClass:
1374 return cast<IfStmt>(S)->getCond() == Cond;
1375 case Stmt::ForStmtClass:
1376 return cast<ForStmt>(S)->getCond() == Cond;
1377 case Stmt::WhileStmtClass:
1378 return cast<WhileStmt>(S)->getCond() == Cond;
1379 case Stmt::DoStmtClass:
1380 return cast<DoStmt>(S)->getCond() == Cond;
1381 case Stmt::ChooseExprClass:
1382 return cast<ChooseExpr>(S)->getCond() == Cond;
1383 case Stmt::IndirectGotoStmtClass:
1384 return cast<IndirectGotoStmt>(S)->getTarget() == Cond;
1385 case Stmt::SwitchStmtClass:
1386 return cast<SwitchStmt>(S)->getCond() == Cond;
1387 case Stmt::BinaryConditionalOperatorClass:
1388 return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
1389 case Stmt::ConditionalOperatorClass: {
1390 const auto *CO = cast<ConditionalOperator>(S);
1391 return CO->getCond() == Cond ||
1392 CO->getLHS() == Cond ||
1393 CO->getRHS() == Cond;
1395 case Stmt::ObjCForCollectionStmtClass:
1396 return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
1397 case Stmt::CXXForRangeStmtClass: {
1398 const auto *FRS = cast<CXXForRangeStmt>(S);
1399 return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
1407 if (
const auto *FS = dyn_cast<ForStmt>(FL))
1408 return FS->getInc() == S || FS->getInit() == S;
1409 if (
const auto *FRS = dyn_cast<CXXForRangeStmt>(FL))
1410 return FRS->getInc() == S || FRS->getRangeStmt() == S ||
1411 FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
1424 PathPieces::iterator Prev = pieces.end();
1425 for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
1427 auto *Piece = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
1432 PathDiagnosticLocation SrcLoc = Piece->getStartLocation();
1435 PathDiagnosticLocation NextSrcContext = SrcLoc;
1436 const Stmt *InnerStmt =
nullptr;
1437 while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
1438 SrcContexts.push_back(NextSrcContext);
1439 InnerStmt = NextSrcContext.asStmt();
1448 const Stmt *Dst = Piece->getEndLocation().getStmtOrNull();
1452 PathDiagnosticLocation DstContext =
1454 if (!DstContext.isValid() || DstContext.asStmt() == Dst)
1458 if (llvm::is_contained(SrcContexts, DstContext))
1462 Piece->setStartLocation(DstContext);
1467 auto *PrevPiece = dyn_cast<PathDiagnosticControlFlowPiece>(Prev->get());
1470 if (
const Stmt *PrevSrc =
1471 PrevPiece->getStartLocation().getStmtOrNull()) {
1473 if (PrevSrcParent ==
1475 PrevPiece->setEndLocation(DstContext);
1486 std::make_shared<PathDiagnosticControlFlowPiece>(SrcLoc, DstContext);
1488 I = pieces.insert(I, std::move(
P));
1504 for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
1505 const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
1510 const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
1511 const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
1513 if (!s1Start || !s1End)
1516 PathPieces::iterator NextI = I; ++NextI;
1520 PathDiagnosticControlFlowPiece *PieceNextI =
nullptr;
1526 const auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
1528 StringRef S = EV->getString();
1537 PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
1544 const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
1545 const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
1547 if (!s2Start || !s2End || s1End != s2Start)
1562 PieceNextI->setStartLocation(PieceI->getStartLocation());
1563 I = pieces.erase(I);
1574 SourceRange ExpansionRange(
SM.getExpansionLoc(Range.getBegin()),
1575 SM.getExpansionRange(Range.getEnd()).getEnd());
1578 if (FID !=
SM.getFileID(ExpansionRange.
getEnd()))
1585 unsigned BeginOffset =
SM.getFileOffset(ExpansionRange.
getBegin());
1586 unsigned EndOffset =
SM.getFileOffset(ExpansionRange.
getEnd());
1587 StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);
1593 if (Snippet.find_first_of(
"\r\n") != StringRef::npos)
1597 return Snippet.size();
1623 for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
1625 const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
1632 const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
1633 const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
1635 PathPieces::iterator NextI = I; ++NextI;
1639 const auto *PieceNextI =
1640 dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
1643 if (isa<PathDiagnosticEventPiece>(NextI->get())) {
1647 PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
1656 const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
1657 const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
1659 if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
1660 const size_t MAX_SHORT_LINE_LENGTH = 80;
1662 if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {
1664 if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {
1666 I = Path.erase(NextI);
1689 bool erased =
false;
1691 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
1695 const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
1700 const Stmt *start = PieceI->getStartLocation().getStmtOrNull();
1701 const Stmt *end = PieceI->getEndLocation().getStmtOrNull();
1716 if (!
SM.isWrittenInSameFile(FirstLoc, SecondLoc))
1718 if (
SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc))
1719 std::swap(SecondLoc, FirstLoc);
1728 const size_t MAX_PUNY_EDGE_LENGTH = 2;
1729 if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {
1741 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
1742 const auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());
1747 PathPieces::iterator NextI = I; ++NextI;
1751 const auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
1757 if (PieceI->getString() == PieceNextI->getString()) {
1765 bool hasChanges =
false;
1771 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
1773 if (
auto *CallI = dyn_cast<PathDiagnosticCallPiece>(I->get())) {
1776 if (!OCS.count(CallI)) {
1786 auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
1793 const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
1794 const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull();
1798 PathPieces::iterator NextI = I; ++NextI;
1802 const auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
1809 const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
1810 const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull();
1828 if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
1829 PieceI->setEndLocation(PieceNextI->getEndLocation());
1842 if (s1End && s1End == s2Start && level2) {
1843 bool removeEdge =
false;
1869 else if (s1Start && s2End &&
1882 else if (s1Start && s2End &&
1884 SourceRange EdgeRange(PieceI->getEndLocation().asLocation(),
1885 PieceI->getStartLocation().asLocation());
1892 PieceI->setEndLocation(PieceNextI->getEndLocation());
1906 if (s1End == s2Start) {
1907 const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(level3);
1908 if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
1909 s2End == FS->getElement()) {
1910 PieceI->setEndLocation(PieceNextI->getEndLocation());
1947 const auto *FirstEdge =
1948 dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
1952 const Decl *D = C.getLocationContextFor(&Path)->getDecl();
1953 PathDiagnosticLocation EntryLoc =
1955 if (FirstEdge->getStartLocation() != EntryLoc)
1964 PathPieces path = PD.path.flatten(
true);
1967 for (
const auto &
P : path) {
1968 FullSourceLoc Loc =
P->getLocation().asLocation().getExpansionLoc();
1972 ExecutedLines[FID].insert(LineNo);
1976 PathDiagnosticConstruct::PathDiagnosticConstruct(
1977 const PathDiagnosticConsumer *PDC,
const ExplodedNode *ErrorNode,
1978 const PathSensitiveBugReport *R)
1979 : Consumer(PDC), CurrentNode(ErrorNode),
1980 SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()),
1982 LCM[&PD->getActivePath()] = ErrorNode->getLocationContext();
1985 PathDiagnosticBuilder::PathDiagnosticBuilder(
1986 BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
1987 PathSensitiveBugReport *r,
const ExplodedNode *ErrorNode,
1988 std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics)
1989 : BugReporterContext(BRC), BugPath(
std::move(BugPath)), R(r),
1990 ErrorNode(ErrorNode),
1991 VisitorsDiagnostics(
std::move(VisitorsDiagnostics)) {}
1993 std::unique_ptr<PathDiagnostic>
1994 PathDiagnosticBuilder::generate(
const PathDiagnosticConsumer *PDC)
const {
1995 PathDiagnosticConstruct Construct(PDC, ErrorNode, R);
2000 if (!PDC->shouldGenerateDiagnostics())
2004 auto EndNotes = VisitorsDiagnostics->find(ErrorNode);
2006 if (EndNotes != VisitorsDiagnostics->end()) {
2007 assert(!EndNotes->second.empty());
2008 LastPiece = EndNotes->second[0];
2010 LastPiece = BugReporterVisitor::getDefaultEndPath(*
this, ErrorNode,
2013 Construct.PD->setEndOfPath(LastPiece);
2015 PathDiagnosticLocation PrevLoc = Construct.PD->getLocation();
2018 while (Construct.ascendToPrevNode()) {
2019 generatePathDiagnosticsForNode(Construct, PrevLoc);
2021 auto VisitorNotes = VisitorsDiagnostics->find(Construct.getCurrentNode());
2022 if (VisitorNotes == VisitorsDiagnostics->end())
2027 std::set<llvm::FoldingSetNodeID> DeduplicationSet;
2031 llvm::FoldingSetNodeID
ID;
2033 if (!DeduplicationSet.insert(
ID).second)
2036 if (PDC->shouldAddPathEdges())
2038 updateStackPiecesWithMessage(
Note, Construct.CallStack);
2039 Construct.getActivePath().push_front(
Note);
2043 if (PDC->shouldAddPathEdges()) {
2047 Construct.getLocationContextForActivePath()->
getStackFrame();
2050 PathDiagnosticLocation::createBegin(D,
SM));
2055 if (!Construct.PD->path.empty()) {
2056 if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
2057 bool stillHasNotes =
2059 assert(stillHasNotes);
2060 (void)stillHasNotes;
2064 if (!Opts.ShouldAddPopUpNotes)
2071 if (PDC->shouldAddPathEdges()) {
2077 while (
optimizeEdges(Construct, Construct.getMutablePieces(), OCS)) {
2092 if (Opts.ShouldDisplayMacroExpansions)
2095 return std::move(Construct.PD);
2102 void BugType::anchor() {}
2104 void BuiltinBug::anchor() {}
2110 LLVM_ATTRIBUTE_USED
static bool
2112 for (
const std::pair<StringRef, StringRef> &Pair : Registry.Dependencies) {
2113 if (Pair.second == CheckerName)
2119 LLVM_ATTRIBUTE_USED
static bool isHidden(
const CheckerRegistryData &Registry,
2120 StringRef CheckerName) {
2121 for (
const CheckerInfo &Checker : Registry.Checkers) {
2122 if (Checker.FullName == CheckerName)
2123 return Checker.IsHidden;
2126 "Checker name not found in CheckerRegistry -- did you retrieve it "
2127 "correctly from CheckerManager::getCurrentCheckerName?");
2130 PathSensitiveBugReport::PathSensitiveBugReport(
2131 const BugType &bt, StringRef shortDesc, StringRef desc,
2133 const Decl *DeclToUnique)
2134 :
BugReport(
Kind::PathSensitive, bt, shortDesc, desc), ErrorNode(errorNode),
2136 UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
2138 ->getAnalysisManager()
2139 .getCheckerManager()
2140 ->getCheckerRegistryData(),
2142 "Some checkers depend on this one! We don't allow dependency "
2143 "checkers to emit warnings, because checkers should depend on "
2144 "*modeling*, not *diagnostics*.");
2149 ->getAnalysisManager()
2150 .getCheckerManager()
2151 ->getCheckerRegistryData(),
2153 "Hidden checkers musn't emit diagnostics as they are by definition "
2154 "non-user facing!");
2158 std::unique_ptr<BugReporterVisitor> visitor) {
2162 llvm::FoldingSetNodeID
ID;
2163 visitor->Profile(
ID);
2165 void *InsertPos =
nullptr;
2170 Callbacks.push_back(std::move(visitor));
2187 hash.AddInteger(
static_cast<int>(
getKind()));
2188 hash.AddPointer(&
BT);
2194 if (!
range.isValid())
2196 hash.Add(
range.getBegin());
2197 hash.Add(
range.getEnd());
2202 hash.AddInteger(
static_cast<int>(
getKind()));
2203 hash.AddPointer(&
BT);
2217 if (!
range.isValid())
2219 hash.Add(
range.getBegin());
2220 hash.Add(
range.getEnd());
2226 llvm::DenseMap<T, bugreporter::TrackingKind> &InterestingnessMap, T Val,
2228 auto Result = InterestingnessMap.insert({Val, TKind});
2248 "BugReport::markInteresting currently can only handle 2 different "
2249 "tracking kinds! Please define what tracking kind should this entitiy"
2250 "have, if it was already marked as interesting with a different kind!");
2262 if (
const auto *meta = dyn_cast<SymbolMetadata>(sym))
2274 if (
const auto *meta = dyn_cast<SymbolMetadata>(sym))
2286 if (
const auto *SR = dyn_cast<SymbolicRegion>(R))
2297 if (
const auto *SR = dyn_cast<SymbolicRegion>(R))
2332 "BugReport::getInterestingnessKind currently can only handle 2 different "
2333 "tracking kinds! Please define what tracking kind should we return here "
2334 "when the kind of getAsRegion() and getAsSymbol() is different!");
2347 return It->getSecond();
2358 return It->getSecond();
2360 if (
const auto *SR = dyn_cast<SymbolicRegion>(R))
2388 const Stmt *S =
nullptr;
2392 if (BE->getBlock() == &Exit)
2413 assert(
ErrorNode &&
"Cannot create a location with a null node.");
2433 if (
const auto *ME = dyn_cast<MemberExpr>(S))
2437 if (
const auto *B = dyn_cast<BinaryOperator>(S))
2443 if (S->getBeginLoc().isValid())
2469 assert(StrBugTypes.empty() &&
2470 "Destroying BugReporter before diagnostics are emitted!");
2473 for (
const auto I : EQClassesVector)
2480 for (
const auto EQ : EQClassesVector)
2487 StrBugTypes.clear();
2500 std::unique_ptr<ExplodedGraph> BugPath;
2507 class BugPathGetter {
2508 std::unique_ptr<ExplodedGraph> TrimmedGraph;
2510 using PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;
2513 PriorityMapTy PriorityMap;
2517 using ReportNewNodePair =
2518 std::pair<PathSensitiveBugReport *, const ExplodedNode *>;
2521 BugPathInfo CurrentBugPath;
2524 template <
bool Descending>
2525 class PriorityCompare {
2526 const PriorityMapTy &PriorityMap;
2529 PriorityCompare(
const PriorityMapTy &M) : PriorityMap(M) {}
2531 bool operator()(
const ExplodedNode *LHS,
const ExplodedNode *RHS)
const {
2532 PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);
2533 PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);
2534 PriorityMapTy::const_iterator E = PriorityMap.end();
2541 return Descending ? LI->second > RI->second
2542 : LI->second < RI->second;
2545 bool operator()(
const ReportNewNodePair &LHS,
2546 const ReportNewNodePair &RHS)
const {
2547 return (*
this)(LHS.second, RHS.second);
2552 BugPathGetter(
const ExplodedGraph *OriginalGraph,
2555 BugPathInfo *getNextBugPath();
2560 BugPathGetter::BugPathGetter(
const ExplodedGraph *OriginalGraph,
2563 for (
const auto I : bugReports) {
2564 assert(I->isValid() &&
2565 "We only allow BugReporterVisitors and BugReporter itself to "
2566 "invalidate reports!");
2567 Nodes.emplace_back(I->getErrorNode());
2573 TrimmedGraph = OriginalGraph->trim(
Nodes, &ForwardMap);
2580 for (PathSensitiveBugReport *Report : bugReports) {
2581 const ExplodedNode *NewNode = ForwardMap.lookup(Report->getErrorNode());
2583 "Failed to construct a trimmed graph that contains this error "
2585 ReportNodes.emplace_back(Report, NewNode);
2586 RemainingNodes.insert(NewNode);
2589 assert(!RemainingNodes.empty() &&
"No error node found in the trimmed graph");
2592 std::queue<const ExplodedNode *> WS;
2594 assert(TrimmedGraph->num_roots() == 1);
2595 WS.push(*TrimmedGraph->roots_begin());
2598 while (!WS.empty()) {
2599 const ExplodedNode *
Node = WS.front();
2602 PriorityMapTy::iterator PriorityEntry;
2604 std::tie(PriorityEntry, IsNew) = PriorityMap.insert({
Node,
Priority});
2608 assert(PriorityEntry->second <=
Priority);
2612 if (RemainingNodes.erase(
Node))
2613 if (RemainingNodes.empty())
2616 for (
const ExplodedNode *Succ :
Node->succs())
2621 llvm::sort(ReportNodes, PriorityCompare<true>(PriorityMap));
2624 BugPathInfo *BugPathGetter::getNextBugPath() {
2625 if (ReportNodes.empty())
2628 const ExplodedNode *OrigN;
2629 std::tie(CurrentBugPath.Report, OrigN) = ReportNodes.pop_back_val();
2630 assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
2631 "error node not accessible from root");
2635 auto GNew = std::make_unique<ExplodedGraph>();
2639 ExplodedNode *Succ =
nullptr;
2643 ExplodedNode *NewN = GNew->createUncachedNode(
2644 OrigN->getLocation(), OrigN->getState(),
2645 OrigN->getID(), OrigN->isSink());
2649 Succ->addPredecessor(NewN, *GNew);
2651 CurrentBugPath.ErrorNode = NewN;
2656 if (OrigN->pred_empty()) {
2657 GNew->addRoot(NewN);
2663 OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(),
2664 PriorityCompare<false>(PriorityMap));
2667 CurrentBugPath.BugPath = std::move(GNew);
2669 return &CurrentBugPath;
2676 using MacroStackTy = std::vector<
2677 std::pair<std::shared_ptr<PathDiagnosticMacroPiece>,
SourceLocation>>;
2679 using PiecesTy = std::vector<PathDiagnosticPieceRef>;
2681 MacroStackTy MacroStack;
2684 for (PathPieces::const_iterator I = path.begin(), E = path.end();
2686 const auto &piece = *I;
2689 if (
auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
2694 const FullSourceLoc Loc = piece->getLocation().asLocation();
2699 SM.getExpansionLoc(Loc) :
2704 Pieces.push_back(piece);
2711 if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
2712 MacroStack.back().first->subPieces.push_back(piece);
2718 std::shared_ptr<PathDiagnosticMacroPiece> MacroGroup;
2721 SM.getExpansionLoc(Loc) :
2725 while (!MacroStack.empty()) {
2726 if (InstantiationLoc == MacroStack.back().second) {
2727 MacroGroup = MacroStack.back().first;
2731 if (ParentInstantiationLoc == MacroStack.back().second) {
2732 MacroGroup = MacroStack.back().first;
2736 MacroStack.pop_back();
2739 if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
2741 auto NewGroup = std::make_shared<PathDiagnosticMacroPiece>(
2745 MacroGroup->subPieces.push_back(NewGroup);
2747 assert(InstantiationLoc.
isFileID());
2748 Pieces.push_back(NewGroup);
2751 MacroGroup = NewGroup;
2752 MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
2756 MacroGroup->subPieces.push_back(piece);
2762 path.insert(path.end(), Pieces.begin(), Pieces.end());
2768 static std::unique_ptr<VisitorsDiagnosticsTy>
2770 const ExplodedNode *ErrorNode,
2771 BugReporterContext &BRC) {
2772 std::unique_ptr<VisitorsDiagnosticsTy> Notes =
2773 std::make_unique<VisitorsDiagnosticsTy>();
2778 const ExplodedNode *NextNode = ErrorNode->getFirstPred();
2786 for (std::unique_ptr<BugReporterVisitor> &Visitor : R->visitors())
2787 visitors.push_back(std::move(Visitor));
2791 const ExplodedNode *Pred = NextNode->getFirstPred();
2794 for (
auto &
V : visitors) {
2795 V->finalizeVisitor(BRC, ErrorNode, *R);
2797 if (
auto Piece =
V->getEndPath(BRC, ErrorNode, *R)) {
2798 assert(!LastPiece &&
2799 "There can only be one final piece in a diagnostic.");
2800 assert(Piece->getKind() == PathDiagnosticPiece::Kind::Event &&
2801 "The final piece must contain a message!");
2802 LastPiece = std::move(Piece);
2803 (*Notes)[ErrorNode].push_back(LastPiece);
2809 for (
auto &
V : visitors) {
2810 auto P =
V->VisitNode(NextNode, BRC, *R);
2812 (*Notes)[NextNode].push_back(std::move(
P));
2826 PathSensitiveBugReporter &Reporter) {
2828 BugPathGetter BugGraph(&Reporter.getGraph(), bugReports);
2830 while (BugPathInfo *BugPath = BugGraph.getNextBugPath()) {
2832 PathSensitiveBugReport *R = BugPath->Report;
2833 assert(R &&
"No original report found for sliced graph.");
2834 assert(R->isValid() &&
"Report selected by trimmed graph marked invalid.");
2835 const ExplodedNode *ErrorNode = BugPath->ErrorNode;
2839 R->addVisitor<LikelyFalsePositiveSuppressionBRVisitor>();
2842 R->addVisitor<NilReceiverBRVisitor>();
2843 R->addVisitor<ConditionBRVisitor>();
2844 R->addVisitor<TagVisitor>();
2846 BugReporterContext BRC(Reporter);
2849 std::unique_ptr<VisitorsDiagnosticsTy> visitorNotes =
2853 if (Reporter.getAnalyzerOptions().ShouldCrosscheckWithZ3) {
2857 R->addVisitor<FalsePositiveRefutationBRVisitor>();
2866 return PathDiagnosticBuilder(
2867 std::move(BRC), std::move(BugPath->BugPath), BugPath->Report,
2868 BugPath->ErrorNode, std::move(visitorNotes));
2875 std::unique_ptr<DiagnosticForConsumerMapTy>
2879 assert(!bugReports.empty());
2881 auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
2884 PathDiagnosticBuilder::findValidReport(bugReports, *
this);
2888 if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) {
2889 (*Out)[PC] = std::move(PD);
2898 bool ValidSourceLoc = R->getLocation().isValid();
2899 assert(ValidSourceLoc);
2902 if (!ValidSourceLoc)
2906 llvm::FoldingSetNodeID
ID;
2915 EQClasses.InsertNode(
EQ, InsertPos);
2916 EQClassesVector.push_back(
EQ);
2918 EQ->AddReport(std::move(R));
2922 if (
auto PR = dyn_cast<PathSensitiveBugReport>(R.get()))
2926 assert((E->isSink() || E->getLocation().getTag()) &&
2927 "Error node must either be a sink or have a tag");
2930 E->getLocationContext()->getAnalysisDeclContext();
2949 struct FRIEC_WLItem {
2954 : N(n), I(N->succ_begin()), E(N->succ_end()) {}
2959 BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass(
2964 assert(
EQ.getReports().size() > 0);
2965 const BugType& BT =
EQ.getReports()[0]->getBugType();
2966 if (!BT.isSuppressOnSink()) {
2967 BugReport *R =
EQ.getReports()[0].get();
2968 for (
auto &J :
EQ.getReports()) {
2969 if (
auto *PR = dyn_cast<PathSensitiveBugReport>(J.get())) {
2971 bugReports.push_back(PR);
2983 BugReport *exampleReport =
nullptr;
2985 for (
const auto &I:
EQ.getReports()) {
2986 auto *R = dyn_cast<PathSensitiveBugReport>(I.get());
2990 const ExplodedNode *errorNode = R->getErrorNode();
2991 if (errorNode->isSink()) {
2993 "BugType::isSuppressSink() should not be 'true' for sink end nodes");
2996 if (errorNode->succ_empty()) {
2997 bugReports.push_back(R);
3007 if (
const CFGBlock *ErrorB = errorNode->getCFGBlock())
3008 if (ErrorB->isInevitablySinking())
3013 using WLItem = FRIEC_WLItem;
3016 llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
3019 WL.push_back(errorNode);
3020 Visited[errorNode] = 1;
3022 while (!WL.empty()) {
3023 WLItem &WI = WL.back();
3024 assert(!WI.N->succ_empty());
3026 for (; WI.I != WI.E; ++WI.I) {
3027 const ExplodedNode *Succ = *WI.I;
3029 if (Succ->succ_empty()) {
3031 if (!Succ->isSink()) {
3032 bugReports.push_back(R);
3043 unsigned &mark = Visited[Succ];
3053 if (!WL.empty() && &WL.back() == &WI)
3060 return exampleReport;
3063 void BugReporter::FlushReport(BugReportEquivClass&
EQ) {
3065 BugReport *report = findReportInEquivalenceClass(
EQ, bugReports);
3072 if (report->getBugType().getCheckerName().startswith(
3078 std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =
3081 for (
auto &
P : *Diagnostics) {
3082 PathDiagnosticConsumer *Consumer =
P.first;
3083 std::unique_ptr<PathDiagnostic> &PD =
P.second;
3087 if (PD->path.empty()) {
3088 PathDiagnosticLocation L = report->getLocation();
3089 auto piece = std::make_unique<PathDiagnosticEventPiece>(
3090 L, report->getDescription());
3092 piece->addRange(Range);
3093 PD->setEndOfPath(std::move(piece));
3096 PathPieces &Pieces = PD->getMutablePieces();
3100 for (
auto I = report->getNotes().rbegin(),
3101 E = report->getNotes().rend(); I != E; ++I) {
3102 PathDiagnosticNotePiece *Piece = I->get();
3103 auto ConvertedPiece = std::make_shared<PathDiagnosticEventPiece>(
3104 Piece->getLocation(), Piece->getString());
3105 for (
const auto &R: Piece->getRanges())
3106 ConvertedPiece->addRange(R);
3108 Pieces.push_front(std::move(ConvertedPiece));
3111 for (
auto I = report->getNotes().rbegin(),
3112 E = report->getNotes().rend(); I != E; ++I)
3113 Pieces.push_front(*I);
3116 for (
const auto &I : report->getFixits())
3117 Pieces.back()->addFixit(I);
3120 Consumer->HandlePathDiagnostic(std::move(PD));
3131 if (
const auto FD = dyn_cast<FunctionDecl>(Signature)) {
3132 SignatureSourceRange = FD->getSourceRange();
3133 }
else if (
const auto OD = dyn_cast<ObjCMethodDecl>(Signature)) {
3134 SignatureSourceRange = OD->getSourceRange();
3140 : SignatureSourceRange.
getEnd();
3143 unsigned StartLine =
SM.getExpansionLineNumber(Start);
3144 unsigned EndLine =
SM.getExpansionLineNumber(
End);
3146 FileID FID =
SM.getFileID(
SM.getExpansionLoc(Start));
3147 for (
unsigned Line = StartLine;
Line <= EndLine;
Line++)
3148 ExecutedLines[FID].insert(
Line);
3158 FileID FID =
SM.getFileID(ExpansionLoc);
3159 unsigned LineNo =
SM.getExpansionLineNumber(ExpansionLoc);
3160 ExecutedLines[FID].insert(LineNo);
3165 static std::unique_ptr<FilesToLineNumsMap>
3167 auto ExecutedLines = std::make_unique<FilesToLineNumsMap>();
3170 if (N->getFirstPred() ==
nullptr) {
3172 const Decl *D = N->getLocationContext()->getDecl();
3174 }
else if (
auto CE = N->getLocationAs<
CallEnter>()) {
3176 const Decl* D = CE->getCalleeContext()->getDecl();
3178 }
else if (
const Stmt *S = N->getStmtForDiagnostics()) {
3182 const Stmt *
P = N->getParentMap().getParent(S);
3187 if (
const auto *RS = dyn_cast_or_null<ReturnStmt>(
P)) {
3189 P = N->getParentMap().getParent(RS);
3192 if (isa_and_nonnull<SwitchCase, LabelStmt>(
P))
3196 N = N->getFirstPred();
3198 return ExecutedLines;
3201 std::unique_ptr<DiagnosticForConsumerMapTy>
3205 auto *basicReport = cast<BasicBugReport>(exampleReport);
3206 auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
3207 for (
auto *Consumer : consumers)
3222 "The call piece should not be in a header file.");
3228 const PathPieces &Path = CP->path;
3234 if (
auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
3242 if (PD.path.empty())
3245 PathDiagnosticPiece *LastP = PD.path.back().get();
3247 const SourceManager &SMgr = LastP->getLocation().getManager();
3251 if (
auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
3255 CP->setAsLastInMainSourceFile();
3258 const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
3261 llvm::raw_svector_ostream os(buf);
3262 os <<
" (within a call to '" << ND->getDeclName() <<
"')";
3263 PD.appendToDesc(os.str());
3267 PD.setDeclWithIssue(CP->getCaller());
3268 PD.setLocation(CP->getLocation());
3277 std::unique_ptr<DiagnosticForConsumerMapTy>
3278 PathSensitiveBugReporter::generateDiagnosticForConsumerMap(
3281 std::vector<BasicBugReport *> BasicBugReports;
3282 std::vector<PathSensitiveBugReport *> PathSensitiveBugReports;
3283 if (isa<BasicBugReport>(exampleReport))
3285 consumers, bugReports);
3291 assert(!bugReports.empty());
3292 MaxBugClassSize.updateMax(bugReports.size());
3296 reinterpret_cast<PathSensitiveBugReport *
const *
>(&*bugReports.begin()),
3297 reinterpret_cast<PathSensitiveBugReport *
const *
>(&*bugReports.end()));
3299 consumers, convertedArrayOfReports);
3304 MaxValidBugClassSize.updateMax(bugReports.size());
3309 for (
auto const &
P : *Out)
3310 if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.
AnalyzeAll)
3317 const CheckerBase *Checker, StringRef Name,
3318 StringRef Category, StringRef Str,
3319 PathDiagnosticLocation Loc,
3322 EmitBasicReport(DeclWithIssue, Checker->getCheckerName(), Name, Category, Str,
3323 Loc, Ranges, Fixits);
3327 CheckerNameRef CheckName,
3328 StringRef
name, StringRef category,
3329 StringRef str, PathDiagnosticLocation Loc,
3333 BugType *BT = getBugTypeForName(CheckName,
name, category);
3334 auto R = std::make_unique<BasicBugReport>(*BT, str, Loc);
3335 R->setDeclWithIssue(DeclWithIssue);
3336 for (
const auto &SR : Ranges)
3338 for (
const auto &FH : Fixits)
3339 R->addFixItHint(FH);
3343 BugType *BugReporter::getBugTypeForName(CheckerNameRef CheckName,
3344 StringRef
name, StringRef category) {
3346 llvm::raw_svector_ostream(fullDesc) << CheckName.getName() <<
":" <<
name
3348 std::unique_ptr<BugType> &BT = StrBugTypes[fullDesc];
3350 BT = std::make_unique<BugType>(CheckName,
name, category);