aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/GRExprEngine.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-12-23 00:26:16 +0000
committerTed Kremenek <kremenek@apple.com>2009-12-23 00:26:16 +0000
commit949bdb43bf370b23a79a37b017e0a0566c0d66e0 (patch)
treef6919799da77ef27338b3ad435a6dc6dacf435a6 /lib/Analysis/GRExprEngine.cpp
parent2a17af0c7e05500e25d4cc71341f1f232085ebea (diff)
Add basic support for analyzing CastExprs as lvalues.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91952 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r--lib/Analysis/GRExprEngine.cpp30
1 files changed, 27 insertions, 3 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 4d431e5639..6e77b6b103 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -658,7 +658,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: {
CastExpr* C = cast<CastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst);
+ VisitCast(C, C->getSubExpr(), Pred, Dst, false);
break;
}
@@ -753,6 +753,13 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
}
switch (Ex->getStmtClass()) {
+ // C++ stuff we don't support yet.
+ case Stmt::CXXMemberCallExprClass: {
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ Builder->BuildSinks = true;
+ MakeNode(Dst, Ex, Pred, GetState(Pred));
+ break;
+ }
case Stmt::ArraySubscriptExprClass:
VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true);
@@ -783,6 +790,14 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return;
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CStyleCastExprClass: {
+ CastExpr *C = cast<CastExpr>(Ex);
+ QualType T = Ex->getType();
+ VisitCast(C, C->getSubExpr(), Pred, Dst, true);
+ break;
+ }
+
case Stmt::MemberExprClass:
VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
return;
@@ -2080,7 +2095,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
//===----------------------------------------------------------------------===//
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst){
+ ExplodedNodeSet& Dst, bool asLValue){
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@@ -2088,7 +2103,8 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
T = ExCast->getTypeAsWritten();
- if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType())
+ if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType() ||
+ asLValue)
VisitLValue(Ex, Pred, S1);
else
Visit(Ex, Pred, S1);
@@ -2098,10 +2114,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
// Check for casting to "void".
if (T->isVoidType()) {
+ assert(!asLValue);
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
Dst.Add(*I);
return;
}
+
+ // If we are evaluating the cast in an lvalue context, we implicitly want
+ // the cast to evaluate to a location.
+ if (asLValue) {
+ ASTContext &Ctx = getContext();
+ T = Ctx.getPointerType(Ctx.getCanonicalType(T));
+ }
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;