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
This commit is contained in:
Ted Kremenek 2009-12-23 00:26:16 +00:00
Родитель 2a17af0c7e
Коммит 949bdb43bf
3 изменённых файлов: 39 добавлений и 4 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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,11 +2114,19 @@ 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;
const GRState* state = GetState(N);

Просмотреть файл

@ -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);
}