]> granicus.if.org Git - clang/commitdiff
Sema: Implement DR477
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 30 Apr 2014 18:24:01 +0000 (18:24 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 30 Apr 2014 18:24:01 +0000 (18:24 +0000)
Summary: Friend declarations shouldn't mention explicit or virtual.

Reviewers: rsmith

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D3562

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

include/clang/Basic/DiagnosticParseKinds.td
lib/Sema/DeclSpec.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
test/CXX/drs/dr4xx.cpp
www/cxx_dr_status.html

index 6cb7a55db43a1215516788fc6fe4444d56b3404e..335b6abf1346d5cb12f68de23f7009f145a4ffd5 100644 (file)
@@ -69,7 +69,7 @@ def err_invalid_short_spec : Error<"'short %0' is invalid">;
 def err_invalid_long_spec : Error<"'long %0' is invalid">;
 def err_invalid_longlong_spec : Error<"'long long %0' is invalid">;
 def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
-def err_friend_storage_spec : Error<"'%0' is invalid in friend declarations">;
+def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
 
 def ext_ident_list_in_param : Extension<
   "type-less parameter names in function declaration">;
index 5c2006f6e93fad5a66f218ad55ec86b4fb13d92a..69415ce34df1ca6ae9fb6f66c074b1dcef705ad3 100644 (file)
@@ -1125,14 +1125,41 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
       ThreadHint = FixItHint::CreateRemoval(SCLoc);
     }
 
-    Diag(D, SCLoc, diag::err_friend_storage_spec)
+    Diag(D, SCLoc, diag::err_friend_decl_spec)
       << SpecName << StorageHint << ThreadHint;
 
     ClearStorageClassSpecs();
   }
 
+  // C++11 [dcl.fct.spec]p5:
+  //   The virtual specifier shall be used only in the initial
+  //   declaration of a non-static class member function;
+  // C++11 [dcl.fct.spec]p6:
+  //   The explicit specifier shall be used only in the declaration of
+  //   a constructor or conversion function within its class
+  //   definition;
+  if (isFriendSpecified() && (isVirtualSpecified() || isExplicitSpecified())) {
+    StringRef Keyword;
+    SourceLocation SCLoc;
+
+    if (isVirtualSpecified()) {
+      Keyword = "virtual";
+      SCLoc = getVirtualSpecLoc();
+    } else {
+      Keyword = "explicit";
+      SCLoc = getExplicitSpecLoc();
+    }
+
+    FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
+    Diag(D, SCLoc, diag::err_friend_decl_spec)
+      << Keyword << Hint;
+
+    FS_virtual_specified = FS_explicit_specified = false;
+    FS_virtualLoc = FS_explicitLoc = SourceLocation();
+  }
+
   assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
+
   // Okay, now we can infer the real type.
 
   // TODO: return "auto function" and other bad things based on the real type.
index ee870d9601614c4a34e23b10bf9955859976d6b7..5d1e6fb85ce9c40506b4858c63cf84b267c09774 100644 (file)
@@ -14,3 +14,7 @@ public:
 explicit A::A() { } // expected-error {{'explicit' can only be specified inside the class definition}}
 explicit A::operator bool() { return false; }  // expected-warning {{explicit conversion functions are a C++11 extension}}\
                                                // expected-error {{'explicit' can only be specified inside the class definition}}
+
+class B {
+  friend explicit A::A(); // expected-error {{'explicit' is invalid in friend declarations}}
+};
index de85aea1c9de6f5fc6418e371acf793bfc79e364..726c67e2da04f8d55aa78f4e66e433fa2c1dbf15 100644 (file)
@@ -844,14 +844,14 @@ namespace dr474 { // dr474: yes
 
 // dr475 FIXME write a codegen test
 
-namespace dr477 { // dr477: no
+namespace dr477 { // dr477: 3.5
   struct A {
     explicit A();
     virtual void f();
   };
   struct B {
-    friend explicit A::A(); // FIXME: reject this
-    friend virtual void A::f(); // FIXME: reject this
+    friend explicit A::A(); // expected-error {{'explicit' is invalid in friend declarations}}
+    friend virtual void A::f(); // expected-error {{'virtual' is invalid in friend declarations}}
   };
   explicit A::A() {} // expected-error {{can only be specified inside the class definition}}
   virtual void A::f() {} // expected-error {{can only be specified inside the class definition}}
index 1ada70c70225de5c5ef542e8c2b4be8e0b6c383a..dc6339982c877cce60eef1e312c9343f4d8ed1bb 100644 (file)
@@ -2903,7 +2903,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#477">477</a></td>
     <td>CD1</td>
     <td>Can <TT>virtual</TT> appear in a <TT>friend</TT> declaration?</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="478">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#478">478</a></td>