forked from OSchip/llvm-project
Created new "ExprDeclBitVector" type bundle for dataflow analyses that need boolean
values associated with ScopedDecls and CFGBlock-level Exprs. This is the common boilerplate needed by UninitializedValues and LiveVariables. Refactored UninitializedValues to use ExprDeclBitVector. Shortened the string diagnostic for UninitializedValues. llvm-svn: 42408
This commit is contained in:
parent
0d675ee06e
commit
b9ce295b0a
|
@ -33,13 +33,8 @@ class RegisterDeclsExprs : public CFGRecStmtDeclVisitor<RegisterDeclsExprs> {
|
|||
public:
|
||||
RegisterDeclsExprs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {}
|
||||
|
||||
void VisitBlockVarDecl(BlockVarDecl* VD) {
|
||||
if (!AD.isTracked(VD)) AD[VD] = AD.NumDecls++;
|
||||
}
|
||||
|
||||
void BlockStmt_VisitExpr(Expr* E) {
|
||||
if (!AD.isTracked(E)) AD[E] = AD.NumBlockExprs++;
|
||||
}
|
||||
void VisitBlockVarDecl(BlockVarDecl* VD) { AD.Register(VD); }
|
||||
void BlockStmt_VisitExpr(Expr* E) { AD.Register(E); }
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -77,19 +72,19 @@ public:
|
|||
bool VisitDeclStmt(DeclStmt* D);
|
||||
|
||||
BlockVarDecl* FindBlockVarDecl(Stmt* S);
|
||||
|
||||
static inline bool Initialized() { return true; }
|
||||
static inline bool Uninitialized() { return false; }
|
||||
};
|
||||
|
||||
static const bool Initialized = true;
|
||||
static const bool Uninitialized = false;
|
||||
|
||||
|
||||
bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
|
||||
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) {
|
||||
if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);
|
||||
|
||||
return V.getBitRef(VD,AD);
|
||||
return V(VD,AD);
|
||||
}
|
||||
else return Initialized();
|
||||
else return Initialized;
|
||||
}
|
||||
|
||||
BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
|
||||
|
@ -109,7 +104,7 @@ BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
|
|||
bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
|
||||
|
||||
if (CFG::hasImplicitControlFlow(B))
|
||||
return V.getBitRef(B,AD);
|
||||
return V(B,AD);
|
||||
|
||||
if (B->isAssignmentOp())
|
||||
// Get the Decl for the LHS (if any).
|
||||
|
@ -122,30 +117,33 @@ bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
|
|||
// just adding extra messages that don't
|
||||
// contribute to diagnosing the bug. In InitWithAssigns mode
|
||||
// we unconditionally set the assigned variable to Initialized to
|
||||
// prevent Uninitialized propogation.
|
||||
return V.getBitRef(VD,AD) = Initialized();
|
||||
// prevent Uninitialized propagation.
|
||||
return V(VD,AD) = Initialized;
|
||||
}
|
||||
else return V.getBitRef(VD,AD) = Visit(B->getRHS());
|
||||
else return V(VD,AD) = Visit(B->getRHS());
|
||||
|
||||
return VisitStmt(B);
|
||||
}
|
||||
|
||||
bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
|
||||
bool x = Initialized();
|
||||
bool x = Initialized;
|
||||
|
||||
for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
|
||||
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D))
|
||||
if (Stmt* I = VD->getInit()) {
|
||||
x = V.getBitRef(cast<Expr>(I),AD);
|
||||
V.getBitRef(VD,AD) = x;
|
||||
}
|
||||
if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) {
|
||||
if (Stmt* I = VD->getInit())
|
||||
x = InitWithAssigns ? Initialized : V(cast<Expr>(I),AD);
|
||||
else
|
||||
x = Uninitialized;
|
||||
|
||||
V(VD,AD) = x;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool TransferFuncs::VisitCallExpr(CallExpr* C) {
|
||||
VisitChildren(C);
|
||||
return Initialized();
|
||||
return Initialized;
|
||||
}
|
||||
|
||||
bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
||||
|
@ -153,7 +151,7 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
|||
case UnaryOperator::AddrOf:
|
||||
// For "&x", treat "x" as now being initialized.
|
||||
if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr()))
|
||||
V.getBitRef(VD,AD) = Initialized();
|
||||
V(VD,AD) = Initialized;
|
||||
else
|
||||
return Visit(U->getSubExpr());
|
||||
|
||||
|
@ -163,20 +161,20 @@ bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
|||
}
|
||||
|
||||
bool TransferFuncs::VisitStmt(Stmt* S) {
|
||||
bool x = Initialized();
|
||||
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) == Uninitialized()) x = Uninitialized();
|
||||
if (Visit(*I) == Uninitialized) x = Uninitialized;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
|
||||
assert (AD.isTracked(E));
|
||||
return V.getBitRef(E,AD) = Visit(E);
|
||||
return V(E,AD) = Visit(E);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -196,15 +194,9 @@ bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
struct Merge {
|
||||
void operator()(UninitializedValues::ValTy& Dst,
|
||||
UninitializedValues::ValTy& Src) {
|
||||
assert (Src.sizesEqual(Dst) && "BV sizes do not match.");
|
||||
Dst.DeclBV |= Src.DeclBV;
|
||||
Dst.ExprBV |= Src.ExprBV;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
typedef ExprDeclBitVector_Types::Union Merge;
|
||||
typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Unitialized values checker. Scan an AST and flag variable uses
|
||||
|
@ -228,7 +220,7 @@ public:
|
|||
|
||||
assert ( AD.isTracked(VD) && "Unknown VarDecl.");
|
||||
|
||||
if (V.getBitRef(VD,AD) == TransferFuncs::Uninitialized())
|
||||
if (V(VD,AD) == Uninitialized)
|
||||
if (AlreadyWarned.insert(VD))
|
||||
Diags.Report(DR->getSourceRange().Begin(), diag::warn_uninit_val);
|
||||
}
|
||||
|
@ -237,8 +229,6 @@ public:
|
|||
|
||||
namespace clang {
|
||||
void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
|
||||
|
||||
typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
|
||||
|
||||
// Compute the unitialized values information.
|
||||
UninitializedValues U;
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
//=- ExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Ted Kremenek and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides definition of dataflow types used by analyses such
|
||||
// as LiveVariables and UninitializedValues. The underlying dataflow values
|
||||
// are implemented as bitvectors, but the definitions in this file include
|
||||
// the necessary boilerplate to use with our dataflow framework.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_EXPRDECLBVDVAL_H
|
||||
#define LLVM_CLANG_EXPRDECLBVDVAL_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Expr;
|
||||
class ScopedDecl;
|
||||
|
||||
struct ExprDeclBitVector_Types {
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// AnalysisDataTy - Whole-function meta data.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
class AnalysisDataTy {
|
||||
typedef llvm::DenseMap<const ScopedDecl*, unsigned > DMapTy;
|
||||
typedef llvm::DenseMap<const Expr*, unsigned > EMapTy;
|
||||
|
||||
EMapTy EMap;
|
||||
DMapTy DMap;
|
||||
unsigned NDecls;
|
||||
unsigned NExprs;
|
||||
|
||||
public:
|
||||
|
||||
AnalysisDataTy() : NDecls(0), NExprs(0) {}
|
||||
virtual ~AnalysisDataTy() {}
|
||||
|
||||
bool isTracked(const ScopedDecl* SD) { return DMap.find(SD) != DMap.end(); }
|
||||
bool isTracked(const Expr* E) { return EMap.find(E) != EMap.end(); }
|
||||
|
||||
unsigned operator[](const ScopedDecl* SD) const {
|
||||
DMapTy::const_iterator I = DMap.find(SD);
|
||||
assert (I != DMap.end());
|
||||
return I->second;
|
||||
}
|
||||
|
||||
unsigned operator[](const Expr* E) const {
|
||||
EMapTy::const_iterator I = EMap.find(E);
|
||||
assert (I != EMap.end());
|
||||
return I->second;
|
||||
}
|
||||
|
||||
unsigned getNumDecls() const { return NDecls; }
|
||||
unsigned getNumExprs() const { return NExprs; }
|
||||
|
||||
void Register(const ScopedDecl* SD) {
|
||||
if (!isTracked(SD)) DMap[SD] = NDecls++;
|
||||
}
|
||||
|
||||
void Register(const Expr* E) {
|
||||
if (!isTracked(E)) EMap[E] = NExprs++;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// ValTy - Dataflow value.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
class ValTy {
|
||||
llvm::BitVector DeclBV;
|
||||
llvm::BitVector ExprBV;
|
||||
public:
|
||||
|
||||
void resetValues(AnalysisDataTy& AD) {
|
||||
DeclBV.resize(AD.getNumDecls());
|
||||
DeclBV.reset();
|
||||
ExprBV.resize(AD.getNumExprs());
|
||||
ExprBV.reset();
|
||||
}
|
||||
|
||||
bool operator==(const ValTy& RHS) const {
|
||||
assert (sizesEqual(RHS));
|
||||
return DeclBV == RHS.DeclBV && ExprBV == RHS.ExprBV;
|
||||
}
|
||||
|
||||
void copyValues(const ValTy& RHS) {
|
||||
DeclBV = RHS.DeclBV;
|
||||
ExprBV = RHS.ExprBV;
|
||||
}
|
||||
|
||||
llvm::BitVector::reference
|
||||
operator()(const ScopedDecl* SD, const AnalysisDataTy& AD) {
|
||||
return DeclBV[AD[SD]];
|
||||
}
|
||||
const llvm::BitVector::reference
|
||||
operator()(const ScopedDecl* SD, const AnalysisDataTy& AD) const {
|
||||
return const_cast<ValTy&>(*this)(SD,AD);
|
||||
}
|
||||
|
||||
llvm::BitVector::reference
|
||||
operator()(const Expr* E, const AnalysisDataTy& AD) {
|
||||
return ExprBV[AD[E]];
|
||||
}
|
||||
const llvm::BitVector::reference
|
||||
operator()(const Expr* E, const AnalysisDataTy& AD) const {
|
||||
return const_cast<ValTy&>(*this)(E,AD);
|
||||
}
|
||||
|
||||
ValTy& operator|=(const ValTy& RHS) {
|
||||
assert (sizesEqual(RHS));
|
||||
DeclBV |= RHS.DeclBV;
|
||||
ExprBV |= RHS.ExprBV;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ValTy& operator&=(const ValTy& RHS) {
|
||||
assert (sizesEqual(RHS));
|
||||
DeclBV &= RHS.DeclBV;
|
||||
ExprBV &= RHS.ExprBV;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool sizesEqual(const ValTy& RHS) const {
|
||||
return DeclBV.size() == RHS.DeclBV.size()
|
||||
&& ExprBV.size() == RHS.ExprBV.size();
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Some useful merge operations.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
|
||||
struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
|
||||
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef LLVM_CLANG_UNITVALS_H
|
||||
#define LLVM_CLANG_UNITVALS_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "clang/Analysis/ExprDeclBitVector.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
|
||||
|
||||
namespace clang {
|
||||
|
@ -31,75 +31,16 @@ namespace clang {
|
|||
class UninitializedValues_ValueTypes {
|
||||
public:
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// AnalysisDataTy - Whole-function meta data used by the transfer function
|
||||
// logic.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
struct ObserverTy;
|
||||
|
||||
struct AnalysisDataTy {
|
||||
llvm::DenseMap<const BlockVarDecl*, unsigned > VMap;
|
||||
llvm::DenseMap<const Expr*, unsigned > EMap;
|
||||
unsigned NumDecls;
|
||||
unsigned NumBlockExprs;
|
||||
struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
|
||||
AnalysisDataTy() : Observer(NULL) {}
|
||||
virtual ~AnalysisDataTy() {};
|
||||
|
||||
ObserverTy* Observer;
|
||||
|
||||
AnalysisDataTy() : NumDecls(0), NumBlockExprs(0), Observer(NULL) {}
|
||||
|
||||
bool isTracked(const BlockVarDecl* VD) {
|
||||
return VMap.find(VD) != VMap.end();
|
||||
}
|
||||
|
||||
bool isTracked(const Expr* E) {
|
||||
return EMap.find(E) != EMap.end();
|
||||
}
|
||||
|
||||
unsigned& operator[](const BlockVarDecl *VD) { return VMap[VD]; }
|
||||
unsigned& operator[](const Expr* E) { return EMap[E]; }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// ValTy - Dataflow value.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
struct ValTy {
|
||||
llvm::BitVector DeclBV;
|
||||
llvm::BitVector ExprBV;
|
||||
|
||||
void resetValues(AnalysisDataTy& AD) {
|
||||
DeclBV.resize(AD.NumDecls);
|
||||
DeclBV.reset();
|
||||
ExprBV.resize(AD.NumBlockExprs);
|
||||
ExprBV.reset();
|
||||
}
|
||||
|
||||
bool operator==(const ValTy& RHS) const {
|
||||
return DeclBV == RHS.DeclBV && ExprBV == RHS.ExprBV;
|
||||
}
|
||||
|
||||
void copyValues(const ValTy& RHS) {
|
||||
DeclBV = RHS.DeclBV;
|
||||
ExprBV = RHS.ExprBV;
|
||||
}
|
||||
|
||||
llvm::BitVector::reference getBitRef(const BlockVarDecl* VD,
|
||||
AnalysisDataTy& AD) {
|
||||
assert (AD.isTracked(VD) && "BlockVarDecl not tracked.");
|
||||
return DeclBV[AD.VMap[VD]];
|
||||
}
|
||||
|
||||
llvm::BitVector::reference getBitRef(const Expr* E,
|
||||
AnalysisDataTy& AD) {
|
||||
assert (AD.isTracked(E) && "Expr not tracked.");
|
||||
return ExprBV[AD.EMap[E]];
|
||||
}
|
||||
|
||||
bool sizesEqual(ValTy& RHS) {
|
||||
return DeclBV.size() == RHS.DeclBV.size() &&
|
||||
ExprBV.size() == RHS.ExprBV.size();
|
||||
}
|
||||
};
|
||||
typedef ExprDeclBitVector_Types::ValTy ValTy;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
|
||||
|
|
|
@ -785,7 +785,7 @@ DIAG(warn_floatingpoint_eq, WARNING,
|
|||
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")
|
||||
DIAG(warn_uninit_val, WARNING, "use of uninitialized variable")
|
||||
|
||||
// CFString checking
|
||||
DIAG(err_cfstring_literal_not_string_constant, ERROR,
|
||||
|
|
Loading…
Reference in New Issue