[cfe-commits] r89750 - in /cfe/trunk: include/clang/Analysis/PathSensitive/CheckerVisitor.def lib/Analysis/CMakeLists.txt lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/GRExprEngineInternalChecks.h lib/Analysis/UndefResultChecker.cpp
Zhongxing Xu
xuzhongxing at gmail.com
Tue Nov 24 00:24:26 PST 2009
Author: zhongxingxu
Date: Tue Nov 24 02:24:26 2009
New Revision: 89750
URL: http://llvm.org/viewvc/llvm-project?rev=89750&view=rev
Log:
Refactor undefined result checker. This is the last one.
Added:
cfe/trunk/lib/Analysis/UndefResultChecker.cpp
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def
cfe/trunk/lib/Analysis/CMakeLists.txt
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def?rev=89750&r1=89749&r2=89750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/CheckerVisitor.def Tue Nov 24 02:24:26 2009
@@ -24,6 +24,7 @@
#ifdef POSTVISIT
POSTVISIT(CallExpr)
+POSTVISIT(BinaryOperator)
#undef POSTVISIT
#endif
Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=89750&r1=89749&r2=89750&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Tue Nov 24 02:24:26 2009
@@ -56,6 +56,7 @@
Store.cpp
SymbolManager.cpp
UndefBranchChecker.cpp
+ UndefResultChecker.cpp
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
UninitializedValues.cpp
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=89750&r1=89749&r2=89750&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Nov 24 02:24:26 2009
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "GRExprEngineInternalChecks.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h"
#include "clang/Analysis/PathSensitive/Checker.h"
@@ -2576,6 +2577,8 @@
else
Visit(LHS, Pred, Tmp1);
+ ExplodedNodeSet Tmp3;
+
for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
SVal LeftV = (*I1)->getState()->getSVal(LHS);
ExplodedNodeSet Tmp2;
@@ -2610,7 +2613,7 @@
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
- EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV);
+ EvalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV);
continue;
}
@@ -2622,26 +2625,17 @@
if (Result.isUnknown()) {
if (OldSt != state) {
// Generate a new node if we have already created a new state.
- MakeNode(Dst, B, *I2, state);
+ MakeNode(Tmp3, B, *I2, state);
}
else
- Dst.Add(*I2);
+ Tmp3.Add(*I2);
continue;
}
state = state->BindExpr(B, Result);
- if (Result.isUndef()) {
- if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){
- UndefNode->markAsSink();
- UndefResults.insert(UndefNode);
- }
- continue;
- }
-
- // Otherwise, create a new node.
- MakeNode(Dst, B, *I2, state);
+ MakeNode(Tmp3, B, *I2, state);
continue;
}
@@ -2720,11 +2714,13 @@
llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy);
}
- EvalStore(Dst, B, LHS, *I3, state->BindExpr(B, Result),
+ EvalStore(Tmp3, B, LHS, *I3, state->BindExpr(B, Result),
location, LHSVal);
}
}
}
+
+ CheckerVisit(B, Dst, Tmp3, false);
}
//===----------------------------------------------------------------------===//
@@ -2980,3 +2976,27 @@
GraphPrintSourceManager = NULL;
#endif
}
+
+void GRExprEngine::RegisterInternalChecks() {
+ // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
+ // are different than what probably many checks will do since they don't
+ // create BugReports on-the-fly but instead wait until GRExprEngine finishes
+ // analyzing a function. Generation of BugReport objects is done via a call
+ // to 'FlushReports' from BugReporter.
+ // The following checks do not need to have their associated BugTypes
+ // explicitly registered with the BugReporter. If they issue any BugReports,
+ // their associated BugType will get registered with the BugReporter
+ // automatically. Note that the check itself is owned by the GRExprEngine
+ // object.
+ RegisterAttrNonNullChecker(*this);
+ RegisterCallAndMessageChecker(*this);
+ RegisterDereferenceChecker(*this);
+ RegisterVLASizeChecker(*this);
+ RegisterDivZeroChecker(*this);
+ RegisterReturnStackAddressChecker(*this);
+ RegisterReturnUndefChecker(*this);
+ RegisterUndefinedArraySubscriptChecker(*this);
+ RegisterUndefinedAssignmentChecker(*this);
+ RegisterUndefBranchChecker(*this);
+ RegisterUndefResultChecker(*this);
+}
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=89750&r1=89749&r2=89750&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Tue Nov 24 02:24:26 2009
@@ -25,146 +25,6 @@
using namespace clang::bugreporter;
//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-template <typename ITERATOR> inline
-ExplodedNode* GetNode(ITERATOR I) {
- return *I;
-}
-
-//===----------------------------------------------------------------------===//
-// Bug Descriptions.
-//===----------------------------------------------------------------------===//
-namespace clang {
-class BuiltinBugReport : public RangedBugReport {
-public:
- BuiltinBugReport(BugType& bt, const char* desc,
- ExplodedNode *n)
- : RangedBugReport(bt, desc, n) {}
-
- BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
- ExplodedNode *n)
- : RangedBugReport(bt, shortDesc, desc, n) {}
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N);
-};
-
-void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N) {
- static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
-}
-
-template <typename ITER>
-void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
- for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
- GetNode(I)));
-}
-
-class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
-public:
- UndefResult(GRExprEngine* eng)
- : BuiltinBug(eng,"Undefined or garbage result",
- "Result of operation is garbage or undefined") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
- E = Eng.undef_results_end(); I!=E; ++I) {
-
- ExplodedNode *N = *I;
- const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
- BuiltinBugReport *report = NULL;
-
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
- llvm::SmallString<256> sbuf;
- llvm::raw_svector_ostream OS(sbuf);
- const GRState *ST = N->getState();
- const Expr *Ex = NULL;
- bool isLeft = true;
-
- if (ST->getSVal(B->getLHS()).isUndef()) {
- Ex = B->getLHS()->IgnoreParenCasts();
- isLeft = true;
- }
- else if (ST->getSVal(B->getRHS()).isUndef()) {
- Ex = B->getRHS()->IgnoreParenCasts();
- isLeft = false;
- }
-
- if (Ex) {
- OS << "The " << (isLeft ? "left" : "right")
- << " operand of '"
- << BinaryOperator::getOpcodeStr(B->getOpcode())
- << "' is a garbage value";
- }
- else {
- // Neither operand was undefined, but the result is undefined.
- OS << "The result of the '"
- << BinaryOperator::getOpcodeStr(B->getOpcode())
- << "' expression is undefined";
- }
-
- // FIXME: Use StringRefs to pass string information.
- report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
- if (Ex) report->addRange(Ex->getSourceRange());
- }
- else {
- report = new BuiltinBugReport(*this,
- "Expression evaluates to an uninitialized"
- " or undefined value", N);
- }
-
- BR.EmitReport(report);
- }
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
-
- const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
- const Stmt *X = S;
-
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
- const GRState *ST = N->getState();
- if (ST->getSVal(B->getLHS()).isUndef())
- X = B->getLHS();
- else if (ST->getSVal(B->getRHS()).isUndef())
- X = B->getRHS();
- }
-
- registerTrackNullOrUndefValue(BRC, X, N);
- }
-};
-
-} // end clang namespace
-
-//===----------------------------------------------------------------------===//
// Check registration.
//===----------------------------------------------------------------------===//
-void GRExprEngine::RegisterInternalChecks() {
- // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
- // are different than what probably many checks will do since they don't
- // create BugReports on-the-fly but instead wait until GRExprEngine finishes
- // analyzing a function. Generation of BugReport objects is done via a call
- // to 'FlushReports' from BugReporter.
- BR.Register(new UndefResult(this));
-
- // The following checks do not need to have their associated BugTypes
- // explicitly registered with the BugReporter. If they issue any BugReports,
- // their associated BugType will get registered with the BugReporter
- // automatically. Note that the check itself is owned by the GRExprEngine
- // object.
- RegisterAttrNonNullChecker(*this);
- RegisterCallAndMessageChecker(*this);
- RegisterDereferenceChecker(*this);
- RegisterVLASizeChecker(*this);
- RegisterDivZeroChecker(*this);
- RegisterReturnStackAddressChecker(*this);
- RegisterReturnUndefChecker(*this);
- RegisterUndefinedArraySubscriptChecker(*this);
- RegisterUndefinedAssignmentChecker(*this);
- RegisterUndefBranchChecker(*this);
-}
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h?rev=89750&r1=89749&r2=89750&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Tue Nov 24 02:24:26 2009
@@ -35,6 +35,7 @@
void RegisterUndefinedArraySubscriptChecker(GRExprEngine &Eng);
void RegisterUndefinedAssignmentChecker(GRExprEngine &Eng);
void RegisterUndefBranchChecker(GRExprEngine &Eng);
+void RegisterUndefResultChecker(GRExprEngine &Eng);
} // end clang namespace
#endif
Added: cfe/trunk/lib/Analysis/UndefResultChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UndefResultChecker.cpp?rev=89750&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/UndefResultChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/UndefResultChecker.cpp Tue Nov 24 02:24:26 2009
@@ -0,0 +1,86 @@
+//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefResultChecker, a builtin check in GRExprEngine that
+// performs checks for undefined results of non-assignment binary operators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN UndefResultChecker
+ : public CheckerVisitor<UndefResultChecker> {
+
+ BugType *BT;
+
+public:
+ UndefResultChecker() : BT(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+} // end anonymous namespace
+
+void clang::RegisterUndefResultChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new UndefResultChecker());
+}
+
+void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ const GRState *state = C.getState();
+ if (state->getSVal(B).isUndef()) {
+ // Generate an error node.
+ ExplodedNode *N = C.GenerateSink();
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Result of operation is garbage or undefined");
+
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream OS(sbuf);
+ const Expr *Ex = NULL;
+ bool isLeft = true;
+
+ if (state->getSVal(B->getLHS()).isUndef()) {
+ Ex = B->getLHS()->IgnoreParenCasts();
+ isLeft = true;
+ }
+ else if (state->getSVal(B->getRHS()).isUndef()) {
+ Ex = B->getRHS()->IgnoreParenCasts();
+ isLeft = false;
+ }
+
+ if (Ex) {
+ OS << "The " << (isLeft ? "left" : "right")
+ << " operand of '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' is a garbage value";
+ }
+ else {
+ // Neither operand was undefined, but the result is undefined.
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined";
+ }
+ EnhancedBugReport *report = new EnhancedBugReport(*BT,
+ OS.str().str().c_str(), N);
+ report->addRange(Ex->getSourceRange());
+ if (Ex)
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ else
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
+ C.EmitReport(report);
+ }
+}
More information about the cfe-commits
mailing list