hamzasood updated this revision to Diff 110776.
hamzasood added a comment.

@rjmccall The warning is emitted, but you're right that there's no test to 
ensure that actually happens; test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp 
used Wno-c++2a-extensions to suppress the warning.

I've changed it so that checking for the warning is now part of the test.


https://reviews.llvm.org/D36572

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaLambda.cpp
  test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
  test/FixIt/fixit-cxx0x.cpp
  test/SemaCXX/cxx2a-lambda-equals-this.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===================================================================
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -777,13 +777,12 @@
 
 <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 @@
     <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>
Index: test/SemaCXX/cxx2a-lambda-equals-this.cpp
===================================================================
--- test/SemaCXX/cxx2a-lambda-equals-this.cpp
+++ test/SemaCXX/cxx2a-lambda-equals-this.cpp
@@ -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();
+  }
+};
Index: test/FixIt/fixit-cxx0x.cpp
===================================================================
--- test/FixIt/fixit-cxx0x.cpp
+++ test/FixIt/fixit-cxx0x.cpp
@@ -54,7 +54,6 @@
 
 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'}}
Index: test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
===================================================================
--- test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
@@ -8,7 +8,7 @@
     (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 @@
 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}}
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -948,17 +948,15 @@
         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_cxx1z_compat_equals_this_lambda_capture);
 
       // C++11 [expr.prim.lambda]p12:
       //   If this is captured by a local lambda expression, its nearest
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6484,8 +6484,6 @@
     "%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<
@@ -6558,6 +6556,14 @@
      InGroup<CXXPre1zCompat>, DefaultIgnore;
   def ext_star_this_lambda_capture_cxx1z : ExtWarn<
     "capture of '*this' by copy is a C++1z extension">, InGroup<CXX1z>;
+
+  // C++2a [=, this] captures.
+  def warn_cxx1z_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<
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -167,6 +167,9 @@
 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++1z-compat">;
+def CXXPre2aCompatPedantic : DiagGroup<"c++98-c++11-c++14-c++1z-compat-pedantic",
+                                       [CXXPre2aCompat]>;
 
 def CXX98CompatBindToTemporaryCopy :
   DiagGroup<"c++98-compat-bind-to-temporary-copy">;
@@ -780,6 +783,10 @@
 // earlier C++ versions.
 def CXX1z : DiagGroup<"c++1z-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]>;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to