"friends can only be classes or functions">;
def err_friend_is_member : Error<
"friends cannot be members of the declaring class">;
+def extwarn_friend_inner_class : ExtWarn<
+ "C++ 98 does not allow inner classes as friends">;
def err_unelaborated_friend_type : Error<
"must specify '%select{class|union}0' in a friend "
"%select{class|union}0 declaration">;
Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
<< RD->getSourceRange();
- // C++ [class.friend]p1: A friend of a class is a function or
- // class that is not a member of the class . . .
- // Definitions currently get treated in a way that causes this
- // error, so only report it if we didn't see a definition.
- else if (RD->getDeclContext() == CurContext)
- Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+ // C++98 [class.friend]p1: A friend of a class is a function
+ // or class that is not a member of the class . . .
+ // But that's a silly restriction which nobody implements for
+ // inner classes, and C++0x removes it anyway, so we only report
+ // this
+ // But no-one implements it that way, and C++0x removes this
+ // restriction, so we only report it (as a warning) if we're being
+ // pedantic. Ideally this would real -pedantic mode
+ //
+ // Also, definitions currently get treated in a way that causes
+ // this error, so only report it if we didn't see a definition.
+ else if (RD->getDeclContext() == CurContext &&
+ !(getLangOptions().CPlusPlus0x || getLangOptions().GNUMode))
+ Diag(DS.getFriendSpecLoc(), diag::extwarn_friend_inner_class);
return DeclPtrTy::make(RD);
}
// C++ [class.friend]p1: A friend of a class is a function or
// class that is not a member of the class . . .
- if (FD && DC == CurContext)
+ // C++0x changes this for both friend types and functions.
+ // Most C++ 98 compilers do seem to give an error here, so
+ // we do, too.
+ if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
}
void a_member();
friend void A::a_member(); // expected-error {{ friends cannot be members of the declaring class }}
friend void a_member(); // okay (because we ignore class scopes when looking up friends)
- friend class A::AInner; // expected-error {{ friends cannot be members of the declaring class }}
- friend class AInner; // expected-error {{ friends cannot be members of the declaring class }}
+ friend class A::AInner; // this is okay as an extension
+ friend class AInner; // okay, refers to ::AInner
friend void Derived::missing_member(); // expected-error {{ no function named 'missing_member' with type 'void ()' was found in the specified scope }}