diff options
author | Michael Han <Michael.Han@autodesk.com> | 2012-11-28 23:17:40 +0000 |
---|---|---|
committer | Michael Han <Michael.Han@autodesk.com> | 2012-11-28 23:17:40 +0000 |
commit | 52b501cd723d56efe3ad2ab708c2b75530fe6caa (patch) | |
tree | f1bbfb03898dbaf7cef1687e2d22233e325e3ff2 /lib/Parse/ParseDeclCXX.cpp | |
parent | b15c8984ea300624fbbde385d3907667ce1043fa (diff) |
Implement C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains to a friend declaration, that declaration shall be a definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168826 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 700cf4e4af..bf12ee6900 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1915,8 +1915,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ColonProtectionRAIIObject X(*this); ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributesWithRange FnAttrs(AttrFactory); // Optional C++0x attribute-specifier MaybeParseCXX0XAttributes(attrs); + // We need to keep these attributes for future diagnostic + // before they are taken over by declaration specifier. + FnAttrs.addAll(attrs.getList()); + FnAttrs.Range = attrs.Range; + MaybeParseMicrosoftAttributes(attrs); if (Tok.is(tok::kw_using)) { @@ -1955,6 +1961,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); + + if (DS.isFriendSpecified()) + ProhibitAttributes(FnAttrs); + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); DS.complete(TheDecl); @@ -2023,12 +2033,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } } + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // to a friend declaration, that declaration shall be a definition. + if (DeclaratorInfo.isFunctionDeclarator() && + DefinitionKind != FDK_Definition && DS.isFriendSpecified()) { + // Diagnose attributes that appear before decl specifier: + // [[]] friend int foo(); + ProhibitAttributes(FnAttrs); + } + if (DefinitionKind) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params); ConsumeBrace(); SkipUntil(tok::r_brace, /*StopAtSemi*/false); - + // Consume the optional ';' if (Tok.is(tok::semi)) ConsumeToken(); @@ -2123,6 +2142,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *ThisDecl = 0; if (DS.isFriendSpecified()) { + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // to a friend declaration, that declaration shall be a definition. + // + // Diagnose attributes appear after friend member function declarator: + // foo [[]] (); + SmallVector<SourceRange, 4> Ranges; + DeclaratorInfo.getCXX11AttributeRanges(Ranges); + if (!Ranges.empty()) { + for (SmallVector<SourceRange, 4>::iterator I = Ranges.begin(), + E = Ranges.end(); I != E; ++I) { + Diag((*I).getBegin(), diag::err_attributes_not_allowed) + << *I; + } + } + // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); |