diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-04-30 23:23:55 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-04-30 23:23:55 +0000 |
commit | e720ce7a3b1c1bfa5f7482183caa6e31fca9a3fb (patch) | |
tree | ba99317c718cc14ca0e53b0071474498d53f75af /lib/Sema/SemaChecking.cpp | |
parent | 8fba894335b979e6d213c685bca959168c1f2182 (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.cpp | 58 |
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; |