зеркало из 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).
|
/// 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,11 +2114,19 @@ 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;
|
||||||
const GRState* state = GetState(N);
|
const GRState* state = GetState(N);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче