aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorMichael Han <Michael.Han@autodesk.com>2012-11-28 23:17:40 +0000
committerMichael Han <Michael.Han@autodesk.com>2012-11-28 23:17:40 +0000
commit52b501cd723d56efe3ad2ab708c2b75530fe6caa (patch)
treef1bbfb03898dbaf7cef1687e2d22233e325e3ff2 /lib/Parse/ParseDeclCXX.cpp
parentb15c8984ea300624fbbde385d3907667ce1043fa (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.cpp36
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);