diff options
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 31 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 4 | ||||
| -rw-r--r-- | clang/test/SemaCXX/cxx1y-deduced-return-type.cpp | 5 |
3 files changed, 24 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a50b5e7c7ff..d14b10559d9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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<AutoType>()) { - 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<AutoType>()) { + 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<FunctionProtoTypeLoc>().getResultLoc(); + Context.adjustDeducedFunctionResultType( + FD, SubstAutoType(ResultType.getType(), Context.VoidTy)); } } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 248665ac86c..b5ff7a30a9e 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/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<int>'. + // FIXME: Unify this and C++1y auto function handling. if (isa<CapturingScopeInfo>(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); diff --git a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp index f0146f88d68..eb6f6aaf9bc 100644 --- a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/clang/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 { |

