[cfe-commits] r42041 - in /cfe/trunk: Analysis/UnintializedValues.cpp include/clang/Analysis/UninitializedValues.h
Ted Kremenek
kremenek at apple.com
Mon Sep 17 11:31:23 PDT 2007
Author: kremenek
Date: Mon Sep 17 13:31:23 2007
New Revision: 42041
URL: http://llvm.org/viewvc/llvm-project?rev=42041&view=rev
Log:
Split tracking of unitialized values for Decls and CFGBlock-level expressions.
Modified:
cfe/trunk/Analysis/UnintializedValues.cpp
cfe/trunk/include/clang/Analysis/UninitializedValues.h
Modified: cfe/trunk/Analysis/UnintializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/UnintializedValues.cpp?rev=42041&r1=42040&r2=42041&view=diff
==============================================================================
--- cfe/trunk/Analysis/UnintializedValues.cpp (original)
+++ cfe/trunk/Analysis/UnintializedValues.cpp Mon Sep 17 13:31:23 2007
@@ -33,12 +33,12 @@
void VisitVarDecl(VarDecl* D) {
if (AD.VMap.find(D) == AD.VMap.end())
- AD.VMap[D] = AD.Counter++;
+ AD.VMap[D] = AD.NumDecls++;
}
void BlockStmt_VisitExpr(Expr* E) {
if (AD.EMap.find(E) == AD.EMap.end())
- AD.EMap[E] = AD.Counter++;
+ AD.EMap[E] = AD.NumBlockExprs++;
}
};
@@ -47,7 +47,9 @@
void UninitializedValues::InitializeValues(const CFG& cfg) {
RegisterDeclsAndExprs R(cfg,this->getAnalysisData());
R.VisitAllDecls();
- getBlockDataMap()[ &cfg.getEntry() ].resize( getAnalysisData().Counter );
+ UninitializedValues::ValTy& V = getBlockDataMap()[&cfg.getEntry()];
+ V.DeclBV.resize(getAnalysisData().NumDecls);
+ V.ExprBV.resize(getAnalysisData().NumBlockExprs);
}
//===--------------------------------------------------------------------===//
@@ -55,44 +57,140 @@
//===--------------------------------------------------------------------===//
namespace {
+
class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
UninitializedValues::ValTy V;
UninitializedValues::AnalysisDataTy& AD;
public:
TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
- V.resize(AD.Counter);
+ V.DeclBV.resize(AD.NumDecls);
+ V.ExprBV.resize(AD.NumBlockExprs);
}
UninitializedValues::ValTy& getVal() { return V; }
-// bool VisitDeclRefExpr(DeclRefExpr* DR);
-// bool VisitBinaryOperator(BinaryOperator* B);
-// bool VisitUnaryOperator(UnaryOperator* U);
+ bool VisitDeclRefExpr(DeclRefExpr* DR);
+ bool VisitBinaryOperator(BinaryOperator* B);
+ bool VisitUnaryOperator(UnaryOperator* U);
+ bool VisitStmt(Stmt* S);
+ bool VisitCallExpr(CallExpr* C);
+ bool BlockStmt_VisitExpr(Expr* E);
+
+ static inline bool Initialized() { return true; }
+ static inline bool Unintialized() { 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.");
+ return V.DeclBV[ AD.VMap[VD] ];
+ }
+ else
+ return Initialized();
+}
+
+bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
+ if (CFG::hasImplicitControlFlow(B)) {
+ assert ( AD.EMap.find(B) != AD.EMap.end() && "Unknown block-level expr.");
+ return V.ExprBV[ AD.EMap[B] ];
+ }
+
+ return VisitStmt(B);
+}
+
+bool TransferFuncs::VisitCallExpr(CallExpr* C) {
+ VisitStmt(C);
+ return Initialized();
+}
+
+bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
+ switch (U->getOpcode()) {
+ case UnaryOperator::AddrOf: {
+ // Blast through parentheses and find the decl (if any). Treat it
+ // as initialized from this point forward.
+ for (Stmt* S = U->getSubExpr() ;; )
+ 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.");
+ V.DeclBV[ AD.VMap[VD] ] = Initialized();
+ }
+ break;
+ }
+ else {
+ // Evaluate the transfer function for subexpressions, even
+ // if we cannot reason more deeply about the &-expression.
+ return Visit(U->getSubExpr());
+ }
+
+ return Initialized();
+ }
+
+ default:
+ return Visit(U->getSubExpr());
+ }
+}
+
+bool TransferFuncs::VisitStmt(Stmt* S) {
+ bool x = Initialized();
+
+ // We don't stop at the first subexpression that is Uninitialized because
+ // 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();
+
+ return x;
+}
+
+bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
+ assert ( AD.EMap.find(E) != AD.EMap.end() );
+ return V.ExprBV[ AD.EMap[E] ] = Visit(E);
+}
+
} // end anonymous namespace
//===--------------------------------------------------------------------===//
// Merge operator.
+//
+// In our transfer functions we take the approach that any
+// combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
+//
+// Merges take the opposite approach.
+//
+// In the merge of dataflow values (for Decls) we prefer unsoundness, and
+// prefer false negatives to false positives. At merges, if a value for a
+// tracked Decl is EVER initialized in any of the predecessors we treat it as
+// initialized at the confluence point.
+//
+// For tracked CFGBlock-level expressions (such as the result of
+// short-circuit), we do the opposite merge: if a value is EVER uninitialized
+// 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 {
void operator()(UninitializedValues::ValTy& Dst,
UninitializedValues::ValTy& Src) {
- assert (Dst.size() == Src.size() && "Bitvector sizes do not match.");
- Src |= Dst;
+ assert (Dst.DeclBV.size() == Src.DeclBV.size()
+ && "Bitvector sizes do not match.");
+
+ Dst.DeclBV |= Src.DeclBV;
+
+ assert (Dst.ExprBV.size() == Src.ExprBV.size()
+ && "Bitvector sizes do not match.");
+
+ Dst.ExprBV &= Src.ExprBV;
}
};
} // end anonymous namespace
//===--------------------------------------------------------------------===//
-// Observer to flag warnings for uses of uninitialized variables.
-//===--------------------------------------------------------------------===//
-
-
-
-
-//===--------------------------------------------------------------------===//
// External interface (driver logic).
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/include/clang/Analysis/UninitializedValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/UninitializedValues.h?rev=42041&r1=42040&r2=42041&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/UninitializedValues.h Mon Sep 17 13:31:23 2007
@@ -28,27 +28,33 @@
/// Unitialized Values analysis.
class UninitializedValues_ValueTypes {
public:
- class ValTy {
- llvm::BitVector BV;
- public:
- // Accessors to internal bitvector.
- unsigned size() const { return BV.size(); }
- void resize(unsigned i) { BV.resize(i); }
- llvm::BitVector::reference operator[](unsigned i) { return BV[i]; }
- void operator|=(const ValTy& RHS) { BV |= RHS.BV; }
-
+ struct ValTy {
+ llvm::BitVector DeclBV;
+ llvm::BitVector ExprBV;
+
// Used by the solver.
- void resetValues() { BV.reset(); }
- bool equal(ValTy& RHS) const { return BV == RHS.BV; }
- void copyValues(ValTy& RHS) { BV = RHS.BV; }
+ void resetValues() {
+ DeclBV.reset();
+ ExprBV.reset();
+ }
+
+ bool equal(ValTy& RHS) const {
+ return DeclBV == RHS.DeclBV && ExprBV == RHS.ExprBV;
+ }
+
+ void copyValues(ValTy& RHS) {
+ DeclBV = RHS.DeclBV;
+ ExprBV = RHS.ExprBV;
+ }
};
struct AnalysisDataTy {
llvm::DenseMap<const VarDecl*, unsigned > VMap;
llvm::DenseMap<const Expr*, unsigned > EMap;
- unsigned Counter;
+ unsigned NumDecls;
+ unsigned NumBlockExprs;
- AnalysisDataTy() : Counter(0) {}
+ AnalysisDataTy() : NumDecls(0), NumBlockExprs(0) {}
};
};
More information about the cfe-commits
mailing list