From 1836e600234bc53bf0db60cbedc750ed635fd62d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 26 Jul 2013 23:45:07 +0000 Subject: [PATCH] Handle a difference in lambda return type deduction between C++11 and C++1y: if no return type is specified, C++11 will deduce a cv-qualified return type in some cases, but C++1y never will. llvm-svn: 187275 --- clang/lib/Sema/SemaStmt.cpp | 10 ++++++++-- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp | 5 ++++- clang/test/SemaCXX/lambda-expressions.cpp | 16 +++++++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7feb96f..61319d2 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2376,9 +2376,15 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return StmtError(); RetValExp = Result.take(); - if (!CurContext->isDependentContext()) + if (!CurContext->isDependentContext()) { FnRetType = RetValExp->getType(); - else + // In C++11, we take the type of the expression after decay and + // lvalue-to-rvalue conversion, so a class type can be cv-qualified. + // In C++1y, we perform template argument deduction as if the return + // type were 'auto', so an implicit return type is never cv-qualified. + if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers()) + FnRetType = FnRetType.getUnqualifiedType(); + } else FnRetType = CurCap->ReturnType = Context.DependentTy; } else { if (RetValExp) { 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 368b3f6..c69aa11 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 @@ -39,7 +39,10 @@ X infer_X_return_type_fail(X x) { if (y > 0) return X(); else - return x; // expected-error{{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}} + 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 }(5); } diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 8736afe..e8e2eb6 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s namespace std { class type_info; }; @@ -251,3 +252,16 @@ namespace PR16708 { return 0; }; } + +namespace TypeDeduction { + struct S {}; + void f() { + const S s {}; + S &&t = [&] { return s; } (); +#if __cplusplus <= 201103L + // expected-error@-2 {{drops qualifiers}} +#else + S &&u = [&] () -> auto { return s; } (); +#endif + } +} -- 2.7.4