Author: faisalv Date: Fri Aug 18 20:43:07 2017 New Revision: 311224 URL: http://llvm.org/viewvc/llvm-project?rev=311224&view=rev Log: [c++2a] Implement P0409R2 - Allow lambda capture [=,this] (by hamzasood)
This patch, by hamzasood, implements P0409R2, and allows [=, this] pre-C++2a as an extension (with appropriate warnings) for consistency. https://reviews.llvm.org/D36572 Thanks Hamza! Added: cfe/trunk/test/SemaCXX/cxx2a-lambda-equals-this.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp cfe/trunk/test/FixIt/fixit-cxx0x.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Aug 18 20:43:07 2017 @@ -168,6 +168,9 @@ def CXXPre14CompatPedantic : DiagGroup<" def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">; def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", [CXXPre1zCompat]>; +def CXXPre2aCompat : DiagGroup<"c++98-c++11-c++14-c++17-compat">; +def CXXPre2aCompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", + [CXXPre2aCompat]>; def CXX98CompatBindToTemporaryCopy : DiagGroup<"c++98-compat-bind-to-temporary-copy">; @@ -784,6 +787,10 @@ def CXX14 : DiagGroup<"c++14-extensions" // earlier C++ versions. def CXX17 : DiagGroup<"c++17-extensions">; +// A warning group for warnings about using C++2a features as extensions in +// earlier C++ versions. +def CXX2a : DiagGroup<"c++2a-extensions">; + def : DiagGroup<"c++0x-extensions", [CXX11]>; def : DiagGroup<"c++1y-extensions", [CXX14]>; def : DiagGroup<"c++1z-extensions", [CXX17]>; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Aug 18 20:43:07 2017 @@ -6470,8 +6470,6 @@ let CategoryName = "Lambda Issue" in { "%0 can appear only once in a capture list">; def err_reference_capture_with_reference_default : Error< "'&' cannot precede a capture when the capture default is '&'">; - def err_this_capture_with_copy_default : Error< - "'this' cannot be explicitly captured when the capture default is '='">; def err_copy_capture_with_copy_default : Error< "'&' must precede a capture when the capture default is '='">; def err_capture_does_not_name_variable : Error< @@ -6544,6 +6542,14 @@ let CategoryName = "Lambda Issue" in { InGroup<CXXPre1zCompat>, DefaultIgnore; def ext_star_this_lambda_capture_cxx17 : ExtWarn< "capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>; + + // C++2a [=, this] captures. + def warn_cxx17_compat_equals_this_lambda_capture : Warning< + "explicit capture of 'this' with a capture default of '=' is incompatible " + "with C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore; + def ext_equals_this_lambda_capture_cxx2a : ExtWarn< + "explicit capture of 'this' with a capture default of '=' " + "is a C++2a extension">, InGroup<CXX2a>; } def err_return_in_captured_stmt : Error< Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Aug 18 20:43:07 2017 @@ -948,17 +948,15 @@ void Sema::ActOnStartOfLambdaDefinition( continue; } - // C++1z [expr.prim.lambda]p8: - // If a lambda-capture includes a capture-default that is =, each - // simple-capture of that lambda-capture shall be of the form "& - // identifier" or "* this". [ Note: The form [&,this] is redundant but - // accepted for compatibility with ISO C++14. --end note ] - if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) { - Diag(C->Loc, diag::err_this_capture_with_copy_default) - << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); - continue; - } + // C++2a [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is =, + // each simple-capture of that lambda-capture shall be of the form + // "&identifier", "this", or "* this". [ Note: The form [&,this] is + // redundant but accepted for compatibility with ISO C++14. --end note ] + if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) + Diag(C->Loc, !getLangOpts().CPlusPlus2a + ? diag::ext_equals_this_lambda_capture_cxx2a + : diag::warn_cxx17_compat_equals_this_lambda_capture); // C++11 [expr.prim.lambda]p12: // If this is captured by a local lambda expression, its nearest Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp Fri Aug 18 20:43:07 2017 @@ -8,7 +8,7 @@ class X0 { (void)[this, this] () {}; // expected-error {{'this' can appear only once}} (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}} (void)[=, &foo] () {}; - (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}} + (void)[=, this] () {}; // expected-warning {{C++2a extension}} (void)[&, foo] () {}; (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} (void)[&, this] () {}; @@ -23,7 +23,7 @@ struct S2 { void S2::f(int i) { (void)[&, i]{ }; (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}} - (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}} + (void)[=, this]{ }; // expected-warning{{C++2a extension}} (void)[=]{ this->g(i); }; (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} (void)[i(0), i(1)]{ }; // expected-error{{'i' can appear only once in a capture list}} Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original) +++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Fri Aug 18 20:43:07 2017 @@ -54,7 +54,6 @@ struct S2 { void S2::f(int i) { (void)[&, &i, &i]{}; // expected-error 2{{'&' cannot precede a capture when the capture default is '&'}} - (void)[=, this]{ this->g(5); }; // expected-error{{'this' cannot be explicitly captured}} (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}} Added: cfe/trunk/test/SemaCXX/cxx2a-lambda-equals-this.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-lambda-equals-this.cpp?rev=311224&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/cxx2a-lambda-equals-this.cpp (added) +++ cfe/trunk/test/SemaCXX/cxx2a-lambda-equals-this.cpp Fri Aug 18 20:43:07 2017 @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s +// expected-no-diagnostics + +// This test does two things. +// Deleting the copy constructor ensures that an [=, this] capture doesn't copy the object. +// Accessing a member variable from the lambda ensures that the capture actually works. +class A { + A(const A &) = delete; + int i; + + void func() { + auto L = [=, this]() -> int { return i; }; + L(); + } +}; Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=311224&r1=311223&r2=311224&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Fri Aug 18 20:43:07 2017 @@ -777,13 +777,12 @@ code. This issue is expected to be recti <h2 id="cxx20">C++2a implementation status</h2> -<p>Clang does not yet support any of the proposed features of -<!--<p>Clang has <b>experimental</b> support for some proposed features of--> +<p>Clang has <b>experimental</b> support for some proposed features of the C++ standard following C++17, provisionally named C++2a. Note that support for these features may change or be removed without notice, as the draft C++2a standard evolves. -<!--<p>You can use Clang in C++2a mode with the <code>-std=c++2a</code> option.</p>--> +<p>You can use Clang in C++2a mode with the <code>-std=c++2a</code> option.</p> <details open> <summary>List of features and minimum Clang version with support</summary> @@ -808,7 +807,7 @@ as the draft C++2a standard evolves. <tr> <td>Allow <i>lambda-capture</i> <tt>[=, this]</tt></td> <td><a href="http://wg21.link/p0409r2">P0409R2</a></td> - <td class="none" align="center">No</td> + <td class="svn" align="center">SVN</td> </tr> <tr> <td><tt>__VA_OPT__</tt> for preprocessor comma elision</td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits