summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--clang/lib/Sema/DeclSpec.cpp31
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp4
-rw-r--r--clang/test/CXX/drs/dr4xx.cpp6
-rw-r--r--clang/www/cxx_dr_status.html2
5 files changed, 38 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 6cb7a55db43..335b6abf134 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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">;
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 5c2006f6e93..69415ce34df 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -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.
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
index ee870d96016..5d1e6fb85ce 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp
@@ -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}}
+};
diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index de85aea1c9d..726c67e2da0 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -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}}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 1ada70c7022..dc6339982c8 100644
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -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>
OpenPOWER on IntegriCloud