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). /// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals. /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,

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

@ -658,7 +658,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
case Stmt::ImplicitCastExprClass: case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: { case Stmt::CStyleCastExprClass: {
CastExpr* C = cast<CastExpr>(S); CastExpr* C = cast<CastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst); VisitCast(C, C->getSubExpr(), Pred, Dst, false);
break; break;
} }
@ -753,6 +753,13 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
} }
switch (Ex->getStmtClass()) { 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: case Stmt::ArraySubscriptExprClass:
VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true); 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); VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return; 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: case Stmt::MemberExprClass:
VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true); VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
return; return;
@ -2080,7 +2095,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst){ ExplodedNodeSet& Dst, bool asLValue){
ExplodedNodeSet S1; ExplodedNodeSet S1;
QualType T = CastE->getType(); QualType T = CastE->getType();
QualType ExTy = Ex->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)) if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
T = ExCast->getTypeAsWritten(); T = ExCast->getTypeAsWritten();
if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType()) if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType() ||
asLValue)
VisitLValue(Ex, Pred, S1); VisitLValue(Ex, Pred, S1);
else else
Visit(Ex, Pred, S1); Visit(Ex, Pred, S1);
@ -2098,10 +2114,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
// Check for casting to "void". // Check for casting to "void".
if (T->isVoidType()) { if (T->isVoidType()) {
assert(!asLValue);
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
Dst.Add(*I); Dst.Add(*I);
return; 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) { for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I; ExplodedNode* N = *I;

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

@ -12,3 +12,14 @@ char test1_as_rvalue() {
return test1_aux(); 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);
}