29 #include "llvm/ADT/DenseMap.h"
30 #include "llvm/ADT/IntrusiveRefCntPtr.h"
31 #include "llvm/ADT/STLExtras.h"
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/ADT/Statistic.h"
34 #include "llvm/Support/raw_ostream.h"
38 using namespace clang;
41 #define DEBUG_TYPE "BugReporter"
44 "The maximum number of bug reports in the same equivalence class");
46 "The maximum number of bug reports in the same equivalence class "
47 "where at least one report is valid (not suppressed)");
51 void BugReporterContext::anchor() {}
65 static inline const Stmt*
88 if (X->
getTag() == tagPreferred && Y->
getTag() == tagLesser)
91 if (Y->
getTag() == tagPreferred && X->
getTag() == tagLesser)
103 unsigned N = path.size();
110 for (
unsigned i = 0; i < N; ++i) {
114 switch (piece->getKind()) {
128 dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
130 cast<PathDiagnosticEventPiece>(piece);
144 path.push_back(piece);
150 typedef llvm::DenseMap<const PathPieces *, const LocationContext *>
158 bool containsSomethingInteresting =
false;
159 const unsigned N = pieces.size();
161 for (
unsigned i = 0 ; i < N ; ++i) {
167 switch (piece->getKind()) {
171 assert(LCM.count(&call->
path));
173 containsSomethingInteresting =
true;
180 containsSomethingInteresting =
true;
187 containsSomethingInteresting =
true;
195 containsSomethingInteresting |= !
event->
isPrunable();
202 pieces.push_back(piece);
205 return containsSomethingInteresting;
220 for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
224 assert((*I)->getLocation().asLocation().isValid());
228 if (LastCallLocation) {
245 assert(ThisCallLocation &&
"Outermost call has an invalid location");
254 for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
262 dyn_cast<PathDiagnosticControlFlowPiece>(*I)) {
263 const Stmt *Start = CF->getStartLocation().asStmt();
264 const Stmt *
End = CF->getEndLocation().asStmt();
265 if (Start && isa<CXXDefaultInitExpr>(Start)) {
268 }
else if (End && isa<CXXDefaultInitExpr>(End)) {
269 PathPieces::iterator
Next = std::next(I);
272 dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
273 NextCF->setStartLocation(CF->getStartLocation());
289 for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
296 if (!(*I)->getLocation().isValid() ||
297 !(*I)->getLocation().asLocation().isValid()) {
331 R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
341 Decl const &getCodeDecl() {
return R->getErrorNode()->getCodeDecl(); }
343 ParentMap& getParentMap() {
return LC->getParentMap(); }
346 return getParentMap().getParent(S);
349 NodeMapClosure& getNodeResolver()
override {
return NMC; }
357 bool supportsLogicalOpControlFlow()
const {
358 return PDC ? PDC->supportsLogicalOpControlFlow() :
true;
364 PathDiagnosticBuilder::ExecutionContinues(
const ExplodedNode *N) {
373 PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
377 if (os.str().empty())
383 os <<
"Execution continues on line "
384 << getSourceManager().getExpansionLineNumber(Loc.
asLocation())
387 os <<
"Execution jumps to the end of the ";
389 if (isa<ObjCMethodDecl>(D))
391 else if (isa<FunctionDecl>(D))
394 assert(isa<BlockDecl>(D));
395 os <<
"anonymous block";
411 switch (Parent->getStmtClass()) {
412 case Stmt::ForStmtClass:
413 case Stmt::DoStmtClass:
414 case Stmt::WhileStmtClass:
415 case Stmt::ObjCForCollectionStmtClass:
416 case Stmt::CXXForRangeStmtClass:
432 switch (Parent->getStmtClass()) {
433 case Stmt::BinaryOperatorClass: {
439 case Stmt::CompoundStmtClass:
440 case Stmt::StmtExprClass:
442 case Stmt::ChooseExprClass:
445 if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S)
449 case Stmt::BinaryConditionalOperatorClass:
450 case Stmt::ConditionalOperatorClass:
453 if (allowNestedContexts ||
454 cast<AbstractConditionalOperator>(Parent)->getCond() == S)
458 case Stmt::CXXForRangeStmtClass:
459 if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
462 case Stmt::DoStmtClass:
464 case Stmt::ForStmtClass:
465 if (cast<ForStmt>(Parent)->getBody() == S)
468 case Stmt::IfStmtClass:
469 if (cast<IfStmt>(Parent)->getCond() != S)
472 case Stmt::ObjCForCollectionStmtClass:
473 if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
476 case Stmt::WhileStmtClass:
477 if (cast<WhileStmt>(Parent)->getCond() != S)
487 assert(S &&
"Cannot have null Stmt for PathDiagnosticLocation");
494 assert(S &&
"Null Stmt passed to getEnclosingStmtLocation");
504 ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
513 for (
auto &V : visitors) {
528 typedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*>
StackDiagPair;
536 dyn_cast<PathDiagnosticEventPiece>(P)) {
538 if (ep->hasCallStackHint())
539 for (StackDiagVector::iterator I = CallStack.begin(),
540 E = CallStack.end(); I != E; ++I) {
543 std::string stackMsg = ep->getCallStackMessage(N);
559 ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
580 LCM[&C->
path] = CE->getCalleeContext();
598 if (VisitedEntireCall) {
599 C = cast<PathDiagnosticCallPiece>(PD.
getActivePath().front());
601 const Decl *Caller = CE->getLocationContext()->getDecl();
604 LCM[&C->
path] = CE->getCalleeContext();
608 if (!CallStack.empty()) {
609 assert(CallStack.back().first ==
C);
610 CallStack.pop_back();
627 switch (T->getStmtClass()) {
631 case Stmt::GotoStmtClass:
632 case Stmt::IndirectGotoStmtClass: {
639 llvm::raw_string_ostream os(sbuf);
642 os <<
"Control jumps to line "
645 Start, End, os.str()));
649 case Stmt::SwitchStmtClass: {
652 llvm::raw_string_ostream os(sbuf);
657 switch (S->getStmtClass()) {
659 os <<
"No cases match in the switch statement. "
660 "Control jumps to line "
663 case Stmt::DefaultStmtClass:
664 os <<
"Control jumps to the 'default' case at line "
668 case Stmt::CaseStmtClass: {
669 os <<
"Control jumps to 'case ";
670 const CaseStmt *Case = cast<CaseStmt>(
S);
674 bool GetRawInt =
true;
676 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
689 os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
697 Start, End, os.str()));
700 os <<
"'Default' branch taken. ";
703 Start, End, os.str()));
709 case Stmt::BreakStmtClass:
710 case Stmt::ContinueStmtClass: {
712 llvm::raw_string_ostream os(sbuf);
715 Start, End, os.str()));
720 case Stmt::BinaryConditionalOperatorClass:
721 case Stmt::ConditionalOperatorClass: {
723 llvm::raw_string_ostream os(sbuf);
724 os <<
"'?' condition is ";
734 End = PDB.getEnclosingStmtLocation(S);
737 Start, End, os.str()));
742 case Stmt::BinaryOperatorClass: {
743 if (!PDB.supportsLogicalOpControlFlow())
748 llvm::raw_string_ostream os(sbuf);
749 os <<
"Left side of '";
752 os <<
"&&" <<
"' is ";
760 Start,
End, os.str()));
767 Start, End, os.str()));
772 os <<
"||" <<
"' is ";
779 Start, End, os.str()));
787 Start,
End, os.str()));
794 case Stmt::DoStmtClass: {
797 llvm::raw_string_ostream os(sbuf);
799 os <<
"Loop condition is true. ";
803 End = PDB.getEnclosingStmtLocation(S);
806 Start, End, os.str()));
812 End = PDB.getEnclosingStmtLocation(S);
815 Start, End,
"Loop condition is false. Exiting loop"));
821 case Stmt::WhileStmtClass:
822 case Stmt::ForStmtClass: {
825 llvm::raw_string_ostream os(sbuf);
827 os <<
"Loop condition is false. ";
830 End = PDB.getEnclosingStmtLocation(S);
833 Start, End, os.str()));
838 End = PDB.getEnclosingStmtLocation(S);
841 Start, End,
"Loop condition is true. Entering loop body"));
847 case Stmt::IfStmtClass: {
851 End = PDB.getEnclosingStmtLocation(S);
855 Start, End,
"Taking false branch"));
858 Start, End,
"Taking true branch"));
869 for (
auto &V : visitors) {
878 if (!PDB.getBugReport()->isValid())
899 if (isa<AbstractConditionalOperator>(E))
903 if (B->isLogicalOp())
916 void markDead() { IsDead =
true; }
917 bool isDead()
const {
return IsDead; }
922 bool firstCharOnly =
false) {
924 const Stmt *Original =
S;
928 switch (S->getStmtClass()) {
931 case Stmt::ParenExprClass:
932 case Stmt::GenericSelectionExprClass:
933 S = cast<Expr>(
S)->IgnoreParens();
934 firstCharOnly =
true;
936 case Stmt::BinaryConditionalOperatorClass:
937 case Stmt::ConditionalOperatorClass:
938 S = cast<AbstractConditionalOperator>(
S)->getCond();
939 firstCharOnly =
true;
941 case Stmt::ChooseExprClass:
942 S = cast<ChooseExpr>(
S)->getCond();
943 firstCharOnly =
true;
945 case Stmt::BinaryOperatorClass:
946 S = cast<BinaryOperator>(
S)->getLHS();
947 firstCharOnly =
true;
965 std::vector<ContextLocation> CLocs;
966 typedef std::vector<ContextLocation>::iterator iterator;
968 PathDiagnosticBuilder &PDB;
981 if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
983 rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC,
true));
994 if (!PD.path.empty()) {
995 PrevLoc = (*PD.path.begin())->getLocation();
997 if (
const Stmt *S = PrevLoc.asStmt())
998 addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1003 while (!CLocs.empty()) popLocation();
1009 PDB.getSourceManager());
1014 void flushLocations() {
1015 while (!CLocs.empty())
1021 bool IsPostJump =
false);
1025 void addContext(
const Stmt *S);
1027 void addExtendedContext(
const Stmt *S);
1038 return PDB.getEnclosingStmtLocation(S);
1047 if (Container == Containee)
1054 if (
const Stmt *ContainerS = Container.
asStmt()) {
1056 if (S == ContainerS)
1058 S = PDB.getParent(S);
1078 assert(ContainerBegLine <= ContainerEndLine);
1079 assert(ContaineeBegLine <= ContaineeEndLine);
1081 return (ContainerBegLine <= ContaineeBegLine &&
1082 ContainerEndLine >= ContaineeEndLine &&
1083 (ContainerBegLine != ContaineeBegLine ||
1086 (ContainerEndLine != ContaineeEndLine ||
1092 if (!PrevLoc.isValid()) {
1125 while (!CLocs.empty()) {
1126 ContextLocation &TopContextLoc = CLocs.back();
1129 if (TopContextLoc == CLoc) {
1131 if (IsConsumedExpr(TopContextLoc))
1132 TopContextLoc.markDead();
1138 TopContextLoc.markDead();
1142 if (containsLocation(TopContextLoc, CLoc)) {
1146 if (IsConsumedExpr(CLoc)) {
1147 CLocs.push_back(ContextLocation(CLoc,
true));
1152 CLocs.push_back(ContextLocation(CLoc, IsPostJump));
1165 if (
const Expr *
X = dyn_cast_or_null<Expr>(L.
asStmt()))
1171 void EdgeBuilder::addExtendedContext(
const Stmt *S) {
1175 const Stmt *Parent = PDB.getParent(S);
1177 if (isa<CompoundStmt>(Parent))
1178 Parent = PDB.getParent(Parent);
1184 switch (Parent->getStmtClass()) {
1185 case Stmt::DoStmtClass:
1186 case Stmt::ObjCAtSynchronizedStmtClass:
1196 void EdgeBuilder::addContext(
const Stmt *S) {
1205 while (!CLocs.empty()) {
1209 if (TopContextLoc == L)
1212 if (containsLocation(TopContextLoc, L)) {
1246 switch (Ex->getStmtClass()) {
1248 if (!isa<CastExpr>(Ex))
1251 case Stmt::BinaryOperatorClass:
1252 case Stmt::UnaryOperatorClass: {
1253 for (
const Stmt *SubStmt : Ex->children()) {
1254 if (
const Expr *child = dyn_cast_or_null<Expr>(SubStmt)) {
1276 if (
const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
1279 PE = FD->param_end();
1281 for (; AI != AE && PI != PE; ++AI, ++PI) {
1282 if (
const Expr *ArgE = *AI) {
1284 Loc LV = State->
getLValue(PD, CalleeCtx);
1299 switch (Term->getStmtClass()) {
1300 case Stmt::ForStmtClass:
1301 case Stmt::WhileStmtClass:
1302 case Stmt::ObjCForCollectionStmtClass:
1303 case Stmt::CXXForRangeStmtClass:
1341 const Stmt *S = SP->getStmt();
1351 const Stmt *LoopBody =
nullptr;
1352 switch (Term->getStmtClass()) {
1353 case Stmt::CXXForRangeStmtClass: {
1362 case Stmt::ForStmtClass: {
1363 const ForStmt *FS = cast<ForStmt>(Term);
1369 case Stmt::ObjCForCollectionStmtClass: {
1374 case Stmt::WhileStmtClass:
1375 LoopBody = cast<WhileStmt>(Term)->getBody();
1390 ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
1391 EdgeBuilder EB(PD, PDB);
1404 if (
const Expr *Ex = PS->getStmtAs<
Expr>())
1411 const Stmt *S = CE->getCalleeContext()->getCallSite();
1412 if (
const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1420 LCM[&C->
path] = CE->getCalleeContext();
1423 EB.flushLocations();
1435 const Decl *D = CE->getCalleeContext()->getDecl();
1442 EB.flushLocations();
1452 if (VisitedEntireCall) {
1453 C = cast<PathDiagnosticCallPiece>(PD.
getActivePath().front());
1455 const Decl *Caller = CE->getLocationContext()->getDecl();
1457 LCM[&C->
path] = CE->getCalleeContext();
1463 if (!CallStack.empty()) {
1464 assert(CallStack.back().first ==
C);
1465 CallStack.pop_back();
1483 if (CallerCtx != CalleeCtx) {
1486 CalleeCtx, CallerCtx);
1491 if (
const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1495 if (
const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1497 else if (
const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1498 CS = dyn_cast<CompoundStmt>(WS->getBody());
1502 "Looping back to the head of the loop");
1515 const CFGBlock *BSrc = BE->getSrc();
1538 EB.addContext(Term);
1550 EB.addContext(stmt);
1553 EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1567 for (
auto &V : visitors) {
1570 EB.addEdge(Loc,
true);
1575 EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1580 return PDB.getBugReport()->isValid();
1615 dyn_cast_or_null<ObjCForCollectionStmt>(S))
1616 return FS->getElement();
1623 "Loop body skipped when range is empty";
1625 "Loop body skipped when collection is empty";
1630 ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
1663 if (VisitedEntireCall) {
1665 C = cast<PathDiagnosticCallPiece>(
P);
1667 const Decl *Caller = CE->getLocationContext()->getDecl();
1678 assert(LCM[&C->
path] ==
nullptr ||
1679 LCM[&C->
path] == CE->getCalleeContext());
1680 LCM[&C->
path] = CE->getCalleeContext();
1695 if (!CallStack.empty()) {
1696 assert(CallStack.back().first ==
C);
1697 CallStack.pop_back();
1714 const Stmt *S = CE->getCalleeContext()->getCallSite();
1716 if (
const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1728 LCM[&C->
path] = CE->getCalleeContext();
1744 if (
const Expr *Ex = PS->getStmtAs<
Expr>())
1752 if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
1767 if (CallerCtx != CalleeCtx) {
1770 CalleeCtx, CallerCtx);
1775 if (
const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1777 const Stmt *Body =
nullptr;
1779 if (
const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1780 Body = FS->getBody();
1781 else if (
const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1782 Body = WS->getBody();
1784 dyn_cast<ObjCForCollectionStmt>(Loop)) {
1785 Body = OFS->getBody();
1787 dyn_cast<CXXForRangeStmt>(Loop)) {
1788 Body = FRS->getBody();
1800 if (
const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
1807 const CFGBlock *BSrc = BE->getSrc();
1818 const char *str =
nullptr;
1821 if (!IsInLoopBody) {
1822 if (isa<ObjCForCollectionStmt>(Term)) {
1824 }
else if (isa<CXXForRangeStmt>(Term)) {
1843 }
else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
1844 isa<GotoStmt>(Term)) {
1857 for (
auto &V : visitors) {
1893 if (isa<ExprWithCleanups>(S) ||
1894 isa<CXXBindTemporaryExpr>(S) ||
1895 isa<SubstNonTypeTemplateParmExpr>(S))
1905 switch (S->getStmtClass()) {
1906 case Stmt::BinaryOperatorClass: {
1912 case Stmt::IfStmtClass:
1913 return cast<IfStmt>(
S)->getCond() == Cond;
1914 case Stmt::ForStmtClass:
1915 return cast<ForStmt>(
S)->getCond() == Cond;
1916 case Stmt::WhileStmtClass:
1917 return cast<WhileStmt>(
S)->getCond() == Cond;
1918 case Stmt::DoStmtClass:
1919 return cast<DoStmt>(
S)->getCond() == Cond;
1920 case Stmt::ChooseExprClass:
1921 return cast<ChooseExpr>(
S)->getCond() == Cond;
1922 case Stmt::IndirectGotoStmtClass:
1923 return cast<IndirectGotoStmt>(
S)->getTarget() == Cond;
1924 case Stmt::SwitchStmtClass:
1925 return cast<SwitchStmt>(
S)->getCond() == Cond;
1926 case Stmt::BinaryConditionalOperatorClass:
1927 return cast<BinaryConditionalOperator>(
S)->getCond() == Cond;
1928 case Stmt::ConditionalOperatorClass: {
1930 return CO->
getCond() == Cond ||
1934 case Stmt::ObjCForCollectionStmtClass:
1935 return cast<ObjCForCollectionStmt>(
S)->getElement() == Cond;
1936 case Stmt::CXXForRangeStmtClass: {
1946 if (
const ForStmt *FS = dyn_cast<ForStmt>(FL))
1947 return FS->getInc() == S || FS->getInit() ==
S;
1949 return FRS->getInc() == S || FRS->getRangeStmt() == S ||
1950 FRS->getLoopVarStmt() || FRS->getRangeInit() ==
S;
1964 PathPieces::iterator Prev = pieces.end();
1965 for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
1977 const Stmt *InnerStmt =
nullptr;
1978 while (NextSrcContext.
isValid() && NextSrcContext.
asStmt() != InnerStmt) {
1979 SrcContexts.push_back(NextSrcContext);
1980 InnerStmt = NextSrcContext.
asStmt();
1995 if (!DstContext.isValid() || DstContext.asStmt() == Dst)
1999 if (std::find(SrcContexts.begin(), SrcContexts.end(), DstContext) !=
2027 I = pieces.insert(I, Piece);
2044 for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
2055 if (!s1Start || !s1End)
2058 PathPieces::iterator NextI = I; ++NextI;
2089 if (!s2Start || !s2End || s1End != s2Start)
2094 if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) ||
2095 isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) ||
2096 isa<CXXForRangeStmt>(s1Start)))
2106 I = pieces.erase(I);
2125 const llvm::MemoryBuffer *Buffer = SM.
getBuffer(FID, &Invalid);
2131 StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);
2137 if (Snippet.find_first_of(
"\r\n") != StringRef::npos)
2141 return Snippet.size();
2168 for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
2181 PathPieces::iterator NextI = I; ++NextI;
2189 if (isa<PathDiagnosticEventPiece>(*NextI)) {
2205 if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
2206 const size_t MAX_SHORT_LINE_LENGTH = 80;
2208 if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {
2210 if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {
2212 I = Path.erase(NextI);
2239 bool erased =
false;
2241 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
2271 std::swap(SecondLoc, FirstLoc);
2280 const size_t MAX_PUNY_EDGE_LENGTH = 2;
2281 if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {
2293 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
2300 PathPieces::iterator NextI = I; ++NextI;
2320 bool hasChanges =
false;
2325 for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
2330 if (!OCS.count(CallI)) {
2352 PathPieces::iterator NextI = I; ++NextI;
2384 if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
2399 if (s1End && s1End == s2Start && level2) {
2400 bool removeEdge =
false;
2426 else if (s1Start && s2End &&
2439 else if (s1Start && s2End &&
2463 if (s1End == s2Start) {
2465 dyn_cast_or_null<ObjCForCollectionStmt>(level3);
2511 const Decl *D = LCM[&Path]->getDecl();
2523 void BugType::anchor() { }
2527 void BuiltinBug::anchor() {}
2533 void BugReport::NodeResolver::anchor() {}
2539 llvm::FoldingSetNodeID
ID;
2540 visitor->Profile(ID);
2547 Callbacks.push_back(std::move(visitor));
2553 popInterestingSymbolsAndRegions();
2570 hash.AddPointer(&
BT);
2597 if (getInterestingSymbols().insert(sym).second)
2601 getInterestingRegions().insert(meta->getRegion());
2610 if (getInterestingRegions().insert(R).second)
2614 getInterestingSymbols().insert(SR->getSymbol());
2637 return getInterestingSymbols().count(sym);
2644 bool b = getInterestingRegions().count(R);
2648 return getInterestingSymbols().count(SR->getSymbol());
2658 void BugReport::lazyInitializeInterestingSets() {
2666 lazyInitializeInterestingSets();
2671 lazyInitializeInterestingSets();
2675 void BugReport::pushInterestingSymbolsAndRegions() {
2680 void BugReport::popInterestingSymbolsAndRegions() {
2690 const Stmt *S =
nullptr;
2694 if (BE->getBlock() == &Exit)
2707 if (
const Expr *E = dyn_cast_or_null<Expr>(
getStmt()))
2717 return llvm::iterator_range<BugReport::ranges_iterator>(
Ranges.begin(),
2724 "Either Location or ErrorNode should be specified but not both.");
2749 typedef std::vector<BugReportEquivClass *> ContTy;
2750 for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
2757 if (BugTypes.isEmpty())
2766 I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
2767 const_cast<BugType*>(*I)->FlushReports(*
this);
2771 typedef std::vector<BugReportEquivClass *> ContVecTy;
2772 for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
2782 llvm::DeleteContainerSeconds(StrBugTypes);
2785 BugTypes = F.getEmptySet();
2798 std::unique_ptr<ExplodedGraph> Graph;
2804 class TrimmedGraph {
2807 typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
2808 PriorityMapTy PriorityMap;
2810 typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
2813 std::unique_ptr<ExplodedGraph> G;
2816 template <
bool Descending>
2817 class PriorityCompare {
2818 const PriorityMapTy &PriorityMap;
2821 PriorityCompare(
const PriorityMapTy &M) : PriorityMap(M) {}
2824 PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);
2825 PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);
2826 PriorityMapTy::const_iterator E = PriorityMap.end();
2833 return Descending ? LI->second > RI->second
2834 : LI->second < RI->second;
2837 bool operator()(
const NodeIndexPair &LHS,
const NodeIndexPair &RHS)
const {
2838 return (*
this)(LHS.first, RHS.first);
2846 bool popNextReportGraph(ReportGraph &GraphWrapper);
2850 TrimmedGraph::TrimmedGraph(
const ExplodedGraph *OriginalGraph,
2855 G = OriginalGraph->
trim(Nodes, &ForwardMap, &InverseMap);
2860 llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
2862 for (
unsigned i = 0, count = Nodes.size(); i < count; ++i) {
2863 if (
const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) {
2864 ReportNodes.push_back(std::make_pair(NewNode, i));
2865 RemainingNodes.insert(NewNode);
2869 assert(!RemainingNodes.empty() &&
"No error node found in the trimmed graph");
2872 std::queue<const ExplodedNode *> WS;
2874 assert(G->num_roots() == 1);
2875 WS.push(*G->roots_begin());
2876 unsigned Priority = 0;
2878 while (!WS.empty()) {
2882 PriorityMapTy::iterator PriorityEntry;
2884 std::tie(PriorityEntry, IsNew) =
2885 PriorityMap.insert(std::make_pair(Node, Priority));
2889 assert(PriorityEntry->second <= Priority);
2893 if (RemainingNodes.erase(Node))
2894 if (RemainingNodes.empty())
2904 std::sort(ReportNodes.begin(), ReportNodes.end(),
2905 PriorityCompare<true>(PriorityMap));
2908 bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
2909 if (ReportNodes.empty())
2913 std::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val();
2914 assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
2915 "error node not accessible from root");
2919 auto GNew = llvm::make_unique<ExplodedGraph>();
2920 GraphWrapper.BackMap.clear();
2932 InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN);
2933 assert(IMitr != InverseMap.end() &&
"No mapping to original node.");
2934 GraphWrapper.BackMap[NewN] = IMitr->second;
2940 GraphWrapper.ErrorNode = NewN;
2946 GNew->addRoot(NewN);
2953 PriorityCompare<false>(PriorityMap));
2956 GraphWrapper.Graph = std::move(GNew);
2965 typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>,
2968 typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> >
2971 MacroStackTy MacroStack;
2974 for (PathPieces::const_iterator I = path.begin(), E = path.end();
2995 Pieces.push_back(piece);
3002 if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
3003 MacroStack.back().first->subPieces.push_back(piece);
3016 while (!MacroStack.empty()) {
3017 if (InstantiationLoc == MacroStack.back().second) {
3018 MacroGroup = MacroStack.back().first;
3022 if (ParentInstantiationLoc == MacroStack.back().second) {
3023 MacroGroup = MacroStack.back().first;
3027 MacroStack.pop_back();
3030 if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
3037 MacroGroup->subPieces.push_back(NewGroup);
3039 assert(InstantiationLoc.
isFileID());
3040 Pieces.push_back(NewGroup);
3043 MacroGroup = NewGroup;
3044 MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
3048 MacroGroup->subPieces.push_back(piece);
3054 path.insert(path.end(), Pieces.begin(), Pieces.end());
3060 assert(!bugReports.empty());
3062 bool HasValid =
false;
3063 bool HasInvalid =
false;
3066 E = bugReports.end(); I != E; ++I) {
3067 if ((*I)->isValid()) {
3069 errorNodes.push_back((*I)->getErrorNode());
3073 errorNodes.push_back(
nullptr);
3092 TrimmedGraph TrimG(&getGraph(), errorNodes);
3093 ReportGraph ErrorGraph;
3095 while (TrimG.popNextReportGraph(ErrorGraph)) {
3097 assert(ErrorGraph.Index < bugReports.size());
3098 BugReport *R = bugReports[ErrorGraph.Index];
3099 assert(R &&
"No original report found for sliced graph.");
3100 assert(R->isValid() &&
"Report selected by trimmed graph marked invalid.");
3103 PathDiagnosticBuilder PDB(*
this, R, ErrorGraph.BackMap, &PC);
3107 R->addVisitor(llvm::make_unique<NilReceiverBRVisitor>());
3108 R->addVisitor(llvm::make_unique<ConditionBRVisitor>());
3109 R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());
3112 unsigned origReportConfigToken, finalReportConfigToken;
3122 E = R->visitor_end(); I != E; ++I)
3123 visitors.push_back((*I)->clone());
3127 origReportConfigToken = R->getConfigurationChangeToken();
3131 std::unique_ptr<PathDiagnosticPiece> LastPiece;
3134 if (std::unique_ptr<PathDiagnosticPiece> Piece =
3135 (*I)->getEndPath(PDB, N, *R)) {
3136 assert (!LastPiece &&
3137 "There can only be one final piece in a diagnostic.");
3138 LastPiece = std::move(Piece);
3153 switch (ActiveScheme) {
3172 finalReportConfigToken = R->getConfigurationChangeToken();
3173 }
while (finalReportConfigToken != origReportConfigToken);
3179 if (!PD.
path.empty()) {
3180 if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) {
3182 assert(stillHasNotes);
3183 (void)stillHasNotes;
3216 assert(!HasInvalid &&
"Inconsistent suppression");
3222 BugTypes = F.add(BugTypes, BT);
3228 E->getLocationContext()->getAnalysisDeclContext();
3238 bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid();
3239 assert(ValidSourceLoc);
3242 if (!ValidSourceLoc)
3246 llvm::FoldingSetNodeID
ID;
3257 EQClasses.InsertNode(EQ, InsertPos);
3258 EQClassesVector.push_back(EQ);
3260 EQ->AddReport(std::move(R));
3269 struct FRIEC_WLItem {
3274 : N(n), I(N->succ_begin()), E(N->succ_end()) {}
3295 bugReports.push_back(R);
3309 for (; I != E; ++I) {
3314 if (errorNode->
isSink()) {
3316 "BugType::isSuppressSink() should not be 'true' for sink end nodes");
3320 bugReports.push_back(I);
3328 typedef FRIEC_WLItem WLItem;
3330 llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
3333 WL.push_back(errorNode);
3334 Visited[errorNode] = 1;
3336 while (!WL.empty()) {
3337 WLItem &WI = WL.back();
3338 assert(!WI.N->succ_empty());
3340 for (; WI.I != WI.E; ++WI.I) {
3346 bugReports.push_back(I);
3357 unsigned &mark = Visited[Succ];
3367 if (!WL.empty() && &WL.back() == &WI)
3374 return exampleReport;
3380 if (exampleReport) {
3382 FlushReport(exampleReport, *PDC, bugReports);
3387 void BugReporter::FlushReport(
BugReport *exampleReport,
3403 MaxBugClassSize = std::max(bugReports.size(),
3404 static_cast<size_t>(MaxBugClassSize));
3410 if (!bugReports.empty())
3411 if (!generatePathDiagnostic(*D.get(), PD, bugReports))
3414 MaxValidBugClassSize = std::max(bugReports.size(),
3415 static_cast<size_t>(MaxValidBugClassSize));
3421 D->resetDiagnosticLocationToMainFile();
3425 if (D->path.empty()) {
3427 auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
3430 piece->addRange(Range);
3431 D->setEndOfPath(std::move(piece));
3436 for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
3437 e = Meta.end(); i != e; ++i) {
3446 StringRef Name, StringRef Category,
3449 EmitBasicReport(DeclWithIssue, Checker->
getCheckName(), Name, Category, Str,
3454 StringRef name, StringRef category,
3459 BugType *BT = getBugTypeForName(CheckName, name, category);
3460 auto R = llvm::make_unique<BugReport>(*
BT, str, Loc);
3461 R->setDeclWithIssue(DeclWithIssue);
3465 emitReport(std::move(R));
3469 StringRef category) {
3471 llvm::raw_svector_ostream(fullDesc) << CheckName.
getName() <<
":" << name
3473 BugType *&BT = StrBugTypes[fullDesc];
3475 BT =
new BugType(CheckName, name, category);
3481 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
3482 llvm::errs() <<
"[" << index++ <<
"] ";
3484 llvm::errs() <<
"\n";
3489 llvm::errs() <<
"CALL\n--------------\n";
3493 else if (
const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
3494 llvm::errs() << *ND <<
"\n";
3500 llvm::errs() <<
"EVENT\n--------------\n";
3501 llvm::errs() << getString() <<
"\n";
3502 llvm::errs() <<
" ---- at ----\n";
3507 llvm::errs() <<
"CONTROL\n--------------\n";
3508 getStartLocation().dump();
3509 llvm::errs() <<
" ---- to ----\n";
3510 getEndLocation().dump();
3514 llvm::errs() <<
"MACRO\n--------------\n";
3520 llvm::errs() <<
"<INVALID>\n";
3527 llvm::errs() <<
"<range>\n";
3530 asLocation().dump();
3531 llvm::errs() <<
"\n";
3537 llvm::errs() <<
"<NULL STMT>\n";
3540 if (
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
3541 llvm::errs() << *ND <<
"\n";
3542 else if (isa<BlockDecl>(D))
3544 llvm::errs() <<
"<block>\n";
3546 llvm::errs() <<
"<unknown decl>\n";
3548 llvm::errs() <<
"<NULL DECL>\n";
VisitorList::iterator visitor_iterator
Defines the clang::ASTContext interface.
static void removeEdgesToDefaultInitializers(PathPieces &Pieces)
SourceLocation getEnd() const
static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE)
static bool removeUnneededCalls(PathPieces &pieces, BugReport *R, LocationContextMap &LCM)
const Decl * getDeclWithIssue() const
static void removeRedundantMsgs(PathPieces &path)
ParmVarDecl *const * param_const_iterator
static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS)
static Optional< size_t > getLengthOnSingleLine(SourceManager &SM, SourceRange Range)
const SourceRange * ranges_iterator
MemRegion - The root abstract class for all memory regions.
bool hasCallStackMessage()
StringRef getCategory() const
bool isInteresting(SymbolRef sym)
PathDiagnosticLocation getLocation() const override
llvm::DenseSet< SymbolRef > Symbols
succ_iterator succ_begin()
const ExplodedNode * getErrorNode() const
virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const
Return the "definitive" location of the reported bug.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
SVal getRawSVal(Loc LV, QualType T=QualType()) const
Returns the "raw" SVal bound to LV before any value simplfication.
Defines the SourceManager interface.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
SmallVector< StackDiagPair, 6 > StackDiagVector
static void adjustCallLocations(PathPieces &Pieces, PathDiagnosticLocation *LastCallLocation=nullptr)
StringRef getName() const
void setPrunable(bool isPrunable, bool override=false)
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
static bool optimizeEdges(PathPieces &path, SourceManager &SM, OptimizedCallsSet &OCS, LocationContextMap &LCM)
PathDiagnosticLocation getLocation() const
unsigned succ_size() const
static const Stmt * GetCurrentOrPreviousStmt(const ExplodedNode *N)
SmallVector< SourceRange, 4 > Ranges
static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond)
void dump() const override
const MemRegion * getBaseRegion() const
Defines the Objective-C statement AST node classes.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
ParmVarDecl - Represents a parameter to a function.
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.
static void removePiecesWithInvalidLocations(PathPieces &Pieces)
BoundNodesTreeBuilder Nodes
static void updateStackPiecesWithMessage(PathDiagnosticPiece *P, StackDiagVector &CallStack)
FullSourceLoc asLocation() const
Symbolic value. These values used to capture symbolic execution of the program.
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
void setStartLocation(const PathDiagnosticLocation &L)
unsigned getExpansionLineNumber(bool *Invalid=nullptr) const
void addRange(SourceRange R)
Add a range to a bug report.
std::pair< SourceLocation, SourceLocation > getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
friend class BugReportEquivClass
succ_iterator succ_begin()
static PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P, const LocationContext *LC, bool allowNestedContexts)
static void removeIdenticalEvents(PathPieces &path)
static const char StrLoopBodyZero[]
StringRef getString() const
const BugType & getBugType() const
void pushActivePath(PathPieces *p)
const Stmt * getStmt() const
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
SmallVector< Regions *, 2 > interestingRegions
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
bool isPrunable() const
Return true if the diagnostic piece is prunable.
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
virtual llvm::iterator_range< ranges_iterator > getRanges()
Get the SourceRanges associated with the report.
static bool IsControlFlowExpr(const Stmt *S)
llvm::FoldingSet< BugReporterVisitor > CallbacksSet
Used for ensuring the visitors are only added once.
virtual void FlushReports(BugReporter &BR)
llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts
static void addEdgeToPath(PathPieces &path, PathDiagnosticLocation &PrevLoc, PathDiagnosticLocation NewLoc, const LocationContext *LC)
Adds a sanitized control-flow diagnostic edge to a path.
virtual ~BugReporterVisitor()
STATISTIC(MaxBugClassSize,"The maximum number of bug reports in the same equivalence class")
static bool isJumpToFalseBranch(const BlockEdge *BE)
const Decl * asDecl() const
A builtin binary operation expression such as "x + y" or "x <= y".
const Stmt * getCallSite() const
Expr * IgnoreParenCasts() LLVM_READONLY
static PathDiagnosticCallPiece * construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
static const Stmt * getStmtBeforeCond(ParentMap &PM, const Stmt *Term, const ExplodedNode *N)
StringRef getDescription() const
ExplodedNode * getFirstPred()
StringRef getShortDescription(bool UseFallback=true) const
PathDiagnosticLocation callEnter
static void reversePropagateIntererstingSymbols(BugReport &R, InterestingExprs &IE, const ProgramState *State, const Expr *Ex, const LocationContext *LCtx)
void dump() const override
virtual PathDiagnosticLocation getLocation() const =0
void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)
Add custom or predefined bug report visitors to this report.
const Stmt * asStmt() const
llvm::DenseSet< const Expr * > InterestingExprs
bool isSuppressOnSink() const
const LocationContext * getLocationContext() const
const CFGBlock * getSrc() const
StringRef getName() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static BugReport * FindReportInEquivalenceClass(BugReportEquivClass &EQ, SmallVectorImpl< BugReport * > &bugReports)
llvm::DenseSet< const PathDiagnosticCallPiece * > OptimizedCallsSet
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
static const char * getTag()
ID
Defines the set of possible language-specific address spaces.
const CFGBlock * getDst() const
virtual const ExtraTextList & getExtraText()
bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const
Returns true if the spelling locations for both SourceLocations are part of the same file buffer...
const Decl * getCallee() const
const ProgramStateRef & getState() const
Stmt * getTerminatorCondition(bool StripParens=true)
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
~GRBugReporter() override
const SourceManager & getManager() const
ParentMap & getParentMap() const
SVal getSVal(const Stmt *S, const LocationContext *LCtx) const
Returns the SVal bound to the statement 'S' in the state's environment.
static bool lexicalContains(ParentMap &PM, const Stmt *X, const Stmt *Y)
Return true if X is contained by Y.
static void reversePropagateInterestingSymbols(BugReport &R, InterestingExprs &IE, const ProgramState *State, const LocationContext *CalleeCtx, const LocationContext *CallerCtx)
PathDiagnosticLocation getEndLocation() const
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void Register(BugType *BT)
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
unsigned ConfigurationChangeToken
void FlushReports()
Generate and flush diagnostics for all bug reports.
static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM, SourceManager &SM)
void markInteresting(SymbolRef sym)
static const Stmt * GetPreviousStmt(const ExplodedNode *N)
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
PathDiagnosticLocation getStartLocation() const
CheckName getCheckName() const
static bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
llvm::ilist< BugReport >::iterator iterator
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
bool isConsumedExpr(Expr *E) const
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
CFGTerminator getTerminator()
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static PathDiagnosticEventPiece * eventsDescribeSameCondition(PathDiagnosticEventPiece *X, PathDiagnosticEventPiece *Y)
llvm::DenseSet< const MemRegion * > Regions
static std::unique_ptr< PathDiagnosticPiece > getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR)
Generates the default final diagnostic piece.
Stmt * getParent(Stmt *) const
static void simplifySimpleBranches(PathPieces &pieces)
Move edges from a branch condition to a branch target when the condition is simple.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
const ExplodedNode * ErrorNode
const StackFrameContext * getCurrentStackFrame() const
virtual PathGenerationScheme getGenerationScheme() const
Stmt * getParentIgnoreParens(Stmt *) const
StringRef getCheckName() const
const ExplodedNode *const * const_succ_iterator
bool isValid() const
Return true if this is a valid SourceLocation object.
ExplodedGraph & getGraph()
void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL)
PathDiagnosticLocation callReturn
void Profile(llvm::FoldingSetNodeID &ID) const
void setCallee(const CallEnter &CE, const SourceManager &SM)
bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, ArrayRef< BugReport * > &bugReports) override
PathDiagnosticLocation Location
const Decl * getDecl() const
SourceLocation getBegin() const
const Decl * DeclWithIssue
PathDiagnosticLocation getLocation() const override
static const Stmt * getEnclosingParent(const Stmt *S, const ParentMap &PM)
static bool isLogicalOp(Opcode Opc)
static void removePunyEdges(PathPieces &path, SourceManager &SM, ParentMap &PM)
static bool hasImplicitBody(const Decl *D)
SmallVector< Symbols *, 2 > interestingSymbols
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
virtual void Profile(llvm::FoldingSetNodeID &hash) const
static const char StrLoopCollectionEmpty[]
static const Stmt * getLocStmt(PathDiagnosticLocation L)
const LocationContext * getLocationContext() const
static __inline__ uint32_t volatile uint32_t * p
virtual ~BugReporterData()
PathDiagnosticLocation getUniqueingLocation() const
Get the location on which the report should be uniqued.
static bool GenerateMinimalPathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
const MemRegion * getAsRegion() const
static const Stmt * getTerminatorCondition(const CFGBlock *B)
bool isBodyAutosynthesizedFromModelFile() const
Checks if the body of the Decl is generated by the BodyFarm from a model file.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
void setEndLocation(const PathDiagnosticLocation &L)
static bool isLoop(const Stmt *Term)
const ExplodedNode *const * const_pred_iterator
Represents Objective-C's collection statement.
void setEndOfPath(std::unique_ptr< PathDiagnosticPiece > EndPiece)
void setCallStackMessage(StringRef st)
const Decl * getCaller() const
void dump() const override
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
PathDiagnosticRange asRange() const
ProgramStateManager & getStateManager()
static void CompactPathDiagnostic(PathPieces &path, const SourceManager &SM)
PathPieces & getActivePath()
pred_iterator pred_begin()
static const Stmt * getStmtParent(const Stmt *S, const ParentMap &PM)
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
llvm::DenseMap< const PathPieces *, const LocationContext * > LocationContextMap
static void removeContextCycles(PathPieces &Path, SourceManager &SM, ParentMap &PM)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const
Get the lvalue for a variable reference.
static bool GenerateAlternateExtensivePathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
FullSourceLoc getExpansionLoc() const
static bool GenerateExtensivePathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
DeclStmt * getLoopVarStmt()
A trivial tuple used to represent a source range.
static void addContextEdges(PathPieces &pieces, SourceManager &SM, const ParentMap &PM, const LocationContext *LCtx)
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
bool isWithinCall() const
bool shouldReportIssuesInMainSourceFile()
static const char StrEnteringLoop[]
std::pair< PathDiagnosticCallPiece *, const ExplodedNode * > StackDiagPair
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
static const char StrLoopRangeEmpty[]
This class handles loading and caching of source files into memory.
Expr * IgnoreParens() LLVM_READONLY
static const char * getTag()
static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term)
void dump() const override