forked from OSchip/llvm-project
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:
parent
0f7f6f1abc
commit
7500ab2464
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue