Author: efriedma Date: Fri Aug 3 15:09:44 2018 New Revision: 338931 URL: http://llvm.org/viewvc/llvm-project?rev=338931&view=rev Log: Diagnose invalid cv-qualifiers for friend decls.
Differential Revision: https://reviews.llvm.org/D45712 Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=338931&r1=338930&r2=338931&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Aug 3 15:09:44 2018 @@ -14017,6 +14017,29 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S 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. Modified: cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp?rev=338931&r1=338930&r2=338931&view=diff ============================================================================== --- cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp Fri Aug 3 15:09:44 2018 @@ -52,14 +52,25 @@ struct { // 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; Modified: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=338931&r1=338930&r2=338931&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp Fri Aug 3 15:09:44 2018 @@ -2244,22 +2244,6 @@ S2 s2; #endif #if defined(FIRST) -struct T3 {}; -struct S3 { - friend const T3; -}; -#elif defined(SECOND) -struct T3 {}; -struct S3 { - friend T3; -}; -#else -S3 s3; -// expected-error@second.h:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}} -// expected-note@first.h:* {{but in 'FirstModule' found friend 'const Friend::T3'}} -#endif - -#if defined(FIRST) struct T4 {}; struct S4 { friend T4; @@ -2292,14 +2276,12 @@ S5 s5; 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) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits