Closed by commit rL207682 (authored by @majnemer).

http://reviews.llvm.org/D3562

Files:
  cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
  cfe/trunk/lib/Sema/DeclSpec.cpp
  cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
  cfe/trunk/test/CXX/drs/dr4xx.cpp
  cfe/trunk/www/cxx_dr_status.html
Index: cfe/trunk/lib/Sema/DeclSpec.cpp
===================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp
+++ cfe/trunk/lib/Sema/DeclSpec.cpp
@@ -1125,14 +1125,41 @@
       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: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
===================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
@@ -14,3 +14,7 @@
 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: cfe/trunk/test/CXX/drs/dr4xx.cpp
===================================================================
--- cfe/trunk/test/CXX/drs/dr4xx.cpp
+++ cfe/trunk/test/CXX/drs/dr4xx.cpp
@@ -844,14 +844,14 @@
 
 // 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: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
@@ -69,7 +69,7 @@
 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: cfe/trunk/www/cxx_dr_status.html
===================================================================
--- cfe/trunk/www/cxx_dr_status.html
+++ cfe/trunk/www/cxx_dr_status.html
@@ -2903,7 +2903,7 @@
     <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>
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to