Allow for annotate attributes after access specifiers. When such
attributes are found, propagate them to subsequent declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141861 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 35c181c..b387e9e 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -21,7 +21,9 @@
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
-Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
+Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
+ AttributeList *AccessAttrs,
+ ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo,
const VirtSpecifiers& VS, ExprResult& Init) {
assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
@@ -43,6 +45,8 @@
move(TemplateParams), 0,
VS, /*HasInit=*/false);
if (FnD) {
+ Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
+ false, true);
bool TypeSpecContainsAuto
= D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
if (Init.get())
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index decb7f9..607cb88 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1577,6 +1577,7 @@
/// '=' constant-expression
///
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+ AttributeList *AccessAttrs,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject *TemplateDiags) {
if (Tok.is(tok::at)) {
@@ -1643,7 +1644,7 @@
"Nested template improperly parsed?");
SourceLocation DeclEnd;
ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
- AS);
+ AS, AccessAttrs);
return;
}
@@ -1652,7 +1653,8 @@
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags);
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs,
+ TemplateInfo, TemplateDiags);
}
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
@@ -1783,7 +1785,8 @@
}
Decl *FunDecl =
- ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init);
+ ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
+ VS, Init);
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
LateParsedAttrs[i]->setDecl(FunDecl);
@@ -1867,6 +1870,9 @@
move(TemplateParams),
BitfieldSize.release(),
VS, HasDeferredInitializer);
+ if (AccessAttrs)
+ Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs,
+ false, true);
}
// Set the Decl for any late parsed attributes
@@ -2109,6 +2115,7 @@
CurAS = AS_private;
else
CurAS = AS_public;
+ ParsedAttributes AccessAttrs(AttrFactory);
if (TagDecl) {
// While we still have something to read, read the member-declarations.
@@ -2137,9 +2144,17 @@
SourceLocation ASLoc = Tok.getLocation();
unsigned TokLength = Tok.getLength();
ConsumeToken();
+ AccessAttrs.clear();
+ MaybeParseGNUAttributes(AccessAttrs);
+
SourceLocation EndLoc;
if (Tok.is(tok::colon)) {
EndLoc = Tok.getLocation();
+ if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc,
+ AccessAttrs.getList())) {
+ // found another attribute than only annotations
+ AccessAttrs.clear();
+ }
ConsumeToken();
} else if (Tok.is(tok::semi)) {
EndLoc = Tok.getLocation();
@@ -2158,7 +2173,7 @@
// FIXME: Make sure we don't have a template here.
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS);
+ ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
}
T.consumeClose();
@@ -2779,7 +2794,7 @@
}
// Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS);
+ ParseCXXClassMemberDeclaration(CurAS, 0);
}
if (Tok.isNot(tok::r_brace)) {
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 4509662..92fe4a5 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -26,14 +26,16 @@
Decl *
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
- AccessSpecifier AS) {
+ AccessSpecifier AS,
+ AttributeList *AccessAttrs) {
ObjCDeclContextSwitch ObjCDC(*this);
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
DeclEnd);
}
- return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
+ return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
+ AccessAttrs);
}
/// \brief RAII class that manages the template parameter depth.
@@ -77,7 +79,8 @@
Decl *
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
- AccessSpecifier AS) {
+ AccessSpecifier AS,
+ AttributeList *AccessAttrs) {
assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
"Token does not start a template declaration.");
@@ -161,7 +164,7 @@
isSpecialization,
LastParamListWasEmpty),
ParsingTemplateParams,
- DeclEnd, AS);
+ DeclEnd, AS, AccessAttrs);
}
/// \brief Parse a single declaration that declares a template,
@@ -190,13 +193,15 @@
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject &DiagsFromTParams,
SourceLocation &DeclEnd,
- AccessSpecifier AS) {
+ AccessSpecifier AS,
+ AttributeList *AccessAttrs) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
"Template information required");
if (Context == Declarator::MemberContext) {
// We are parsing a member template.
- ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams);
+ ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
+ &DiagsFromTParams);
return 0;
}