efriedma updated this revision to Diff 154707.
efriedma edited the summary of this revision.
efriedma added a comment.
Move declspec checks before call to GetTypeForDeclarator, since it can fail for
class templates.
Repository:
rC Clang
https://reviews.llvm.org/D45712
Files:
lib/Sema/SemaDeclCXX.cpp
test/CXX/class.access/class.friend/p3-cxx0x.cpp
test/Modules/odr_hash.cpp
Index: test/Modules/odr_hash.cpp
===================================================================
--- test/Modules/odr_hash.cpp
+++ test/Modules/odr_hash.cpp
@@ -2048,22 +2048,6 @@
#endif
#if defined(FIRST)
-struct T3 {};
-struct S3 {
- friend const T3;
-};
-#elif defined(SECOND)
-struct T3 {};
-struct S3 {
- friend T3;
-};
-#else
-S3 s3;
-// [email protected]:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}}
-// [email protected]:* {{but in 'FirstModule' found friend 'const Friend::T3'}}
-#endif
-
-#if defined(FIRST)
struct T4 {};
struct S4 {
friend T4;
@@ -2096,14 +2080,12 @@
friend class FriendA; \
friend struct FriendB; \
friend FriendC; \
- friend const FriendD; \
friend void Function();
#if defined(FIRST) || defined(SECOND)
class FriendA {};
class FriendB {};
class FriendC {};
-class FriendD {};
#endif
#if defined(FIRST) || defined(SECOND)
Index: test/CXX/class.access/class.friend/p3-cxx0x.cpp
===================================================================
--- test/CXX/class.access/class.friend/p3-cxx0x.cpp
+++ test/CXX/class.access/class.friend/p3-cxx0x.cpp
@@ -52,14 +52,25 @@
// Ill-formed
int friend; // expected-error {{'friend' must appear first in a non-function declaration}}
unsigned friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
- const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
+ const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}} \
+ // expected-error {{'const' is invalid in friend declarations}} \
+ // expected-error {{'volatile' is invalid in friend declarations}}
int
friend; // expected-error {{'friend' must appear first in a non-function declaration}}
+ friend const int; // expected-error {{'const' is invalid in friend declarations}}
+ friend volatile int; // expected-error {{'volatile' is invalid in friend declarations}}
+ template <typename T> friend const class X; // expected-error {{'const' is invalid in friend declarations}}
+ // C++ doesn't have restrict and _Atomic, but they're both the same sort
+ // of qualifier.
+ typedef int *PtrToInt;
+ friend __restrict PtrToInt; // expected-error {{'restrict' is invalid in friend declarations}} \
+ // expected-error {{restrict requires a pointer or reference}}
+ friend _Atomic int; // expected-error {{'_Atomic' is invalid in friend declarations}}
// OK
int friend foo(void);
+ const int friend foo2(void);
friend int;
- friend const volatile int;
friend
float;
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -14035,6 +14035,29 @@
assert(DS.isFriendSpecified());
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+ // C++ [class.friend]p3:
+ // A friend declaration that does not declare a function shall have one of
+ // the following forms:
+ // friend elaborated-type-specifier ;
+ // friend simple-type-specifier ;
+ // friend typename-specifier ;
+ //
+ // Any declaration with a type qualifier does not have that form. (It's
+ // legal to specify a qualified type as a friend, you just can't write the
+ // keywords.)
+ if (DS.getTypeQualifiers()) {
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+ Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+ Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(), diag::err_friend_decl_spec) << "_Atomic";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)
+ Diag(DS.getUnalignedSpecLoc(), diag::err_friend_decl_spec) << "__unaligned";
+ }
+
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits