From: Ted Kremenek Date: Wed, 23 Dec 2009 00:26:16 +0000 (+0000) Subject: Add basic support for analyzing CastExprs as lvalues. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=949bdb43bf370b23a79a37b017e0a0566c0d66e0;p=clang 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 --- diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 783055a955..647c1226f0 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -269,7 +269,7 @@ protected: /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + ExplodedNodeSet& Dst, bool asLValue); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, 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(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 OldSink(Builder->BuildSinks); + Builder->BuildSinks = true; + MakeNode(Dst, Ex, Pred, GetState(Pred)); + break; + } case Stmt::ArraySubscriptExprClass: VisitArraySubscriptExpr(cast(Ex), Pred, Dst, true); @@ -783,6 +790,14 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, VisitDeclRefExpr(cast(Ex), Pred, Dst, true); return; + case Stmt::ImplicitCastExprClass: + case Stmt::CStyleCastExprClass: { + CastExpr *C = cast(Ex); + QualType T = Ex->getType(); + VisitCast(C, C->getSubExpr(), Pred, Dst, true); + break; + } + case Stmt::MemberExprClass: VisitMemberExpr(cast(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(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; diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index c3e07b26b0..e1750139c2 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -12,3 +12,14 @@ char test1_as_rvalue() { return test1_aux(); } +// Test passing a value as a reference. The 'const' in test2_aux() adds +// an ImplicitCastExpr, which is evaluated as an lvalue. +int test2_aux(const int &n); +int test2(int n) { + return test2_aux(n); +} + +int test2_b_aux(const short &n); +int test2_b(int n) { + return test2_b_aux(n); +}