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.

llvm-svn: 181584
This commit is contained in:
Richard Smith 2013-05-10 04:31:10 +00:00
parent 0f7f6f1abc
commit 7500ab2464
3 changed files with 24 additions and 16 deletions

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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 {