aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp109
1 files changed, 78 insertions, 31 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index f1340f4811..e66b619bac 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -85,38 +85,58 @@ static inline Stmt* GetCurrentOrNextStmt(const ExplodedNode<GRState>* N) {
// Diagnostics for 'execution continues on line XXX'.
//===----------------------------------------------------------------------===//
-static FullSourceLoc ExecutionContinues(SourceManager& SMgr,
- const ExplodedNode<GRState>* N,
- const Decl& D,
- bool* OutHasStmt = 0) {
+namespace {
+class VISIBILITY_HIDDEN PathDiagnosticBuilder {
+ SourceManager &SMgr;
+ const Decl& CodeDecl;
+ PathDiagnosticClient *PDC;
+public:
+ PathDiagnosticBuilder(SourceManager &smgr, const Decl& codedecl,
+ PathDiagnosticClient *pdc)
+ : SMgr(smgr), CodeDecl(codedecl), PDC(pdc) {}
+
+ FullSourceLoc ExecutionContinues(const ExplodedNode<GRState>* N,
+ bool* OutHasStmt = 0);
+
+ FullSourceLoc ExecutionContinues(llvm::raw_string_ostream& os,
+ const ExplodedNode<GRState>* N);
+
+ bool supportsLogicalOpControlFlow() const {
+ return PDC ? PDC->supportsLogicalOpControlFlow() : true;
+ }
+};
+} // end anonymous namespace
+
+FullSourceLoc
+PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode<GRState>* N,
+ bool* OutHasStmt) {
if (Stmt *S = GetNextStmt(N)) {
if (OutHasStmt) *OutHasStmt = true;
return FullSourceLoc(S->getLocStart(), SMgr);
}
else {
if (OutHasStmt) *OutHasStmt = false;
- return FullSourceLoc(D.getBody()->getRBracLoc(), SMgr);
+ return FullSourceLoc(CodeDecl.getBody()->getRBracLoc(), SMgr);
}
}
-static FullSourceLoc ExecutionContinues(llvm::raw_string_ostream& os,
- SourceManager& SMgr,
- const ExplodedNode<GRState>* N,
- const Decl& D) {
-
+FullSourceLoc
+PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os,
+ const ExplodedNode<GRState>* N) {
+
// Slow, but probably doesn't matter.
if (os.str().empty())
os << ' ';
bool hasStmt;
- FullSourceLoc Loc = ExecutionContinues(SMgr, N, D, &hasStmt);
+ FullSourceLoc Loc = ExecutionContinues(N, &hasStmt);
if (hasStmt)
os << "Execution continues on line "
- << SMgr.getInstantiationLineNumber(Loc) << '.';
+ << SMgr.getInstantiationLineNumber(Loc) << '.';
else
os << "Execution jumps to the end of the "
- << (isa<ObjCMethodDecl>(D) ? "method" : "function") << '.';
+ << (isa<ObjCMethodDecl>(CodeDecl) ? "method" : "function") << '.';
return Loc;
}
@@ -719,6 +739,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
ASTContext& Ctx = getContext();
SourceManager& SMgr = Ctx.getSourceManager();
NodeMapClosure NMC(BackMap.get());
+ PathDiagnosticBuilder PDB(SMgr, getStateManager().getCodeDecl(),
+ getPathDiagnosticClient());
while (NextNode) {
N = NextNode;
@@ -819,8 +841,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
}
else {
os << "'Default' branch taken. ";
- End = ExecutionContinues(os, SMgr, N,
- getStateManager().getCodeDecl());
+ End = PDB.ExecutionContinues(os, N);
}
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
@@ -832,13 +853,13 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
case Stmt::ContinueStmtClass: {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
- FullSourceLoc End =
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
+ FullSourceLoc End = PDB.ExecutionContinues(os, N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
break;
}
+ // Determine control-flow for ternary '?'.
case Stmt::ConditionalOperatorClass: {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -849,9 +870,42 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
else
os << "true";
- FullSourceLoc End =
- ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+ FullSourceLoc End = PDB.ExecutionContinues(N);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ break;
+ }
+
+ // Determine control-flow for short-circuited '&&' and '||'.
+ case Stmt::BinaryOperatorClass: {
+ if (!PDB.supportsLogicalOpControlFlow())
+ break;
+ BinaryOperator *B = cast<BinaryOperator>(T);
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Left side of '";
+
+ if (B->getOpcode() == BinaryOperator::LAnd) {
+ os << "&&";
+ }
+ else {
+ assert(B->getOpcode() == BinaryOperator::LOr);
+ os << "||";
+ }
+
+ os << "' is ";
+ if (*(Src->succ_begin()+1) == Dst)
+ os << (B->getOpcode() == BinaryOperator::LAnd
+ ? "false" : "true");
+ else
+ os << (B->getOpcode() == BinaryOperator::LAnd
+ ? "true" : "false");
+
+ PathDiagnosticLocation Start(B->getLHS(), SMgr);
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
break;
@@ -863,14 +917,12 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
llvm::raw_string_ostream os(sbuf);
os << "Loop condition is true. ";
- FullSourceLoc End =
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
+ FullSourceLoc End = PDB.ExecutionContinues(os, N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
}
else {
- FullSourceLoc End =
- ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+ FullSourceLoc End = PDB.ExecutionContinues(N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
"Loop condition is false. Exiting loop"));
}
@@ -885,15 +937,12 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
llvm::raw_string_ostream os(sbuf);
os << "Loop condition is false. ";
- FullSourceLoc End =
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
-
+ FullSourceLoc End = PDB.ExecutionContinues(os, N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
}
else {
- FullSourceLoc End =
- ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+ FullSourceLoc End = PDB.ExecutionContinues(N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
"Loop condition is true. Entering loop body"));
@@ -903,9 +952,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
}
case Stmt::IfStmtClass: {
- FullSourceLoc End =
- ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
-
+ FullSourceLoc End = PDB.ExecutionContinues(N);
if (*(Src->succ_begin()+1) == Dst)
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
"Taking false branch"));