Sema: Implement DR477

Summary: Friend declarations shouldn't mention explicit or virtual.

Reviewers: rsmith

Subscribers: cfe-commits

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

llvm-svn: 207682
This commit is contained in:
David Majnemer 2014-04-30 18:24:01 +00:00
parent d94f2f16bd
commit deca705593
5 changed files with 38 additions and 7 deletions

View 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">;

View 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.

View 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}}
};

View 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}}

View 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>