[cfe-commits] r137012 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h lib/StaticAnalyzer/Core/BugReporter.cpp lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Ted Kremenek
kremenek at apple.com
Fri Aug 5 23:54:45 PDT 2011
Author: kremenek
Date: Sat Aug 6 01:54:45 2011
New Revision: 137012
URL: http://llvm.org/viewvc/llvm-project?rev=137012&view=rev
Log:
[analyzer] Start sketching out a new BugReporterVisitor that inspects branches and other expressions to generate interesting path events in diagnostics.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Sat Aug 6 01:54:45 2011
@@ -490,13 +490,15 @@
const Stmt *GetCalleeExpr(const ExplodedNode *N);
const Stmt *GetRetValExpr(const ExplodedNode *N);
+void registerConditionVisitor(BugReporterContext &BRC);
+
void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt,
const ExplodedNode* N);
void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
const ExplodedNode *N);
-void registerNilReceiverVisitor(BugReporterContext &BRC);
+void registerNilReceiverVisitor(BugReporterContext &BRC);
void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
const ExplodedNode *N);
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Sat Aug 6 01:54:45 2011
@@ -1619,6 +1619,7 @@
// Register node visitors.
R->registerInitialVisitors(PDB, N);
bugreporter::registerNilReceiverVisitor(PDB);
+ bugreporter::registerConditionVisitor(PDB);
switch (PDB.getGenerationScheme()) {
case PathDiagnosticClient::Extensive:
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=137012&r1=137011&r2=137012&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sat Aug 6 01:54:45 2011
@@ -468,3 +468,155 @@
WorkList.push_back(*I);
}
}
+
+//===----------------------------------------------------------------------===//
+// Visitor that tries to report interesting diagnostics from conditions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ConditionVisitor : public BugReporterVisitor {
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
+ const GRState *CurrentState,
+ const GRState *PrevState,
+ const CFGBlock *srcBlk,
+ const CFGBlock *dstBlk,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ bool tookTrue,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ const DeclRefExpr *DR,
+ const bool tookTrue,
+ BugReporterContext &BRC);
+
+};
+}
+
+PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC) {
+
+ const ProgramPoint &progPoint = N->getLocation();
+
+ // If an assumption was made on a branch, it should be caught
+ // here by looking at the state transition.
+ if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) {
+ const CFGBlock *srcBlk = BE->getSrc();
+
+ if (const Stmt *term = srcBlk->getTerminator()) {
+ const GRState *CurrentState = N->getState();
+ const GRState *PrevState = Prev->getState();
+ if (CurrentState != PrevState)
+ return VisitTerminator(term, CurrentState, PrevState,
+ srcBlk, BE->getDst(),
+ BRC);
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTerminator(const Stmt *Term,
+ const GRState *CurrentState,
+ const GRState *PrevState,
+ const CFGBlock *srcBlk,
+ const CFGBlock *dstBlk,
+ BugReporterContext &BRC) {
+
+ assert(CurrentState != PrevState);
+ const Expr *Cond = 0;
+
+ switch (Term->getStmtClass()) {
+ default:
+ return 0;
+ case Stmt::IfStmtClass:
+ Cond = cast<IfStmt>(Term)->getCond();
+ break;
+ case Stmt::ConditionalOperatorClass:
+ Cond = cast<ConditionalOperator>(Term)->getCond();
+ break;
+ }
+
+ assert(Cond);
+ assert(srcBlk->succ_size() == 2);
+ const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk;
+ return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()),
+ tookTrue, BRC);
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTrueTest(const Expr *Cond,
+ bool tookTrue,
+ BugReporterContext &BRC) {
+
+ const Expr *Ex = Cond;
+
+ while (true)
+ switch (Ex->getStmtClass()) {
+ default:
+ return 0;
+ case Stmt::DeclRefExprClass:
+ return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC);
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(Ex);
+ if (UO->getOpcode() == UO_LNot) {
+ tookTrue = !tookTrue;
+ Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext());
+ continue;
+ }
+ return 0;
+ }
+ }
+}
+
+PathDiagnosticPiece *
+ConditionVisitor::VisitTrueTest(const Expr *Cond,
+ const DeclRefExpr *DR,
+ const bool tookTrue,
+ BugReporterContext &BRC) {
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return 0;
+
+ llvm::SmallString<256> Buf;
+ llvm::raw_svector_ostream Out(Buf);
+
+ Out << "Assuming '";
+ VD->getDeclName().printName(Out);
+ Out << "' is ";
+
+ QualType VDTy = VD->getType();
+
+ if (VDTy->isPointerType())
+ Out << (tookTrue ? "non-null" : "null");
+ else if (VDTy->isObjCObjectPointerType())
+ Out << (tookTrue ? "non-nil" : "nil");
+ else if (VDTy->isScalarType())
+ Out << (tookTrue ? "not equal to 0" : "0");
+ else
+ return 0;
+
+ PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(Loc, Out.str());
+}
+
+void bugreporter::registerConditionVisitor(BugReporterContext &BRC) {
+ BRC.addVisitor(new ConditionVisitor());
+}
+
More information about the cfe-commits
mailing list