aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2011-06-01 07:44:31 +0000
committerNick Lewycky <nicholas@mxc.ca>2011-06-01 07:44:31 +0000
commit8d7946151cd15c0e7c34250c122d59b2f5027999 (patch)
tree00b2eefc8053b9385a63bd722a451c25f25373d8
parentb68ffb107a86f5e3851e8108c712b64dd16ba258 (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.cpp43
-rw-r--r--test/SemaCXX/return.cpp11
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;
+ }
+}