зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
06a9d0431f
Коммит
f45c2992a3
|
@ -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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче