DR1048: drop top-level cv-qualifiers when deducing the return type of a

lambda-expression in C++11, to match the C++14 rules.

llvm-svn: 224620
This commit is contained in:
Richard Smith 2014-12-19 22:10:51 +00:00
parent 86a7f71549
commit 5a0e50cd87
6 changed files with 34 additions and 12 deletions

View File

@ -617,7 +617,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// If it was ever a placeholder, it had to been deduced to DependentTy.
assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
// C++ Core Issue #975, proposed resolution:
// C++ core issue 975:
// If a lambda-expression does not include a trailing-return-type,
// it is as if the trailing-return-type denotes the following type:
// - if there are no return statements in the compound-statement,
@ -631,6 +631,10 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// same, that common type;
// - otherwise, the program is ill-formed.
//
// C++ core issue 1048 additionally removes top-level cv-qualifiers
// from the types of returned expressions to match the C++14 auto
// deduction rules.
//
// In addition, in blocks in non-C++ modes, if all of the return
// statements are enumerator-like expressions of some type T, where
// T has a name for linkage, then we infer the return type of the
@ -679,7 +683,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
const ReturnStmt *RS = *I;
const Expr *RetE = RS->getRetValue();
QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy);
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.hasSameType(ReturnType, CSI.ReturnType))
continue;

View File

@ -2652,8 +2652,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
return StmtError();
RetValExp = Result.get();
// DR1048: even prior to C++14, we should use the 'auto' deduction rules
// when deducing a return type for a lambda-expression (or by extension
// for a block). These rules differ from the stated C++11 rules only in
// that they remove top-level cv-qualifiers.
if (!CurContext->isDependentContext())
FnRetType = RetValExp->getType();
FnRetType = RetValExp->getType().getUnqualifiedType();
else
FnRetType = CurCap->ReturnType = Context.DependentTy;
} else {

View File

@ -14,6 +14,24 @@ namespace std {
};
}
namespace dr1048 { // dr1048: 3.6
struct A {};
const A f();
A g();
typedef const A CA;
#if __cplusplus >= 201103L
// ok: we deduce non-const A in each case.
A &&a = [] (int n) {
while (1) switch (n) {
case 0: return f();
case 1: return g();
case 2: return A();
case 3: return CA();
}
} (0);
#endif
}
namespace dr1070 { // dr1070: 3.5
#if __cplusplus >= 201103L
struct A {

View File

@ -34,15 +34,12 @@ X infer_X_return_type(X x) {
}(5);
}
X infer_X_return_type_fail(X x) {
X infer_X_return_type_2(X x) {
return [x](int y) {
if (y > 0)
return X();
else
return x;
#if __cplusplus <= 201103L
// expected-error@-2 {{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}}
#endif
return x; // ok even in c++11, per dr1048.
}(5);
}

View File

@ -258,9 +258,7 @@ namespace TypeDeduction {
void f() {
const S s {};
S &&t = [&] { return s; } ();
#if __cplusplus <= 201103L
// expected-error@-2 {{drops qualifiers}}
#else
#if __cplusplus > 201103L
S &&u = [&] () -> auto { return s; } ();
#endif
}

View File

@ -6103,7 +6103,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1048">1048</a></td>
<td>CD3</td>
<td><TT>auto</TT> deduction and lambda return type deduction.</td>
<td class="none" align="center">Unknown</td>
<td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="1049">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1049">1049</a></td>