[cfe-commits] r46298 - in /cfe/trunk: Analysis/GRConstants.cpp Driver/ASTConsumers.cpp include/clang/Analysis/Analyses/GRConstants.h include/clang/Analysis/PathSensitive/GREngine.h
Ted Kremenek
kremenek at apple.com
Wed Jan 23 18:02:54 PST 2008
Author: kremenek
Date: Wed Jan 23 20:02:54 2008
New Revision: 46298
URL: http://llvm.org/viewvc/llvm-project?rev=46298&view=rev
Log:
Added passing "ASTContext" to both GREngine and GRConstants.
Added initial support for integer casting operations to GRConstants.
Modified:
cfe/trunk/Analysis/GRConstants.cpp
cfe/trunk/Driver/ASTConsumers.cpp
cfe/trunk/include/clang/Analysis/Analyses/GRConstants.h
cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46298&r1=46297&r2=46298&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Wed Jan 23 20:02:54 2008
@@ -17,6 +17,7 @@
#include "clang/Analysis/PathSensitive/GREngine.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/Support/Casting.h"
@@ -114,14 +115,16 @@
typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
class VISIBILITY_HIDDEN ValueManager {
-
-
APSIntSetTy::Factory APSIntSetFactory;
+ ASTContext* Ctx;
public:
ValueManager() {}
~ValueManager() {}
+ void setContext(ASTContext* ctx) { Ctx = ctx; }
+ ASTContext* getContext() const { return Ctx; }
+
APSIntSetTy GetEmptyAPSIntSet() {
return APSIntSetFactory.GetEmptySet();
}
@@ -164,6 +167,8 @@
public:
~ExprValue() {};
+ ExprValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
+
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getKind());
ID.AddPointer(Data);
@@ -204,9 +209,9 @@
RValue(Kind k, void* d) : ExprValue(k,d) {}
public:
- RValue Add(ValueManager& ValMgr, const RValue& RHS) const;
- RValue Sub(ValueManager& ValMgr, const RValue& RHS) const;
- RValue Mul(ValueManager& ValMgr, const RValue& RHS) const;
+ RValue EvalAdd(ValueManager& ValMgr, const RValue& RHS) const;
+ RValue EvalSub(ValueManager& ValMgr, const RValue& RHS) const;
+ RValue EvalMul(ValueManager& ValMgr, const RValue& RHS) const;
static RValue GetRValue(ValueManager& ValMgr, IntegerLiteral* S);
@@ -225,9 +230,16 @@
return APSIntSetTy(reinterpret_cast<APSIntSetTy::TreeTy*>(getRawPtr()));
}
- RValueMayEqualSet Add(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
- RValueMayEqualSet Sub(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
- RValueMayEqualSet Mul(ValueManager& ValMgr, const RValueMayEqualSet& V) const;
+ RValueMayEqualSet EvalAdd(ValueManager& ValMgr,
+ const RValueMayEqualSet& V) const;
+
+ RValueMayEqualSet EvalSub(ValueManager& ValMgr,
+ const RValueMayEqualSet& V) const;
+
+ RValueMayEqualSet EvalMul(ValueManager& ValMgr,
+ const RValueMayEqualSet& V) const;
+
+ RValueMayEqualSet EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
// Implement isa<T> support.
static inline bool classof(const ExprValue* V) {
@@ -237,12 +249,43 @@
} // end anonymous namespace
//===----------------------------------------------------------------------===//
-// "R-Values": Implementation.
+// Transfer functions: Casts.
+//===----------------------------------------------------------------------===//
+
+ExprValue ExprValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
+ switch (getKind()) {
+ case RValueMayEqualSetKind:
+ return cast<RValueMayEqualSet>(this)->EvalCast(ValMgr, CastExpr);
+ default:
+ return InvalidValue();
+ }
+}
+
+RValueMayEqualSet
+RValueMayEqualSet::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const {
+ QualType T = CastExpr->getType();
+ assert (T->isIntegerType());
+
+ APSIntSetTy S1 = GetValues();
+ APSIntSetTy S2 = ValMgr.GetEmptyAPSIntSet();
+
+ for (APSIntSetTy::iterator I=S1.begin(), E=S1.end(); I!=E; ++I) {
+ llvm::APSInt X = *I;
+ X.setIsSigned(T->isSignedIntegerType());
+ X.extOrTrunc(ValMgr.getContext()->getTypeSize(T,CastExpr->getLocStart()));
+ S2 = ValMgr.AddToSet(S2, X);
+ }
+
+ return S2;
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions: Binary Operations over R-Values.
//===----------------------------------------------------------------------===//
#define RVALUE_DISPATCH_CASE(k1,k2,Op)\
case ((k1##Kind+(MaxRValueKind-MinRValueKind))+(k2##Kind - MinRValueKind)):\
- return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS));
+ return cast<k1>(*this).Eval##Op(ValMgr,cast<k2>(RHS));
#define RVALUE_DISPATCH(Op)\
switch (getKind()+(MaxRValueKind-MinRValueKind)+(RHS.getKind()-MinRValueKind)){\
@@ -253,15 +296,15 @@
}\
return cast<RValue>(InvalidValue());
-RValue RValue::Add(ValueManager& ValMgr, const RValue& RHS) const {
+RValue RValue::EvalAdd(ValueManager& ValMgr, const RValue& RHS) const {
RVALUE_DISPATCH(Add)
}
-RValue RValue::Sub(ValueManager& ValMgr, const RValue& RHS) const {
+RValue RValue::EvalSub(ValueManager& ValMgr, const RValue& RHS) const {
RVALUE_DISPATCH(Sub)
}
-RValue RValue::Mul(ValueManager& ValMgr, const RValue& RHS) const {
+RValue RValue::EvalMul(ValueManager& ValMgr, const RValue& RHS) const {
RVALUE_DISPATCH(Mul)
}
@@ -269,8 +312,8 @@
#undef RVALUE_DISPATCH
RValueMayEqualSet
-RValueMayEqualSet::Add(ValueManager& ValMgr,
- const RValueMayEqualSet& RHS) const {
+RValueMayEqualSet::EvalAdd(ValueManager& ValMgr,
+ const RValueMayEqualSet& RHS) const {
APSIntSetTy S1 = GetValues();
APSIntSetTy S2 = RHS.GetValues();
@@ -285,8 +328,8 @@
}
RValueMayEqualSet
-RValueMayEqualSet::Sub(ValueManager& ValMgr,
- const RValueMayEqualSet& RHS) const {
+RValueMayEqualSet::EvalSub(ValueManager& ValMgr,
+ const RValueMayEqualSet& RHS) const {
APSIntSetTy S1 = GetValues();
APSIntSetTy S2 = RHS.GetValues();
@@ -301,8 +344,8 @@
}
RValueMayEqualSet
-RValueMayEqualSet::Mul(ValueManager& ValMgr,
- const RValueMayEqualSet& RHS) const {
+RValueMayEqualSet::EvalMul(ValueManager& ValMgr,
+ const RValueMayEqualSet& RHS) const {
APSIntSetTy S1 = GetValues();
APSIntSetTy S2 = RHS.GetValues();
@@ -473,8 +516,9 @@
/// Initialize - Initialize the checker's state based on the specified
/// CFG. This results in liveness information being computed for
/// each block-level statement in the CFG.
- void Initialize(CFG& c) {
- cfg = &c;
+ void Initialize(CFG& c, ASTContext& ctx) {
+ cfg = &c;
+ ValMgr.setContext(&ctx);
Liveness = new LiveVariables(c);
Liveness->runOnCFG(c);
Liveness->runOnAllBlocks(c, NULL, true);
@@ -510,6 +554,9 @@
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitCast - Transfer function logic for all casts (implicit and explicit).
+ void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
@@ -566,6 +613,24 @@
case Stmt::IntegerLiteralClass:
return RValue::GetRValue(ValMgr, cast<IntegerLiteral>(S));
+
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
+ if (C->getType() == C->getSubExpr()->getType()) {
+ S = C->getSubExpr();
+ continue;
+ }
+ break;
+ }
+
+ case Stmt::CastExprClass: {
+ CastExpr* C = cast<CastExpr>(S);
+ if (C->getType() == C->getSubExpr()->getType()) {
+ S = C->getSubExpr();
+ continue;
+ }
+ break;
+ }
default:
break;
@@ -575,6 +640,7 @@
}
StateTy::TreeTy* T = St.SlimFind(ValueKey(S, getCFG().isBlkExpr(S)));
+
return T ? T->getValue().second : InvalidValue();
}
@@ -654,6 +720,28 @@
Dst.Add(Builder->generateNode(S, St, Pred));
}
+void GRConstants::VisitCast(Expr* CastE, Expr* E, GRConstants::NodeTy* Pred,
+ GRConstants::NodeSet& Dst) {
+
+ QualType T = CastE->getType();
+
+ // Check for redundant casts.
+ if (E->getType() == T) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ NodeSet S1;
+ Visit(E, Pred, S1);
+
+ for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+ NodeTy* N = *I1;
+ StateTy St = N->getState();
+ const ExprValue& V = GetValue(St, E);
+ Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE)));
+ }
+ }
+
void GRConstants::VisitBinaryOperator(BinaryOperator* B,
GRConstants::NodeTy* Pred,
GRConstants::NodeSet& Dst) {
@@ -684,21 +772,21 @@
const RValue& R1 = cast<RValue>(V1);
const RValue& R2 = cast<RValue>(V2);
- Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2)));
+ Nodify(Dst, B, N2, SetValue(St, B, R1.EvalAdd(ValMgr, R2)));
break;
}
case BinaryOperator::Sub: {
const RValue& R1 = cast<RValue>(V1);
const RValue& R2 = cast<RValue>(V2);
- Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2)));
+ Nodify(Dst, B, N2, SetValue(St, B, R1.EvalSub(ValMgr, R2)));
break;
}
case BinaryOperator::Mul: {
const RValue& R1 = cast<RValue>(V1);
const RValue& R2 = cast<RValue>(V2);
- Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2)));
+ Nodify(Dst, B, N2, SetValue(St, B, R1.EvalMul(ValMgr, R2)));
break;
}
@@ -712,7 +800,7 @@
case BinaryOperator::AddAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
- RValue Result = R1.Add(ValMgr, cast<RValue>(V2));
+ RValue Result = R1.EvalAdd(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
@@ -720,7 +808,7 @@
case BinaryOperator::SubAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
- RValue Result = R1.Sub(ValMgr, cast<RValue>(V2));
+ RValue Result = R1.EvalSub(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
@@ -728,7 +816,7 @@
case BinaryOperator::MulAssign: {
const LValue& L1 = cast<LValue>(V1);
RValue R1 = cast<RValue>(GetValue(N1->getState(), L1));
- RValue Result = R1.Mul(ValMgr, cast<RValue>(V2));
+ RValue Result = R1.EvalMul(ValMgr, cast<RValue>(V2));
Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
break;
}
@@ -764,6 +852,18 @@
Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
break;
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CastExprClass: {
+ CastExpr* C = cast<CastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
default:
Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
break;
@@ -867,8 +967,8 @@
#endif
namespace clang {
-void RunGRConstants(CFG& cfg) {
- GREngine<GRConstants> Engine(cfg);
+void RunGRConstants(CFG& cfg, ASTContext& Ctx) {
+ GREngine<GRConstants> Engine(cfg, Ctx);
Engine.ExecuteWorkList();
#ifndef NDEBUG
llvm::ViewGraph(*Engine.getGraph().roots_begin(),"GRConstants");
Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=46298&r1=46297&r2=46298&view=diff
==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Wed Jan 23 20:02:54 2008
@@ -567,16 +567,17 @@
namespace {
class GRConstantsVisitor : public CFGVisitor {
+ ASTContext* Ctx;
public:
- virtual void Initialize(ASTContext &Context) {}
+ virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
virtual void VisitCFG(CFG& C) {
- RunGRConstants(C);
+ RunGRConstants(C, *Ctx);
}
};
} // end anonymous namespace
-ASTConsumer *clang::CreateGRConstants() {
+ASTConsumer* clang::CreateGRConstants() {
return new GRConstantsVisitor();
}
Modified: cfe/trunk/include/clang/Analysis/Analyses/GRConstants.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/GRConstants.h?rev=46298&r1=46297&r2=46298&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/GRConstants.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/GRConstants.h Wed Jan 23 20:02:54 2008
@@ -23,7 +23,7 @@
/// on a provided CFG. This interface will eventually be replaced with
/// something more elaborate as the requirements on the interface become
/// clearer.
- void RunGRConstants(CFG& cfg);
+ void RunGRConstants(CFG& cfg, ASTContext& Ctx);
} // end clang namespace
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h?rev=46298&r1=46297&r2=46298&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h Wed Jan 23 20:02:54 2008
@@ -22,6 +22,7 @@
namespace clang {
class CFG;
+class ASTContext;
class GRNodeBuilderImpl;
class GRWorkList;
@@ -195,10 +196,10 @@
public:
/// Construct a GREngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
- GREngine(CFG& cfg)
+ GREngine(CFG& cfg, ASTContext& Ctx)
: GREngineImpl(cfg, new GraphTy(), GRWorkList::MakeDFS()),
Checker(static_cast<GraphTy*>(G.get())->getCheckerState()) {
- Checker->Initialize(cfg);
+ Checker->Initialize(cfg, Ctx);
}
/// Construct a GREngine object to analyze the provided CFG and to
More information about the cfe-commits
mailing list