[cfe-commits] r42046 - in /cfe/trunk: Analysis/UnintializedValues.cpp include/clang/Analysis/LocalCheckers.h include/clang/Analysis/UninitializedValues.h include/clang/Basic/DiagnosticKinds.def
Ted Kremenek
kremenek at apple.com
Mon Sep 17 12:59:27 PDT 2007
Author: kremenek
Date: Mon Sep 17 14:59:27 2007
New Revision: 42046
URL: http://llvm.org/viewvc/llvm-project?rev=42046&view=rev
Log:
More progress on UnitializedValues checker. We now have preliminary support
for reporting errors and running the checker.
Modified:
cfe/trunk/Analysis/UnintializedValues.cpp
cfe/trunk/include/clang/Analysis/LocalCheckers.h
cfe/trunk/include/clang/Analysis/UninitializedValues.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/trunk/Analysis/UnintializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/UnintializedValues.cpp?rev=42046&r1=42045&r2=42046&view=diff
==============================================================================
--- cfe/trunk/Analysis/UnintializedValues.cpp (original)
+++ cfe/trunk/Analysis/UnintializedValues.cpp Mon Sep 17 14:59:27 2007
@@ -14,13 +14,18 @@
#include "clang/Analysis/UninitializedValues.h"
#include "clang/Analysis/CFGVarDeclVisitor.h"
#include "clang/Analysis/CFGStmtVisitor.h"
+#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/ASTContext.h"
#include "DataflowSolver.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
using namespace clang;
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// Dataflow initialization logic.
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
namespace {
@@ -52,9 +57,9 @@
V.ExprBV.resize(getAnalysisData().NumBlockExprs);
}
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// Transfer functions.
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
namespace {
@@ -75,15 +80,19 @@
bool VisitStmt(Stmt* S);
bool VisitCallExpr(CallExpr* C);
bool BlockStmt_VisitExpr(Expr* E);
+ bool VisitDeclStmt(DeclStmt* D);
static inline bool Initialized() { return true; }
- static inline bool Unintialized() { return false; }
+ static inline bool Uninitialized() { return false; }
};
bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+ if (AD.Observer)
+ AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);
+
return V.DeclBV[ AD.VMap[VD] ];
}
else
@@ -95,10 +104,38 @@
assert ( AD.EMap.find(B) != AD.EMap.end() && "Unknown block-level expr.");
return V.ExprBV[ AD.EMap[B] ];
}
-
+
+ if (B->isAssignmentOp()) {
+ // Get the Decl for the LHS, if any
+ for (Stmt* S = B->getLHS() ;; ) {
+ if (ParenExpr* P = dyn_cast<ParenExpr>(S))
+ S = P->getSubExpr();
+ else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+ return V.DeclBV[ AD.VMap[VD] ] = Visit(B->getRHS());
+ }
+
+ break;
+ }
+ }
+
return VisitStmt(B);
}
+bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
+ bool x = Initialized();
+
+ for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ if (Stmt* I = VD->getInit()) {
+ assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+ x = V.DeclBV[ AD.VMap[VD] ] = Visit(I);
+ }
+
+ return x;
+}
+
bool TransferFuncs::VisitCallExpr(CallExpr* C) {
VisitStmt(C);
return Initialized();
@@ -140,8 +177,8 @@
// evaluating some subexpressions may result in propogating "Uninitialized"
// or "Initialized" to variables referenced in the other subexpressions.
for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
- if (Visit(*I) == Unintialized())
- x = Unintialized();
+ if (Visit(*I) == Uninitialized())
+ x = Uninitialized();
return x;
}
@@ -153,7 +190,7 @@
} // end anonymous namespace
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// Merge operator.
//
// In our transfer functions we take the approach that any
@@ -171,7 +208,7 @@
// in a predecessor we treat it as uninitalized at the confluence point.
// The reason we do this is because dataflow values for tracked Exprs are
// not as control-dependent as dataflow values for tracked Decls.
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
namespace {
struct Merge {
@@ -190,24 +227,50 @@
};
} // end anonymous namespace
-//===--------------------------------------------------------------------===//
-// External interface (driver logic).
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Unitialized values checker. Scan an AST and flag variable uses
+//===----------------------------------------------------------------------===//
-void UninitializedValues::CheckUninitializedValues(const CFG& cfg) {
+UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}
- typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
+namespace {
- UninitializedValues U;
+class UninitializedValuesChecker : public UninitializedValues::ObserverTy {
+ ASTContext &Ctx;
+ Diagnostic &Diags;
+ llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned;
- { // Compute the unitialized values information.
- Solver S(U);
- S.runOnCFG(cfg);
+public:
+ UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
+ : Ctx(ctx), Diags(diags) {}
+
+ virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
+ UninitializedValues::AnalysisDataTy& AD,
+ DeclRefExpr* DR, VarDecl* VD) {
+
+ assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+ if (V.DeclBV[ AD.VMap[VD] ] == TransferFuncs::Uninitialized())
+ if (AlreadyWarned.insert(VD))
+ Diags.Report(DR->getSourceRange().Begin(), diag::warn_uninit_val);
}
+};
+
+} // end anonymous namespace
+
-// WarnObserver O;
+void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
+
+ typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
+
+ // Compute the unitialized values information.
+ UninitializedValues U;
Solver S(U);
-
- for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+ S.runOnCFG(cfg);
+
+ // Scan for DeclRefExprs that use uninitialized values.
+ UninitializedValuesChecker Observer(Ctx,Diags);
+ U.getAnalysisData().Observer = &Observer;
+
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
S.runOnBlock(&*I);
}
Modified: cfe/trunk/include/clang/Analysis/LocalCheckers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/LocalCheckers.h?rev=42046&r1=42045&r2=42046&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/LocalCheckers.h (original)
+++ cfe/trunk/include/clang/Analysis/LocalCheckers.h Mon Sep 17 14:59:27 2007
@@ -25,6 +25,10 @@
ASTContext &Ctx, Diagnostic &Diags);
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);
+
+void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags);
+
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Analysis/UninitializedValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/UninitializedValues.h?rev=42046&r1=42045&r2=42046&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/UninitializedValues.h Mon Sep 17 14:59:27 2007
@@ -22,12 +22,18 @@
class VarDecl;
class Expr;
+ class DeclRefExpr;
/// UninitializedValues_ValueTypes - Utility class to wrap type declarations
/// for dataflow values and dataflow analysis state for the
/// Unitialized Values analysis.
class UninitializedValues_ValueTypes {
public:
+
+ //===--------------------------------------------------------------------===//
+ // ValTy - Dataflow value.
+ //===--------------------------------------------------------------------===//
+
struct ValTy {
llvm::BitVector DeclBV;
llvm::BitVector ExprBV;
@@ -48,36 +54,45 @@
}
};
+ //===--------------------------------------------------------------------===//
+ // AnalysisDataTy - Whole-function meta data used by the transfer function
+ // logic.
+ //===--------------------------------------------------------------------===//
+
+ struct ObserverTy;
+
struct AnalysisDataTy {
llvm::DenseMap<const VarDecl*, unsigned > VMap;
llvm::DenseMap<const Expr*, unsigned > EMap;
unsigned NumDecls;
unsigned NumBlockExprs;
+ ObserverTy* Observer;
- AnalysisDataTy() : NumDecls(0), NumBlockExprs(0) {}
+ AnalysisDataTy() : NumDecls(0), NumBlockExprs(0), Observer(NULL) {}
};
+
+ //===--------------------------------------------------------------------===//
+ // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
+ // value.
+ //===--------------------------------------------------------------------===//
+
+ struct ObserverTy {
+ virtual ~ObserverTy();
+ virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD,
+ DeclRefExpr* DR, VarDecl* VD) = 0;
+ };
};
/// UninitializedValues - Objects of this class encapsulate dataflow analysis
/// information regarding what variable declarations in a function are
/// potentially unintialized.
class UninitializedValues :
- public DataflowValues<UninitializedValues_ValueTypes> {
-
- //===--------------------------------------------------------------------===//
- // Public interface.
- //===--------------------------------------------------------------------===//
-
- static void CheckUninitializedValues(const CFG& cfg);
+ public DataflowValues<UninitializedValues_ValueTypes> {
+public:
+ typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy;
- //===--------------------------------------------------------------------===//
- // Internal logic.
- //===--------------------------------------------------------------------===//
-
-private:
UninitializedValues() {}
-public:
/// IntializeValues - Create initial dataflow values and meta data for
/// a given CFG. This is intended to be called by the dataflow solver.
void InitializeValues(const CFG& cfg);
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42046&r1=42045&r2=42046&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Sep 17 14:59:27 2007
@@ -753,6 +753,9 @@
// CHECK: stores to variables that are no longer live (dead stores)
DIAG(warn_dead_store, WARNING, "value stored to variable is never used")
+// CHECK: use of uninitialized values
+DIAG(warn_uninit_val, WARNING, "use of potentially uninitialized variable")
+
// CFString checking
DIAG(err_cfstring_literal_not_string_constant, ERROR,
"CFString literal is not a string constant")
More information about the cfe-commits
mailing list