diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-26 06:47:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-26 06:47:28 +0000 |
commit | d85bea2affdd59d83d1be7d24b97f436484c3625 (patch) | |
tree | c54ffce5ad16d80e08ccbb6ebfd047206c93ac1a /lib/Parse/ParseDeclCXX.cpp | |
parent | 74e3c92aa3eb1750ac2eb89994046eb69db39100 (diff) |
Rework the Parse-Sema interaction for friends to better support friend
class templates. We now treat friend class templates much more like
normal class templates, except that they still get special name lookup
rules. Fixes PR5057 and eliminates a bunch of spurious diagnostics in
<iostream>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82848 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 59a6e6281c..bcf332bf30 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -624,9 +624,22 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // 'struct foo :...' then this is a definition. Otherwise we have // something like 'struct foo xyz', a reference. Action::TagUseKind TUK; - if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) - TUK = Action::TUK_Definition; - else if (Tok.is(tok::semi)) + if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) { + if (DS.isFriendSpecified()) { + // C++ [class.friend]p2: + // A class shall not be defined in a friend declaration. + Diag(Tok.getLocation(), diag::err_friend_decl_defines_class) + << SourceRange(DS.getFriendSpecLoc()); + + // Skip everything up to the semicolon, so that this looks like a proper + // friend class (or template thereof) declaration. + SkipUntil(tok::semi, true, true); + TUK = Action::TUK_Friend; + } else { + // Okay, this is a class definition. + TUK = Action::TUK_Definition; + } + } else if (Tok.is(tok::semi)) TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration; else TUK = Action::TUK_Reference; @@ -1043,12 +1056,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); - - if (DS.isFriendSpecified()) { - Actions.ActOnFriendTypeDecl(CurScope, DS, move(TemplateParams)); - } else - Actions.ParsedFreeStandingDeclSpec(CurScope, DS); - + Actions.ParsedFreeStandingDeclSpec(CurScope, DS); return; } |