C++1y: provide full 'auto' return type deduction for lambda expressions. This

completes the implementation of N3638.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181669 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2013-05-12 03:09:35 +00:00
Родитель 06a9d0431f
Коммит f45c2992a3
8 изменённых файлов: 58 добавлений и 8 удалений

Просмотреть файл

@ -852,7 +852,6 @@ Use ``__has_feature(cxx_return_type_deduction)`` or
``__has_extension(cxx_return_type_deduction)`` to determine if support
for return type deduction for functions (using ``auto`` as a return type)
is enabled.
Clang's implementation of this feature is incomplete.
C++1y runtime-sized arrays
^^^^^^^^^^^^^^^^^^^^^^^^^^

Просмотреть файл

@ -798,7 +798,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
//.Case("cxx_generalized_capture", LangOpts.CPlusPlus1y)
//.Case("cxx_generic_lambda", LangOpts.CPlusPlus1y)
//.Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus1y)
//.Case("cxx_return_type_deduction", LangOpts.CPlusPlus1y)
.Case("cxx_return_type_deduction", LangOpts.CPlusPlus1y)
//.Case("cxx_runtime_array", LangOpts.CPlusPlus1y)
.Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus1y)
//.Case("cxx_variable_templates", LangOpts.CPlusPlus1y)

Просмотреть файл

@ -2362,22 +2362,37 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
StmtResult
Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If this is the first return we've seen, infer the return type.
// [expr.prim.lambda]p4 in C++11; block literals follow a superset of those
// rules which allows multiple return statements.
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
QualType FnRetType = CurCap->ReturnType;
// For blocks/lambdas with implicit return types, we check each return
// statement individually, and deduce the common return type when the block
// or lambda is completed.
if (CurCap->HasImplicitReturnType) {
if (AutoType *AT =
FnRetType.isNull() ? 0 : FnRetType->getContainedAutoType()) {
// In C++1y, the return type may involve 'auto'.
FunctionDecl *FD = cast<LambdaScopeInfo>(CurCap)->CallOperator;
if (CurContext->isDependentContext()) {
// C++1y [dcl.spec.auto]p12:
// Return type deduction [...] occurs when the definition is
// instantiated even if the function body contains a return
// statement with a non-type-dependent operand.
CurCap->ReturnType = FnRetType = Context.DependentTy;
} else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
return StmtError();
} else
CurCap->ReturnType = FnRetType = FD->getResultType();
} else if (CurCap->HasImplicitReturnType) {
// FIXME: Fold this into the 'auto' codepath above.
if (RetValExp && !isa<InitListExpr>(RetValExp)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
if (Result.isInvalid())
return StmtError();
RetValExp = Result.take();
if (!RetValExp->isTypeDependent())
if (!CurContext->isDependentContext())
FnRetType = RetValExp->getType();
else
FnRetType = CurCap->ReturnType = Context.DependentTy;
@ -2553,7 +2568,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
// FIXME: Unify this and C++1y auto function handling.
if (isa<CapturingScopeInfo>(getCurFunction()))
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);

Просмотреть файл

@ -0,0 +1,17 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
// RUN: %clang_cc1 -std=c++1y -verify %s
template<typename T> struct S { typedef int type; };
template<typename T> void f() {
auto x = [] { return 0; } ();
// FIXME: We should be able to produce a 'missing typename' diagnostic here.
S<decltype(x)>::type n; // expected-error 2{{}}
}
#if __cplusplus > 201103L
template<typename T> void g() {
auto x = [] () -> auto { return 0; } ();
S<decltype(x)>::type n; // expected-error 2{{}}
}
#endif

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
int a;
int &b = [] (int &r) -> decltype(auto) { return r; } (a);
int &c = [] (int &r) -> decltype(auto) { return (r); } (a);
int &d = [] (int &r) -> auto & { return r; } (a);
int &e = [] (int &r) -> auto { return r; } (a); // expected-error {{cannot bind to a temporary}}
int &f = [] (int r) -> decltype(auto) { return r; } (a); // expected-error {{cannot bind to a temporary}}
int &g = [] (int r) -> decltype(auto) { return (r); } (a); // expected-warning {{reference to stack}}

Просмотреть файл

@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
void missing_lambda_declarator() {
[](){}();

Просмотреть файл

@ -346,3 +346,13 @@ int no_aggregate_nsdmi();
// CHECK-1Y: has_aggregate_nsdmi
// CHECK-11: no_aggregate_nsdmi
// CHECK-NO-11: no_aggregate_nsdmi
#if __has_feature(cxx_return_type_deduction)
int has_return_type_deduction();
#else
int no_return_type_deduction();
#endif
// CHECK-1Y: has_return_type_deduction
// CHECK-11: no_return_type_deduction
// CHECK-NO-11: no_return_type_deduction

Просмотреть файл

@ -431,7 +431,7 @@ available.</p>
</tr>
<tr>
<td>Return type deduction for normal functions</td>
<td class="partial" align="center">Partial</td>
<td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Runtime-sized arrays with automatic storage duration</td>