[cfe-commits] r155856 - in /cfe/trunk: lib/Sema/SemaChecking.cpp test/Analysis/stack-addr-ps.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Mon Apr 30 16:23:55 PDT 2012
Author: akirtzidis
Date: Mon Apr 30 18:23:55 2012
New Revision: 155856
URL: http://llvm.org/viewvc/llvm-project?rev=155856&view=rev
Log:
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
Modified:
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/Analysis/stack-addr-ps.cpp
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=155856&r1=155855&r2=155856&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Apr 30 18:23:55 2012
@@ -3017,8 +3017,10 @@
//===--- 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 @@
// 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 @@
/// * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
case Stmt::MaterializeTemporaryExprClass:
if (Expr *Result = EvalAddr(
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
- refVars))
+ refVars, ParentDecl))
return Result;
return E;
@@ -3251,7 +3255,8 @@
/// 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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;
Modified: cfe/trunk/test/Analysis/stack-addr-ps.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-addr-ps.cpp?rev=155856&r1=155855&r2=155856&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/stack-addr-ps.cpp (original)
+++ cfe/trunk/test/Analysis/stack-addr-ps.cpp Mon Apr 30 18:23:55 2012
@@ -84,3 +84,9 @@
return x;
}
};
+
+// rdar://11345441
+int* f5() {
+ int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-note {{binding reference variable 'i' here}}
+ return &i; // expected-warning {{address of stack memory associated with local variable 'i' returned}}
+}
More information about the cfe-commits
mailing list