From 25d8c856681120581315edcdb48257c99af6b45c Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 10 May 2013 04:31:10 +0000 Subject: [PATCH] C++1y auto return type: when a function contains no 'return' statements at all, substitute 'void' into the return type rather than replacing it with 'void', so that we maintain the 'auto' type sugar. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181584 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 31 +++++++++++++--------- lib/Sema/SemaStmt.cpp | 4 +-- test/SemaCXX/cxx1y-deduced-return-type.cpp | 5 ++++ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a50b5e7c7f..d14b10559d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8849,7 +8849,9 @@ bool Sema::canSkipFunctionBody(Decl *D) { // We cannot skip the body of a function (or function template) which is // constexpr, since we may need to evaluate its body in order to parse the // rest of the file. - return !FD->isConstexpr(); + // We cannot skip the body of a function with an undeduced return type, + // because any callers of that function need to know the type. + return !FD->isConstexpr() && !FD->getResultType()->isUndeducedType(); } Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { @@ -8879,18 +8881,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); - if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && - !FD->isDependentContext()) { - if (FD->getResultType()->isUndeducedType()) { - // If the function has a deduced result type but contains no 'return' - // statements, the result type as written must be exactly 'auto', and - // the deduced result type is 'void'. - if (!FD->getResultType()->getAs()) { - Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto) - << FD->getResultType(); - FD->setInvalidDecl(); - } - Context.adjustDeducedFunctionResultType(FD, Context.VoidTy); + if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body && + !FD->isDependentContext() && FD->getResultType()->isUndeducedType()) { + // If the function has a deduced result type but contains no 'return' + // statements, the result type as written must be exactly 'auto', and + // the deduced result type is 'void'. + if (!FD->getResultType()->getAs()) { + Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto) + << FD->getResultType(); + FD->setInvalidDecl(); + } else { + // Substitute 'void' for the 'auto' in the type. + TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc(). + IgnoreParens().castAs().getResultLoc(); + Context.adjustDeducedFunctionResultType( + FD, SubstAutoType(ResultType.getType(), Context.VoidTy)); } } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 248665ac86..b5ff7a30a9 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2553,9 +2553,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); - // FIXME: Unify this and C++1y auto function handling. In particular, we - // should allow 'return { 1, 2, 3 };' in a lambda to deduce - // 'std::initializer_list'. + // FIXME: Unify this and C++1y auto function handling. if (isa(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index f0146f88d6..eb6f6aaf9b 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -295,7 +295,12 @@ namespace NoReturn { auto f() {} void (*p)() = &f; + auto f(); // ok + auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} + + auto h() = delete; // expected-note {{explicitly deleted}} + auto x = h(); // expected-error {{call to deleted}} } namespace UseBeforeComplete { -- 2.40.0