aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-04-30 23:23:55 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-04-30 23:23:55 +0000
commite720ce7a3b1c1bfa5f7482183caa6e31fca9a3fb (patch)
treeba99317c718cc14ca0e53b0071474498d53f75af /lib/Sema/SemaChecking.cpp
parent8fba894335b979e6d213c685bca959168c1f2182 (diff)
When going through references to check if the function returns the address
of a local variable, make sure we don't infinitely recurse when the reference binds to itself. e.g: int* func() { int& i = i; // assign non-exist variable to a reference which has same name. return &i; // return pointer } rdar://11345441 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155856 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp58
1 files changed, 34 insertions, 24 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index a9557a5474..979a646442 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -3017,8 +3017,10 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
//===--- CHECK: Return Address of Stack Variable --------------------------===//
-static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars);
-static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars);
+static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
+ Decl *ParentDecl);
+static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars,
+ Decl *ParentDecl);
/// CheckReturnStackAddr - Check if a return statement returns the address
/// of a stack variable.
@@ -3033,9 +3035,9 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
// label addresses or references to temporaries.
if (lhsType->isPointerType() ||
(!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
- stackE = EvalAddr(RetValExp, refVars);
+ stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/0);
} else if (lhsType->isReferenceType()) {
- stackE = EvalVal(RetValExp, refVars);
+ stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/0);
}
if (stackE == 0)
@@ -3109,7 +3111,8 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
/// * arbitrary interplay between "&" and "*" operators
/// * pointer arithmetic from an address of a stack variable
/// * taking the address of an array element where the array is on the stack
-static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
+static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
+ Decl *ParentDecl) {
if (E->isTypeDependent())
return NULL;
@@ -3135,7 +3138,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
V->getType()->isReferenceType() && V->hasInit()) {
// Add the reference variable to the "trail".
refVars.push_back(DR);
- return EvalAddr(V->getInit(), refVars);
+ return EvalAddr(V->getInit(), refVars, ParentDecl);
}
return NULL;
@@ -3147,7 +3150,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
UnaryOperator *U = cast<UnaryOperator>(E);
if (U->getOpcode() == UO_AddrOf)
- return EvalVal(U->getSubExpr(), refVars);
+ return EvalVal(U->getSubExpr(), refVars, ParentDecl);
else
return NULL;
}
@@ -3168,7 +3171,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
if (!Base->getType()->isPointerType()) Base = B->getRHS();
assert (Base->getType()->isPointerType());
- return EvalAddr(Base, refVars);
+ return EvalAddr(Base, refVars, ParentDecl);
}
// For conditional operators we need to see if either the LHS or RHS are
@@ -3180,7 +3183,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
if (Expr *lhsExpr = C->getLHS()) {
// In C++, we can have a throw-expression, which has 'void' type.
if (!lhsExpr->getType()->isVoidType())
- if (Expr* LHS = EvalAddr(lhsExpr, refVars))
+ if (Expr* LHS = EvalAddr(lhsExpr, refVars, ParentDecl))
return LHS;
}
@@ -3188,7 +3191,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
if (C->getRHS()->getType()->isVoidType())
return NULL;
- return EvalAddr(C->getRHS(), refVars);
+ return EvalAddr(C->getRHS(), refVars, ParentDecl);
}
case Stmt::BlockExprClass:
@@ -3200,7 +3203,8 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
return E; // address of label.
case Stmt::ExprWithCleanupsClass:
- return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+ return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
+ ParentDecl);
// For casts, we need to handle conversions from arrays to
// pointer values, and pointer-to-pointer conversions.
@@ -3224,10 +3228,10 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
- return EvalAddr(SubExpr, refVars);
+ return EvalAddr(SubExpr, refVars, ParentDecl);
case CK_ArrayToPointerDecay:
- return EvalVal(SubExpr, refVars);
+ return EvalVal(SubExpr, refVars, ParentDecl);
default:
return 0;
@@ -3237,7 +3241,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
case Stmt::MaterializeTemporaryExprClass:
if (Expr *Result = EvalAddr(
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars))
+ refVars, ParentDecl))
return Result;
return E;
@@ -3251,7 +3255,8 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
/// EvalVal - This function is complements EvalAddr in the mutual recursion.
/// See the comments for EvalAddr for more details.
-static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
+static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
+ Decl *ParentDecl) {
do {
// We should only be called for evaluating non-pointer expressions, or
// expressions with a pointer type that are not used as references but instead
@@ -3273,7 +3278,7 @@ do {
}
case Stmt::ExprWithCleanupsClass:
- return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+ return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,ParentDecl);
case Stmt::DeclRefExprClass: {
// When we hit a DeclRefExpr we are looking at code that refers to a
@@ -3281,7 +3286,11 @@ do {
// local storage within the function, and if so, return the expression.
DeclRefExpr *DR = cast<DeclRefExpr>(E);
- if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Check if it refers to itself, e.g. "int& i = i;".
+ if (V == ParentDecl)
+ return DR;
+
if (V->hasLocalStorage()) {
if (!V->getType()->isReferenceType())
return DR;
@@ -3291,9 +3300,10 @@ do {
if (V->hasInit()) {
// Add the reference variable to the "trail".
refVars.push_back(DR);
- return EvalVal(V->getInit(), refVars);
+ return EvalVal(V->getInit(), refVars, V);
}
}
+ }
return NULL;
}
@@ -3305,7 +3315,7 @@ do {
UnaryOperator *U = cast<UnaryOperator>(E);
if (U->getOpcode() == UO_Deref)
- return EvalAddr(U->getSubExpr(), refVars);
+ return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
return NULL;
}
@@ -3314,7 +3324,7 @@ do {
// Array subscripts are potential references to data on the stack. We
// retrieve the DeclRefExpr* for the array variable if it indeed
// has local storage.
- return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars);
+ return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
}
case Stmt::ConditionalOperatorClass: {
@@ -3324,10 +3334,10 @@ do {
// Handle the GNU extension for missing LHS.
if (Expr *lhsExpr = C->getLHS())
- if (Expr *LHS = EvalVal(lhsExpr, refVars))
+ if (Expr *LHS = EvalVal(lhsExpr, refVars, ParentDecl))
return LHS;
- return EvalVal(C->getRHS(), refVars);
+ return EvalVal(C->getRHS(), refVars, ParentDecl);
}
// Accesses to members are potential references to data on the stack.
@@ -3343,13 +3353,13 @@ do {
if (M->getMemberDecl()->getType()->isReferenceType())
return NULL;
- return EvalVal(M->getBase(), refVars);
+ return EvalVal(M->getBase(), refVars, ParentDecl);
}
case Stmt::MaterializeTemporaryExprClass:
if (Expr *Result = EvalVal(
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars))
+ refVars, ParentDecl))
return Result;
return E;