[cfe-commits] r66818 - in /cfe/trunk: include/clang/Analysis/PathDiagnostic.h lib/Analysis/BugReporter.cpp lib/Analysis/PathDiagnostic.cpp lib/Frontend/PlistDiagnostics.cpp
Ted Kremenek
kremenek at apple.com
Thu Mar 12 11:41:53 PDT 2009
Author: kremenek
Date: Thu Mar 12 13:41:53 2009
New Revision: 66818
URL: http://llvm.org/viewvc/llvm-project?rev=66818&view=rev
Log:
PathDiagnostics:
- PathDiagnosticControlFlowPiece now consists of a "start" and "end" location
to indicating the branch location and where the branch goes.
BugReporter:
- Updated BugReporter to construct PathDiagnosticControlFlowPiece objects with
"end" locations.
PlistDiagnostics:
- Plists now contain the bug "type" (not just bug "category")
- Plists now encode control-flow pieces differently than events; now the
"start" and "end" locations are recorded
Modified:
cfe/trunk/include/clang/Analysis/PathDiagnostic.h
cfe/trunk/lib/Analysis/BugReporter.cpp
cfe/trunk/lib/Analysis/PathDiagnostic.cpp
cfe/trunk/lib/Frontend/PlistDiagnostics.cpp
Modified: cfe/trunk/include/clang/Analysis/PathDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathDiagnostic.h?rev=66818&r1=66817&r2=66818&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathDiagnostic.h (original)
+++ cfe/trunk/include/clang/Analysis/PathDiagnostic.h Thu Mar 12 13:41:53 2009
@@ -186,7 +186,6 @@
const Kind kind;
const DisplayHint Hint;
std::vector<SourceRange> ranges;
- std::vector<PathDiagnosticPiece*> SubPieces;
// Do not implement:
PathDiagnosticPiece();
@@ -195,10 +194,12 @@
protected:
PathDiagnosticPiece(FullSourceLoc pos, const std::string& s,
- Kind k = Event, DisplayHint hint = Below);
+ Kind k, DisplayHint hint = Below);
PathDiagnosticPiece(FullSourceLoc pos, const char* s,
- Kind k = Event, DisplayHint hint = Below);
+ Kind k, DisplayHint hint = Below);
+
+ PathDiagnosticPiece(FullSourceLoc pos, Kind k, DisplayHint hint = Below);
public:
virtual ~PathDiagnosticPiece();
@@ -269,15 +270,24 @@
};
class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
+ const SourceLocation EndPos;
public:
- PathDiagnosticControlFlowPiece(FullSourceLoc pos, const std::string& s)
- : PathDiagnosticPiece(pos, s, ControlFlow) {}
+ PathDiagnosticControlFlowPiece(FullSourceLoc startPos, SourceLocation endPos,
+ const std::string& s)
+ : PathDiagnosticPiece(startPos, s, ControlFlow), EndPos(endPos) {}
+
+ PathDiagnosticControlFlowPiece(FullSourceLoc startPos, SourceLocation endPos,
+ const char* s)
+ : PathDiagnosticPiece(startPos, s, ControlFlow), EndPos(endPos) {}
- PathDiagnosticControlFlowPiece(FullSourceLoc pos, const char* s)
- : PathDiagnosticPiece(pos, s, ControlFlow) {}
+ PathDiagnosticControlFlowPiece(FullSourceLoc startPos, SourceLocation endPos)
+ : PathDiagnosticPiece(startPos, ControlFlow), EndPos(endPos) {}
~PathDiagnosticControlFlowPiece();
+ SourceLocation getStartLocation() const { return getLocation(); }
+ SourceLocation getEndLocation() const { return EndPos; }
+
static inline bool classof(const PathDiagnosticPiece* P) {
return P->getKind() == ControlFlow;
}
Modified: cfe/trunk/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BugReporter.cpp?rev=66818&r1=66817&r2=66818&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Thu Mar 12 13:41:53 2009
@@ -84,21 +84,40 @@
// Diagnostics for 'execution continues on line XXX'.
//===----------------------------------------------------------------------===//
-static inline void ExecutionContinues(llvm::raw_string_ostream& os,
- SourceManager& SMgr,
- const ExplodedNode<GRState>* N,
- const Decl& D) {
+static SourceLocation ExecutionContinues(SourceManager& SMgr,
+ const ExplodedNode<GRState>* N,
+ const Decl& D,
+ bool* OutHasStmt = 0) {
+ if (Stmt *S = GetNextStmt(N)) {
+ if (OutHasStmt) *OutHasStmt = true;
+ return S->getLocStart();
+ }
+ else {
+ if (OutHasStmt) *OutHasStmt = false;
+ return D.getBody()->getRBracLoc();
+ }
+}
+
+static SourceLocation ExecutionContinues(llvm::raw_string_ostream& os,
+ SourceManager& SMgr,
+ const ExplodedNode<GRState>* N,
+ const Decl& D) {
// Slow, but probably doesn't matter.
if (os.str().empty())
os << ' ';
- if (Stmt *S = GetNextStmt(N))
+ bool hasStmt;
+ SourceLocation Loc = ExecutionContinues(SMgr, N, D, &hasStmt);
+
+ if (hasStmt)
os << "Execution continues on line "
- << SMgr.getInstantiationLineNumber(S->getLocStart()) << '.';
+ << SMgr.getInstantiationLineNumber(Loc) << '.';
else
os << "Execution jumps to the end of the "
<< (isa<ObjCMethodDecl>(D) ? "method" : "function") << '.';
+
+ return Loc;
}
//===----------------------------------------------------------------------===//
@@ -706,36 +725,33 @@
ProgramPoint P = N->getLocation();
if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
-
CFGBlock* Src = BE->getSrc();
CFGBlock* Dst = BE->getDst();
-
Stmt* T = Src->getTerminator();
if (!T)
continue;
- FullSourceLoc L(T->getLocStart(), SMgr);
+ FullSourceLoc Start(T->getLocStart(), SMgr);
switch (T->getStmtClass()) {
default:
break;
case Stmt::GotoStmtClass:
- case Stmt::IndirectGotoStmtClass: {
-
+ case Stmt::IndirectGotoStmtClass: {
Stmt* S = GetNextStmt(N);
if (!S)
continue;
std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
-
- os << "Control jumps to line "
- << SMgr.getInstantiationLineNumber(S->getLocStart()) << ".\n";
+ llvm::raw_string_ostream os(sbuf);
+ SourceLocation End = S->getLocStart();
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ os << "Control jumps to line " << SMgr.getInstantiationLineNumber(End);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
break;
}
@@ -743,67 +759,70 @@
// Figure out what case arm we took.
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
-
- if (Stmt* S = Dst->getLabel())
+ SourceLocation End;
+
+ if (Stmt* S = Dst->getLabel()) {
+ End = S->getLocStart();
+
switch (S->getStmtClass()) {
- default:
- os << "No cases match in the switch statement. "
- "Control jumps to line "
- << SMgr.getInstantiationLineNumber(S->getLocStart()) << ".\n";
- break;
- case Stmt::DefaultStmtClass:
- os << "Control jumps to the 'default' case at line "
- << SMgr.getInstantiationLineNumber(S->getLocStart()) << ".\n";
- break;
-
- case Stmt::CaseStmtClass: {
- os << "Control jumps to 'case ";
-
- CaseStmt* Case = cast<CaseStmt>(S);
- Expr* LHS = Case->getLHS()->IgnoreParenCasts();
-
- // Determine if it is an enum.
-
- bool GetRawInt = true;
-
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
-
- // FIXME: Maybe this should be an assertion. Are there cases
- // were it is not an EnumConstantDecl?
- EnumConstantDecl* D = dyn_cast<EnumConstantDecl>(DR->getDecl());
- if (D) {
- GetRawInt = false;
- os << D->getNameAsString();
+ default:
+ os << "No cases match in the switch statement. "
+ "Control jumps to line "
+ << SMgr.getInstantiationLineNumber(End);
+ break;
+ case Stmt::DefaultStmtClass:
+ os << "Control jumps to the 'default' case at line "
+ << SMgr.getInstantiationLineNumber(End);
+ break;
+
+ case Stmt::CaseStmtClass: {
+ os << "Control jumps to 'case ";
+ CaseStmt* Case = cast<CaseStmt>(S);
+ Expr* LHS = Case->getLHS()->IgnoreParenCasts();
+
+ // Determine if it is an enum.
+ bool GetRawInt = true;
+
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
+ // FIXME: Maybe this should be an assertion. Are there cases
+ // were it is not an EnumConstantDecl?
+ EnumConstantDecl* D =
+ dyn_cast<EnumConstantDecl>(DR->getDecl());
+
+ if (D) {
+ GetRawInt = false;
+ os << D->getNameAsString();
+ }
}
- }
- if (GetRawInt) {
-
- // Not an enum.
- Expr* CondE = cast<SwitchStmt>(T)->getCond();
- unsigned bits = Ctx.getTypeSize(CondE->getType());
- llvm::APSInt V(bits, false);
+ if (GetRawInt) {
- if (!LHS->isIntegerConstantExpr(V, Ctx, 0, true)) {
- assert (false && "Case condition must be constant.");
- continue;
- }
+ // Not an enum.
+ Expr* CondE = cast<SwitchStmt>(T)->getCond();
+ unsigned bits = Ctx.getTypeSize(CondE->getType());
+ llvm::APSInt V(bits, false);
+
+ if (!LHS->isIntegerConstantExpr(V, Ctx, 0, true)) {
+ assert (false && "Case condition must be constant.");
+ continue;
+ }
+
+ os << V;
+ }
- os << V;
- }
-
- os << ":' at line "
- << SMgr.getInstantiationLineNumber(S->getLocStart()) << ".\n";
-
- break;
+ os << ":' at line " << SMgr.getInstantiationLineNumber(End);
+ break;
+ }
}
}
else {
os << "'Default' branch taken. ";
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
+ End = ExecutionContinues(os, SMgr, N,
+ getStateManager().getCodeDecl());
}
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
break;
}
@@ -811,8 +830,10 @@
case Stmt::ContinueStmtClass: {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ SourceLocation End = ExecutionContinues(os, SMgr, N,
+ getStateManager().getCodeDecl());
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
break;
}
@@ -822,58 +843,73 @@
os << "'?' condition evaluates to ";
if (*(Src->succ_begin()+1) == Dst)
- os << "false.";
+ os << "false";
else
- os << "true.";
+ os << "true";
+
+ SourceLocation End =
+ ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
break;
}
- case Stmt::DoStmtClass: {
-
+ case Stmt::DoStmtClass: {
if (*(Src->succ_begin()) == Dst) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
os << "Loop condition is true. ";
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
-
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ SourceLocation End =
+ ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ SourceLocation End =
+ ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Loop condition is false. Exiting loop"));
}
- else
- PD.push_front(new PathDiagnosticControlFlowPiece(L,
- "Loop condition is false. Exiting loop."));
break;
}
case Stmt::WhileStmtClass:
- case Stmt::ForStmtClass: {
-
+ case Stmt::ForStmtClass: {
if (*(Src->succ_begin()+1) == Dst) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
os << "Loop condition is false. ";
- ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
+ SourceLocation End =
+ ExecutionContinues(os, SMgr, N, getStateManager().getCodeDecl());
- PD.push_front(new PathDiagnosticControlFlowPiece(L, os.str()));
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ SourceLocation End =
+ ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Loop condition is true. Entering loop body"));
}
- else
- PD.push_front(new PathDiagnosticControlFlowPiece(L,
- "Loop condition is true. Entering loop body."));
break;
}
- case Stmt::IfStmtClass: {
+ case Stmt::IfStmtClass: {
+ SourceLocation End =
+ ExecutionContinues(SMgr, N, getStateManager().getCodeDecl());
+
if (*(Src->succ_begin()+1) == Dst)
- PD.push_front(new PathDiagnosticControlFlowPiece(L,
- "Taking false branch."));
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Taking false branch"));
else
- PD.push_front(new PathDiagnosticControlFlowPiece(L,
- "Taking true branch."));
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Taking true branch"));
break;
}
Modified: cfe/trunk/lib/Analysis/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PathDiagnostic.cpp?rev=66818&r1=66817&r2=66818&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/Analysis/PathDiagnostic.cpp Thu Mar 12 13:41:53 2009
@@ -65,6 +65,13 @@
"PathDiagnosticPiece's must have a valid location.");
}
+PathDiagnosticPiece::PathDiagnosticPiece(FullSourceLoc pos, Kind k,
+ DisplayHint hint)
+ : Pos(pos), kind(k), Hint(hint) {
+ assert(Pos.isValid() &&
+ "PathDiagnosticPiece's must have a valid location.");
+}
+
PathDiagnosticPiece::~PathDiagnosticPiece() {}
PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
Modified: cfe/trunk/lib/Frontend/PlistDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PlistDiagnostics.cpp?rev=66818&r1=66817&r2=66818&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PlistDiagnostics.cpp (original)
+++ cfe/trunk/lib/Frontend/PlistDiagnostics.cpp Thu Mar 12 13:41:53 2009
@@ -17,10 +17,12 @@
#include "clang/Basic/FileManager.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Casting.h"
#include "llvm/System/Path.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
+using llvm::cast;
typedef llvm::DenseMap<FileID, unsigned> FIDMap;
@@ -67,8 +69,7 @@
}
static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
- for (unsigned i = 0; i < indent; ++i)
- o << ' ';
+ for (unsigned i = 0; i < indent; ++i) o << ' ';
return o;
}
@@ -95,22 +96,49 @@
Indent(o, indent) << "</array>\n";
}
-static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
- const FIDMap& FM, SourceManager* SM) {
+static void ReportControlFlow(llvm::raw_ostream& o,
+ const PathDiagnosticControlFlowPiece& P,
+ const FIDMap& FM, SourceManager *SM,
+ unsigned indent) {
- unsigned indent = 4;
Indent(o, indent) << "<dict>\n";
++indent;
+ Indent(o, indent) << "<key>kind</key><string>control</string>\n";
+
+ // Output the start and end locations.
+ Indent(o, indent) << "<key>start</key>\n";
+ EmitLocation(o, SM, P.getStartLocation(), FM, indent);
+ Indent(o, indent) << "<key>end</key>\n";
+ EmitLocation(o, SM, P.getEndLocation(), FM, indent);
+
+ // Output any helper text.
+ const std::string& s = P.getString();
+ if (!s.empty()) {
+ Indent(o, indent) << "<key>alternate</key><string>" << s << "</string>\n";
+ }
+
+ --indent;
+ Indent(o, indent) << "</dict>\n";
+}
+
+static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+ const FIDMap& FM, SourceManager* SM, unsigned indent) {
+
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+
+ Indent(o, indent) << "<key>kind</key><string>event</string>\n";
+
// Output the location.
FullSourceLoc L = P.getLocation();
-
+
Indent(o, indent) << "<key>location</key>\n";
EmitLocation(o, SM, L, FM, indent);
-
+
// Output the ranges (if any).
PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
- RE = P.ranges_end();
+ RE = P.ranges_end();
if (RI != RE) {
Indent(o, indent) << "<key>ranges</key>\n";
@@ -122,33 +150,53 @@
}
// Output the text.
+ assert(!P.getString().empty());
Indent(o, indent) << "<key>message</key>\n";
Indent(o, indent) << "<string>" << P.getString() << "</string>\n";
+
+ // Finish up.
+ --indent;
+ Indent(o, indent); o << "</dict>\n";
+}
+
+static void ReportMacro(llvm::raw_ostream& o,
+ const PathDiagnosticMacroPiece& P,
+ const FIDMap& FM, SourceManager *SM,
+ unsigned indent) {
- // Output the hint.
-#if 0
- // Disable the display hint until we clear up its meaning.
- Indent(o, indent) << "<key>displayhint</key>\n";
- Indent(o, indent) << "<string>"
- << (P.getDisplayHint() == PathDiagnosticPiece::Above
- ? "above" : "below")
- << "</string>\n";
-#endif
- // Output the PathDiagnosticPiece::Kind.
- Indent(o, indent) << "<key>kind</key>\n";
- Indent(o, indent) << "<string>";
+ for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
+ I!=E; ++I) {
+
+ switch ((*I)->getKind()) {
+ default:
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, indent);
+ break;
+ }
+ }
+}
+
+static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+ const FIDMap& FM, SourceManager* SM) {
+
+ unsigned indent = 4;
switch (P.getKind()) {
- case PathDiagnosticPiece::Event: o << "Event"; break;
- case PathDiagnosticPiece::ControlFlow: o << "ControlFlow"; break;
- case PathDiagnosticPiece::Macro: o << "Macro"; break;
+ case PathDiagnosticPiece::ControlFlow:
+ ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
+ indent);
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, indent);
+ break;
}
- o << "</string>\n";
-
-
- // Finish up.
- --indent;
- Indent(o, indent); o << "</dict>\n";
}
void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
@@ -238,11 +286,14 @@
o << " </array>\n";
// Output the bug type and bug category.
- o << " <key>description</key>\n <string>" << D->getDescription()
+ o << " <key>description</key><string>" << D->getDescription()
<< "</string>\n"
- << " <key>category</key>\n <string>" << D->getCategory()
+ << " <key>category</key><string>" << D->getCategory()
<< "</string>\n"
- << " </dict>\n";
+ << " <key>type</key><string>" << D->getBugType()
+ << "</string>\n"
+ << " </dict>\n";
+
}
o << " </array>\n";
More information about the cfe-commits
mailing list