diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-11-29 22:32:08 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-11-29 22:32:08 +0000 |
commit | 8b2f01b56209f4bb7331292225c5300753880044 (patch) | |
tree | a6e0d0ab791aa98f093c1c93de470eb30acb1bdd /lib/Sema/SemaChecking.cpp | |
parent | 08e41a656575ee63f8eefc7805493055c645fa85 (diff) |
Emit warnings if we are returning a reference to a local temporary.
The issue was brought to our attention by Matthieu Monrocq.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120331 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index ed45de53f2..807a550750 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1787,11 +1787,35 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, << ALE->getSourceRange(); } else if (lhsType->isReferenceType()) { + // Perform checking for local temporaries returned by reference. + if (RetValExp->Classify(Context).isPRValue()) { + Diag(RetValExp->getLocStart(), diag::warn_ret_local_temp_ref) + << RetValExp->getSourceRange(); + return; + } + // Perform checking for stack values returned by reference. // Check for a reference to the stack - if (DeclRefExpr *DR = EvalVal(RetValExp)) + if (DeclRefExpr *DR = EvalVal(RetValExp)) { + const VarDecl *VD = cast<VarDecl>(DR->getDecl()); + // Check for returning reference variable that binds to temporary. + if (VD->getType()->isReferenceType()) { + if (const Expr *init = VD->getInit()) + if (init->Classify(Context).isPRValue()) { + Diag(DR->getLocStart(), diag::warn_ret_local_temp_var_ref) + << VD->getDeclName() << RetValExp->getSourceRange(); + Diag(VD->getLocation(), diag::note_local_temp_var_ref) + << VD->getDeclName() << VD->getInit()->getSourceRange(); + } + + // When returning a reference variable that doesn't bind to temporary, + // no warning. + return; + } + Diag(DR->getLocStart(), diag::warn_ret_stack_ref) - << DR->getDecl()->getDeclName() << RetValExp->getSourceRange(); + << VD->getDeclName() << RetValExp->getSourceRange(); + } } } @@ -1953,7 +1977,7 @@ do { DeclRefExpr *DR = cast<DeclRefExpr>(E); if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) - if (V->hasLocalStorage() && !V->getType()->isReferenceType()) return DR; + if (V->hasLocalStorage()) return DR; return NULL; } |