From 5a0e50cd87840b9f326e88d3b35c04c3c3b4c76b Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 19 Dec 2014 22:10:51 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/SemaLambda.cpp | 9 +++++++-- clang/lib/Sema/SemaStmt.cpp | 6 +++++- clang/test/CXX/drs/dr10xx.cpp | 18 ++++++++++++++++++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp | 7 ++----- clang/test/SemaCXX/lambda-expressions.cpp | 4 +--- clang/www/cxx_dr_status.html | 2 +- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index a64a0fb..90a81f4 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -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; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a3fd6fa..f487752 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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 { diff --git a/clang/test/CXX/drs/dr10xx.cpp b/clang/test/CXX/drs/dr10xx.cpp index 733621d..a1d7ef6 100644 --- a/clang/test/CXX/drs/dr10xx.cpp +++ b/clang/test/CXX/drs/dr10xx.cpp @@ -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 { diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp index 1016cb1..a36175a 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -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); } diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 6220895..cad322a 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -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 } diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 4645e52..d8dc9bc 100644 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -6103,7 +6103,7 @@ and POD class 1048 CD3 auto deduction and lambda return type deduction. - Unknown + SVN 1049 -- 2.7.4