diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2011-06-01 07:44:31 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2011-06-01 07:44:31 +0000 |
commit | 8d7946151cd15c0e7c34250c122d59b2f5027999 (patch) | |
tree | 00b2eefc8053b9385a63bd722a451c25f25373d8 | |
parent | b68ffb107a86f5e3851e8108c712b64dd16ba258 (diff) |
Even a return statement of an expression with a dependent type in a void
function might need to clean up its temporaries. Fixes PR10057.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132390 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 43 | ||||
-rw-r--r-- | test/SemaCXX/return.cpp | 11 |
2 files changed, 34 insertions, 20 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 186136b793..00a35e1cd0 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1687,27 +1687,30 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { - if (RetValExp && !RetValExp->isTypeDependent()) { - // C99 6.8.6.4p1 (ext_ since GCC warns) - unsigned D = diag::ext_return_has_expr; - if (RetValExp->getType()->isVoidType()) - D = diag::ext_return_has_void_expr; - else { - ExprResult Result = Owned(RetValExp); - Result = IgnoredValueConversions(Result.take()); - if (Result.isInvalid()) - return StmtError(); - RetValExp = Result.take(); - RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take(); - } + if (RetValExp) { + if (!RetValExp->isTypeDependent()) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + unsigned D = diag::ext_return_has_expr; + if (RetValExp->getType()->isVoidType()) + D = diag::ext_return_has_void_expr; + else { + ExprResult Result = Owned(RetValExp); + Result = IgnoredValueConversions(Result.take()); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + RetValExp = ImpCastExprToType(RetValExp, + Context.VoidTy, CK_ToVoid).take(); + } - // return (some void expression); is legal in C++. - if (D != diag::ext_return_has_void_expr || - !getLangOptions().CPlusPlus) { - NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); - Diag(ReturnLoc, D) - << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) - << RetValExp->getSourceRange(); + // return (some void expression); is legal in C++. + if (D != diag::ext_return_has_void_expr || + !getLangOptions().CPlusPlus) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + Diag(ReturnLoc, D) + << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) + << RetValExp->getSourceRange(); + } } CheckImplicitConversions(RetValExp, ReturnLoc); diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index af7f50ce44..f83b55a6ab 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -53,3 +53,14 @@ namespace PR9328 { class foo { operator int * const (); }; + +namespace PR10057 { + struct S { + ~S(); + }; + + template <class VarType> + void Test(const VarType& value) { + return S() = value; + } +} |