]> granicus.if.org Git - clang/commitdiff
[c++2a] P0704R1: Allow pointers to const& member functions to be called on rvalues.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 25 Aug 2017 01:47:55 +0000 (01:47 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 25 Aug 2017 01:47:55 +0000 (01:47 +0000)
Patch by Blitz Rakete!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311744 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp [new file with mode: 0644]
www/cxx_status.html

index 20bfc8631c0acad4dd1bfaba11e41b20454786c1..1567d80d229f77ed59c54228c10186017282bbb6 100644 (file)
@@ -4088,6 +4088,13 @@ def err_pointer_to_member_call_drops_quals : Error<
 def err_pointer_to_member_oper_value_classify: Error<
   "pointer-to-member function type %0 can only be called on an "
   "%select{rvalue|lvalue}1">;
+def ext_pointer_to_const_ref_member_on_rvalue : Extension<
+  "invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">,
+  InGroup<CXX2a>, SFINAEFailure;
+def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning<
+  "invoking a pointer to a 'const &' member function on an rvalue is "
+  "incompatible with C++ standards before C++2a">,
+  InGroup<CXXPre2aCompatPedantic>, DefaultIgnore;
 def ext_ms_deref_template_argument: ExtWarn<
   "non-type template argument containing a dereference operation is a "
   "Microsoft extension">, InGroup<MicrosoftTemplate>;
index 4ef6df70b8e6c776918aafbcfe88ca548f992c99..456aff2fe00ed827bd4e1116ee92c63afaa6133f 100644 (file)
@@ -5175,9 +5175,16 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
       break;
 
     case RQ_LValue:
-      if (!isIndirect && !LHS.get()->Classify(Context).isLValue())
-        Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
-          << RHSType << 1 << LHS.get()->getSourceRange();
+      if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) {
+        // C++2a allows functions with ref-qualifier & if they are also 'const'.
+        if (Proto->isConst())
+          Diag(Loc, getLangOpts().CPlusPlus2a
+                        ? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue
+                        : diag::ext_pointer_to_const_ref_member_on_rvalue);
+        else
+          Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+              << RHSType << 1 << LHS.get()->getSourceRange();
+      }
       break;
 
     case RQ_RValue:
diff --git a/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp b/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp
new file mode 100644 (file)
index 0000000..06fa482
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+struct X {
+  void ref() & {}
+  void cref() const& {}
+};
+
+void test() {
+  X{}.ref(); // expected-error{{cannot initialize object parameter of type 'X' with an expression of type 'X'}}
+  X{}.cref(); // expected-no-error
+
+  (X{}.*&X::ref)(); // expected-error{{pointer-to-member function type 'void (X::*)() &' can only be called on an lvalue}}
+  (X{}.*&X::cref)(); // expected-no-error
+}
index db5a93c91adfafe5487afb6e7d3e99b3a2ec95ef..f4fb9086dd1e4182b2ab6fd15690ad6e2e2099b1 100644 (file)
@@ -802,7 +802,7 @@ as the draft C++2a standard evolves.
     <tr>
       <td><tt>const&amp;</tt>-qualified pointers to members</td>
       <td><a href="http://wg21.link/p0704r1">P0704R1</a></td>
-      <td class="none" align="center">No</td>
+      <td class="svn" align="center">SVN</td>
     </tr>
     <tr>
       <td>Allow <i>lambda-capture</i> <tt>[=, this]</tt></td>