[cfe-commits] r50108 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BasicValueFactory.h include/clang/Analysis/PathSensitive/RValues.h lib/Analysis/BasicValueFactory.cpp lib/Analysis/GRExprEngine.cpp lib/Analysis/RValues.cpp lib/Analysis/ValueState.cpp test/Analysis/null-deref-ps.c
Ted Kremenek
kremenek at apple.com
Tue Apr 22 14:10:19 PDT 2008
Author: kremenek
Date: Tue Apr 22 16:10:18 2008
New Revision: 50108
URL: http://llvm.org/viewvc/llvm-project?rev=50108&view=rev
Log:
Added "nonlval::LValAsInteger" to represent abstract LVals casted to integers, allowing us to track lvals when they are casted back to pointers.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
cfe/trunk/lib/Analysis/BasicValueFactory.cpp
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/RValues.cpp
cfe/trunk/lib/Analysis/ValueState.cpp
cfe/trunk/test/Analysis/null-deref-ps.c
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h Tue Apr 22 16:10:18 2008
@@ -27,22 +27,26 @@
namespace clang {
+class RVal;
+
class BasicValueFactory {
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
APSIntSetTy;
typedef llvm::FoldingSet<SymIntConstraint>
SymIntCSetTy;
+
ASTContext& Ctx;
llvm::BumpPtrAllocator& BPAlloc;
APSIntSetTy APSIntSet;
SymIntCSetTy SymIntCSet;
+ void* PersistentRVals;
public:
BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
- : Ctx(ctx), BPAlloc(Alloc) {}
+ : Ctx(ctx), BPAlloc(Alloc), PersistentRVals(0) {}
~BasicValueFactory();
@@ -66,6 +70,9 @@
const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1,
const llvm::APSInt& V2);
+
+ const std::pair<RVal, unsigned>&
+ getPersistentSizedRVal(const RVal& V, unsigned Bits);
};
} // end clang namespace
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Tue Apr 22 16:10:18 2008
@@ -163,7 +163,8 @@
namespace nonlval {
-enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind };
+enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind,
+ LValAsIntegerKind };
class SymbolVal : public NonLVal {
public:
@@ -230,6 +231,40 @@
}
};
+class LValAsInteger : public NonLVal {
+ LValAsInteger(const std::pair<RVal, unsigned>& data) :
+ NonLVal(LValAsIntegerKind, &data) {}
+
+public:
+
+ LVal getLVal() const {
+ return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
+ }
+
+ const LVal& getPersistentLVal() const {
+ return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
+ }
+
+ unsigned getNumBits() const {
+ return ((std::pair<RVal, unsigned>*) Data)->second;
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == NonLValKind &&
+ V->getSubKind() == LValAsIntegerKind;
+ }
+
+ static inline bool classof(const NonLVal* V) {
+ return V->getSubKind() == LValAsIntegerKind;
+ }
+
+ static inline LValAsInteger Make(BasicValueFactory& Vals, LVal V,
+ unsigned Bits) {
+ return LValAsInteger(Vals.getPersistentSizedRVal(V, Bits));
+ }
+};
+
} // end namespace clang::nonlval
//==------------------------------------------------------------------------==//
Modified: cfe/trunk/lib/Analysis/BasicValueFactory.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicValueFactory.cpp?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicValueFactory.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicValueFactory.cpp Tue Apr 22 16:10:18 2008
@@ -14,15 +14,32 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
+#include "clang/Analysis/PathSensitive/RValues.h"
using namespace clang;
+typedef std::pair<RVal, unsigned> SizedRVal;
+
+namespace llvm {
+template<> struct FoldingSetTrait<SizedRVal> {
+ static inline void Profile(const SizedRVal& X, llvm::FoldingSetNodeID& ID) {
+ X.first.Profile(ID);
+ ID.AddInteger(X.second);
+ }
+};
+}
+
+typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SizedRVal> >
+ PersistentRValsTy;
+
BasicValueFactory::~BasicValueFactory() {
// Note that the dstor for the contents of APSIntSet will never be called,
// so we iterate over the set and invoke the dstor for each APSInt. This
// frees an aux. memory allocated to represent very large constants.
for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
I->getValue().~APSInt();
+
+ delete (PersistentRValsTy*) PersistentRVals;
}
const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
@@ -165,3 +182,29 @@
return &getValue( V1 ^ V2 );
}
}
+
+
+const std::pair<RVal, unsigned>&
+BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) {
+
+ // Lazily create the folding set.
+ if (!PersistentRVals) PersistentRVals = new PersistentRValsTy();
+
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ V.Profile(ID);
+ ID.AddInteger(Bits);
+
+ PersistentRValsTy& Map = *((PersistentRValsTy*) PersistentRVals);
+
+ typedef llvm::FoldingSetNodeWrapper<SizedRVal> FoldNodeTy;
+ FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!P) {
+ P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+ new (P) FoldNodeTy(std::make_pair(V, Bits));
+ Map.InsertNode(P, InsertPos);
+ }
+
+ return *P;
+}
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Apr 22 16:10:18 2008
@@ -1102,10 +1102,8 @@
else
Visit(Ex, Pred, S1);
- // Check for redundant casts or casting to "void"
- if (T->isVoidType() ||
- Ex->getType() == T ||
- (T->isPointerType() && Ex->getType()->isFunctionType())) {
+ // Check for casting to "void".
+ if (T->isVoidType()) {
for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1)
Dst.Add(*I1);
@@ -1113,11 +1111,54 @@
return;
}
+ // FIXME: The rest of this should probably just go into EvalCall, and
+ // let the transfer function object be responsible for constructing
+ // nodes.
+
+ QualType ExTy = Ex->getType();
+
for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N = *I1;
ValueState* St = GetState(N);
-
RVal V = T->isReferenceType() ? GetLVal(St, Ex) : GetRVal(St, Ex);
+
+ // Unknown?
+
+ if (V.isUnknown()) {
+ Dst.Add(N);
+ continue;
+ }
+
+ // Undefined?
+
+ if (V.isUndef()) {
+ MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+ continue;
+ }
+
+ // Check for casts from pointers to integers.
+ if (T->isIntegerType() && ExTy->isPointerType()) {
+ unsigned bits = getContext().getTypeSize(ExTy);
+
+ // FIXME: Determine if the number of bits of the target type is
+ // equal or exceeds the number of bits to store the pointer value.
+ // If not, flag an error.
+
+ V = nonlval::LValAsInteger::Make(BasicVals, cast<LVal>(V), bits);
+ MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+ continue;
+ }
+
+ // Check for casts from integers to pointers.
+ if (T->isPointerType() && ExTy->isIntegerType())
+ if (nonlval::LValAsInteger *LV = dyn_cast<nonlval::LValAsInteger>(&V)) {
+ // Just unpackage the lval and return it.
+ V = LV->getLVal();
+ MakeNode(Dst, CastE, N, SetRVal(St, CastE, V));
+ continue;
+ }
+
+ // All other cases.
MakeNode(Dst, CastE, N, SetRVal(St, CastE, EvalCast(V, CastE->getType())));
}
@@ -2024,6 +2065,11 @@
isFeasible = b ? Assumption : !Assumption;
return St;
}
+
+ case nonlval::LValAsIntegerKind: {
+ return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
+ Assumption, isFeasible);
+ }
}
}
Modified: cfe/trunk/lib/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RValues.cpp?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RValues.cpp (original)
+++ cfe/trunk/lib/Analysis/RValues.cpp Tue Apr 22 16:10:18 2008
@@ -35,6 +35,10 @@
return (symbol_iterator) &C.getSymbol();
}
+ else if (isa<nonlval::LValAsInteger>(this)) {
+ const nonlval::LValAsInteger& V = cast<nonlval::LValAsInteger>(*this);
+ return V.getPersistentLVal().symbol_begin();
+ }
return NULL;
}
@@ -345,7 +349,14 @@
Out << 'U';
break;
- }
+ }
+
+ case nonlval::LValAsIntegerKind: {
+ const nonlval::LValAsInteger& C = *cast<nonlval::LValAsInteger>(this);
+ C.getLVal().print(Out);
+ Out << " [as " << C.getNumBits() << " bit integer]";
+ break;
+ }
default:
assert (false && "Pretty-printed not implemented for this NonLVal.");
Modified: cfe/trunk/lib/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ValueState.cpp?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ValueState.cpp (original)
+++ cfe/trunk/lib/Analysis/ValueState.cpp Tue Apr 22 16:10:18 2008
@@ -277,12 +277,7 @@
return UnknownVal();
QualType ST = C->getSubExpr()->getType();
-
- if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
- E = C->getSubExpr();
- continue;
- }
-
+
break;
}
@@ -294,11 +289,6 @@
if (CT->isVoidType())
return UnknownVal();
- if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
- E = C->getSubExpr();
- continue;
- }
-
break;
}
Modified: cfe/trunk/test/Analysis/null-deref-ps.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/null-deref-ps.c?rev=50108&r1=50107&r2=50108&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/null-deref-ps.c (original)
+++ cfe/trunk/test/Analysis/null-deref-ps.c Tue Apr 22 16:10:18 2008
@@ -1,5 +1,7 @@
// RUN: clang -checker-simple -verify %s
+#include<stdint.h>
+
void f1(int *p) {
if (p) *p = 1;
else *p = 0; // expected-warning{{ereference}}
@@ -27,3 +29,13 @@
return x[i+1]; // expected-warning{{Dereference of null pointer.}}
}
+int f4(int *p) {
+
+ uintptr_t x = p;
+
+ if (x)
+ return 1;
+
+ int *q = (int*) x;
+ return *q; // expected-warning{{Dereference of null pointer.}}
+}
\ No newline at end of file
More information about the cfe-commits
mailing list