/// Recursively scan through a path and prune out calls and macros pieces
/// that aren't needed. Return true if afterwards the path contains
/// "interesting stuff" which means it shouldn't be pruned from the parent path.
-static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
- LocationContextMap &LCM,
+static bool removeUnneededCalls(PathPieces &pieces, const BugReport *R,
+ const LocationContextMap &LCM,
bool IsInteresting = false) {
bool containsSomethingInteresting = IsInteresting;
const unsigned N = pieces.size();
// Check if the location context is interesting.
assert(LCM.count(&call.path));
if (!removeUnneededCalls(call.path, R, LCM,
- R->isInteresting(LCM[&call.path])))
+ R->isInteresting(LCM.lookup(&call.path))))
continue;
containsSomethingInteresting = true;
class PathDiagnosticBuilder : public BugReporterContext {
BugReport *R;
- PathDiagnosticConsumer *PDC;
+ const PathDiagnosticConsumer *PDC;
public:
const LocationContext *LC;
PathDiagnosticBuilder(GRBugReporter &br,
BugReport *r, InterExplodedGraphMap &Backmap,
- PathDiagnosticConsumer *pdc)
+ const PathDiagnosticConsumer *pdc)
: BugReporterContext(br, Backmap), R(r), PDC(pdc),
LC(r->getErrorNode()->getLocationContext()) {}
- PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
+ PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N) const;
PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
- const ExplodedNode *N);
+ const ExplodedNode *N) const;
BugReport *getBugReport() { return R; }
- Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
+ const Decl &getCodeDecl() const { return R->getErrorNode()->getCodeDecl(); }
- ParentMap& getParentMap() { return LC->getParentMap(); }
+ const ParentMap& getParentMap() const { return LC->getParentMap(); }
- const Stmt *getParent(const Stmt *S) {
+ const Stmt *getParent(const Stmt *S) const {
return getParentMap().getParent(S);
}
- PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
+ PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S) const;
PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Minimal;
} // namespace
PathDiagnosticLocation
-PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
+PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) const {
if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N))
return PathDiagnosticLocation(S, getSourceManager(), LC);
PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
- const ExplodedNode *N) {
+ const ExplodedNode *N) const {
// Slow, but probably doesn't matter.
if (os.str().empty())
os << ' ';
}
static PathDiagnosticLocation
-getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,
- const LocationContext *LC, bool allowNestedContexts) {
+getEnclosingStmtLocation(const Stmt *S, const SourceManager &SMgr,
+ const ParentMap &P, const LocationContext *LC,
+ bool allowNestedContexts) {
if (!S)
return {};
}
PathDiagnosticLocation
-PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
+PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) const {
assert(S && "Null Stmt passed to getEnclosingStmtLocation");
return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC,
/*allowNestedContexts=*/false);
using StackDiagVector = SmallVector<StackDiagPair, 6>;
static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
- StackDiagVector &CallStack) {
+ const StackDiagVector &CallStack) {
// If the piece contains a special message, add it to all the call
// pieces on the active stack.
if (auto *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
const CFGBlock *Dst,
const SourceManager &SM,
const LocationContext *LC,
- PathDiagnosticBuilder &PDB,
+ const PathDiagnosticBuilder &PDB,
PathDiagnosticLocation &Start
) {
// Figure out what case arm we took.
std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForGotoOP(
const Stmt *S,
- PathDiagnosticBuilder &PDB,
+ const PathDiagnosticBuilder &PDB,
PathDiagnosticLocation &Start) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
}
std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForBinaryOP(
- const ExplodedNode *N,
- const Stmt *T,
- const CFGBlock *Src,
- const CFGBlock *Dst,
- const SourceManager &SM,
- PathDiagnosticBuilder &PDB,
- const LocationContext *LC) {
+ const ExplodedNode *N, const Stmt *T, const CFGBlock *Src,
+ const CFGBlock *Dst, const SourceManager &SM,
+ const PathDiagnosticBuilder &PDB, const LocationContext *LC) {
+
const auto *B = cast<BinaryOperator>(T);
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE,
const SourceManager &SM,
- PathDiagnosticBuilder &PDB,
+ const PathDiagnosticBuilder &PDB,
PathDiagnostic &PD) {
const LocationContext *LC = N->getLocationContext();
const CFGBlock *Src = BE.getSrc();
return (*(Src->succ_begin()+1) == BE->getDst());
}
-static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
+static bool isContainedByStmt(const ParentMap &PM, const Stmt *S,
+ const Stmt *SubS) {
while (SubS) {
if (SubS == S)
return true;
return false;
}
-static const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
+static const Stmt *getStmtBeforeCond(const ParentMap &PM, const Stmt *Term,
const ExplodedNode *N) {
while (N) {
Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>();
return nullptr;
}
-static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
+static bool isInLoopBody(const ParentMap &PM, const Stmt *S, const Stmt *Term) {
const Stmt *LoopBody = nullptr;
switch (Term->getStmtClass()) {
case Stmt::CXXForRangeStmtClass: {
return S;
}
-static const char StrEnteringLoop[] = "Entering loop body";
-static const char StrLoopBodyZero[] = "Loop body executed 0 times";
-static const char StrLoopRangeEmpty[] =
- "Loop body skipped when range is empty";
-static const char StrLoopCollectionEmpty[] =
- "Loop body skipped when collection is empty";
+llvm::StringLiteral StrEnteringLoop = "Entering loop body";
+llvm::StringLiteral StrLoopBodyZero = "Loop body executed 0 times";
+llvm::StringLiteral StrLoopRangeEmpty = "Loop body skipped when range is empty";
+llvm::StringLiteral StrLoopCollectionEmpty =
+ "Loop body skipped when collection is empty";
static std::unique_ptr<FilesToLineNumsMap>
-findExecutedLines(SourceManager &SM, const ExplodedNode *N);
+findExecutedLines(const SourceManager &SM, const ExplodedNode *N);
/// Generate diagnostics for the node \p N,
/// and write it into \p PD.
}
const CFGBlock *BSrc = BE->getSrc();
- ParentMap &PM = PDB.getParentMap();
+ const ParentMap &PM = PDB.getParentMap();
if (const Stmt *Term = BSrc->getTerminatorStmt()) {
// Are we jumping past the loop body without ever executing the
bool IsInLoopBody =
isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
- const char *str = nullptr;
+ StringRef str;
if (isJumpToFalseBranch(&*BE)) {
if (!IsInLoopBody) {
str = StrEnteringLoop;
}
- if (str) {
+ if (!str.empty()) {
PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
PE->setPrunable(true);
}
static std::unique_ptr<PathDiagnostic>
-generateEmptyDiagnosticForReport(BugReport *R, SourceManager &SM) {
+generateEmptyDiagnosticForReport(const BugReport *R, const SourceManager &SM) {
const BugType &BT = R->getBugType();
return llvm::make_unique<PathDiagnostic>(
R->getBugType().getCheckName(), R->getDeclWithIssue(),
/// This avoids a "swoosh" effect, where an edge from a top-level statement A
/// points to a sub-expression B.1 that's not at the start of B. In these cases,
/// we'd like to see an edge from A to B, then another one from B to B.1.
-static void addContextEdges(PathPieces &pieces, SourceManager &SM,
+static void addContextEdges(PathPieces &pieces, const SourceManager &SM,
const ParentMap &PM, const LocationContext *LCtx) {
PathPieces::iterator Prev = pieces.end();
for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
/// If the locations in the range are not on the same line, returns None.
///
/// Note that this does not do a precise user-visible character or column count.
-static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
+static Optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
SourceRange Range) {
SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
SM.getExpansionRange(Range.getEnd()).getEnd());
}
/// \sa getLengthOnSingleLine(SourceManager, SourceRange)
-static Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
+static Optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
const Stmt *S) {
return getLengthOnSingleLine(SM, S->getSourceRange());
}
/// - if there is an inlined call between the edges instead of a single event.
/// - if the whole statement is large enough that having subexpression arrows
/// might be helpful.
-static void removeContextCycles(PathPieces &Path, SourceManager &SM) {
+static void removeContextCycles(PathPieces &Path, const SourceManager &SM) {
for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
// Pattern match the current piece and its successor.
const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());
}
/// Return true if X is contained by Y.
-static bool lexicalContains(ParentMap &PM, const Stmt *X, const Stmt *Y) {
+static bool lexicalContains(const ParentMap &PM, const Stmt *X, const Stmt *Y) {
while (X) {
if (X == Y)
return true;
}
// Remove short edges on the same line less than 3 columns in difference.
-static void removePunyEdges(PathPieces &path, SourceManager &SM,
- ParentMap &PM) {
+static void removePunyEdges(PathPieces &path, const SourceManager &SM,
+ const ParentMap &PM) {
bool erased = false;
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
}
}
-static bool optimizeEdges(PathPieces &path, SourceManager &SM,
+static bool optimizeEdges(PathPieces &path, const SourceManager &SM,
OptimizedCallsSet &OCS,
- LocationContextMap &LCM) {
+ const LocationContextMap &LCM) {
bool hasChanges = false;
- const LocationContext *LC = LCM[&path];
+ const LocationContext *LC = LCM.lookup(&path);
assert(LC);
- ParentMap &PM = LC->getParentMap();
+ const ParentMap &PM = LC->getParentMap();
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
// Optimize subpaths.
/// statement had an invalid source location), this function does nothing.
// FIXME: We should just generate invalid edges anyway and have the optimizer
// deal with them.
-static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM,
- SourceManager &SM) {
+static void dropFunctionEntryEdge(PathPieces &Path,
+ const LocationContextMap &LCM,
+ const SourceManager &SM) {
const auto *FirstEdge =
dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
if (!FirstEdge)
return;
- const Decl *D = LCM[&Path]->getDecl();
+ const Decl *D = LCM.lookup(&Path)->getDecl();
PathDiagnosticLocation EntryLoc = PathDiagnosticLocation::createBegin(D, SM);
if (FirstEdge->getStartLocation() != EntryLoc)
return;
bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None);
bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive);
- SourceManager &SM = PDB.getSourceManager();
- BugReport *R = PDB.getBugReport();
- AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
+ const SourceManager &SM = PDB.getSourceManager();
+ const BugReport *R = PDB.getBugReport();
+ const AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
StackDiagVector CallStack;
InterestingExprs IE;
LocationContextMap LCM;
assert(!EndNotes->second.empty());
LastPiece = EndNotes->second[0];
} else {
- LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, ErrorNode, *R);
+ LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, ErrorNode,
+ *PDB.getBugReport());
}
PD->setEndOfPath(LastPiece);
}
for (const PathDiagnosticPieceRef &Note : VisitorNotes->second) {
llvm::FoldingSetNodeID ID;
Note->Profile(ID);
- auto P = DeduplicationSet.insert(ID);
- if (!P.second)
+ if (!DeduplicationSet.insert(ID).second)
continue;
if (AddPathEdges)
InterestingLocationContexts.insert(LC);
}
-bool BugReport::isInteresting(SVal V) {
+bool BugReport::isInteresting(SVal V) const {
return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
}
-bool BugReport::isInteresting(SymbolRef sym) {
+bool BugReport::isInteresting(SymbolRef sym) const {
if (!sym)
return false;
// We don't currently consider metadata symbols to be interesting
return InterestingSymbols.count(sym);
}
-bool BugReport::isInteresting(const MemRegion *R) {
+bool BugReport::isInteresting(const MemRegion *R) const {
if (!R)
return false;
R = R->getBaseRegion();
return false;
}
-bool BugReport::isInteresting(const LocationContext *LC) {
+bool BugReport::isInteresting(const LocationContext *LC) const {
if (!LC)
return false;
return InterestingLocationContexts.count(LC);
// Methods for BugReporter and subclasses.
//===----------------------------------------------------------------------===//
-ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
+const ExplodedGraph &GRBugReporter::getGraph() const { return Eng.getGraph(); }
ProgramStateManager&
GRBugReporter::getStateManager() { return Eng.getStateManager(); }
+ProgramStateManager&
+GRBugReporter::getStateManager() const { return Eng.getStateManager(); }
+
BugReporter::~BugReporter() {
FlushReports();
/// Insert all lines participating in the function signature \p Signature
/// into \p ExecutedLines.
static void populateExecutedLinesWithFunctionSignature(
- const Decl *Signature, SourceManager &SM,
+ const Decl *Signature, const SourceManager &SM,
FilesToLineNumsMap &ExecutedLines) {
SourceRange SignatureSourceRange;
const Stmt* Body = Signature->getBody();
}
static void populateExecutedLinesWithStmt(
- const Stmt *S, SourceManager &SM,
+ const Stmt *S, const SourceManager &SM,
FilesToLineNumsMap &ExecutedLines) {
SourceLocation Loc = S->getSourceRange().getBegin();
if (!Loc.isValid())
/// \return all executed lines including function signatures on the path
/// starting from \p N.
static std::unique_ptr<FilesToLineNumsMap>
-findExecutedLines(SourceManager &SM, const ExplodedNode *N) {
+findExecutedLines(const SourceManager &SM, const ExplodedNode *N) {
auto ExecutedLines = llvm::make_unique<FilesToLineNumsMap>();
while (N) {
// Examine the report and see if the last piece is in a header. Reset the
// report location to the last piece in the main source file.
- AnalyzerOptions &Opts = getAnalyzerOptions();
+ const AnalyzerOptions &Opts = getAnalyzerOptions();
for (auto const &P : *Out)
if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
P.second->resetDiagnosticLocationToMainFile();