зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
2a17af0c7e
Коммит
949bdb43bf
|
@ -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,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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче