Implement C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains to a friend declaration, that declaration shall be a definition.
llvm-svn: 168826
This commit is contained in:
parent
998f0a3360
commit
ddc016d4d7
|
@ -1897,6 +1897,17 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// \brief Return a source range list of C++11 attributes associated
|
||||
/// with the declarator.
|
||||
void getCXX11AttributeRanges(SmallVector<SourceRange, 4> &Ranges) {
|
||||
AttributeList *AttrList = Attrs.getList();
|
||||
while (AttrList) {
|
||||
if (AttrList->isCXX0XAttribute())
|
||||
Ranges.push_back(AttrList->getRange());
|
||||
AttrList = AttrList->getNext();
|
||||
}
|
||||
}
|
||||
|
||||
void setAsmLabel(Expr *E) { AsmLabel = E; }
|
||||
Expr *getAsmLabel() const { return AsmLabel; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -151,10 +151,16 @@ enum struct [[]] E5;
|
|||
|
||||
struct S {
|
||||
friend int f [[]] (); // expected-FIXME{{an attribute list cannot appear here}}
|
||||
[[]] friend int g(); // expected-FIXME{{an attribute list cannot appear here}}
|
||||
friend int f1 [[noreturn]] (); //expected-error{{an attribute list cannot appear here}}
|
||||
friend int f2 [[]] [[noreturn]] () {}
|
||||
[[]] friend int g(); // expected-error{{an attribute list cannot appear here}}
|
||||
[[]] friend int h() {
|
||||
}
|
||||
[[]] friend int f3(), f4(), f5(); // expected-error{{an attribute list cannot appear here}}
|
||||
friend int f6 [[noreturn]] (), f7 [[noreturn]] (), f8 [[noreturn]] (); // expected-error3 {{an attribute list cannot appear here}}
|
||||
friend class [[]] C; // expected-error{{an attribute list cannot appear here}}
|
||||
[[]] friend class D; // expected-error{{an attribute list cannot appear here}}
|
||||
[[]] friend int; // expected-error{{an attribute list cannot appear here}}
|
||||
};
|
||||
template<typename T> void tmpl(T) {}
|
||||
template void tmpl [[]] (int); // expected-FIXME {{an attribute list cannot appear here}}
|
||||
|
|
Loading…
Reference in New Issue