forked from OSchip/llvm-project
Make late-parsed attributes follow the conventions of ordinary
GNU attributes to a better extent, by allowing them in more places on a declator. llvm-svn: 151945
This commit is contained in:
parent
a2587ef26d
commit
bd2ee13e78
|
@ -796,15 +796,15 @@ private:
|
|||
CachedTokens Toks;
|
||||
IdentifierInfo &AttrName;
|
||||
SourceLocation AttrNameLoc;
|
||||
Decl *D;
|
||||
SmallVector<Decl*, 2> Decls;
|
||||
|
||||
explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name,
|
||||
SourceLocation Loc)
|
||||
: Self(P), AttrName(Name), AttrNameLoc(Loc), D(0) {}
|
||||
: Self(P), AttrName(Name), AttrNameLoc(Loc) {}
|
||||
|
||||
virtual void ParseLexedAttributes();
|
||||
|
||||
void setDecl(Decl *Dec) { D = Dec; }
|
||||
void addDecl(Decl *D) { Decls.push_back(D); }
|
||||
};
|
||||
|
||||
/// A list of late parsed attributes. Used by ParseGNUAttributes.
|
||||
|
@ -1670,7 +1670,8 @@ private:
|
|||
void ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||
AccessSpecifier AS = AS_none,
|
||||
DeclSpecContext DSC = DSC_normal);
|
||||
DeclSpecContext DSC = DSC_normal,
|
||||
LateParsedAttrList *LateAttrs = 0);
|
||||
bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid,
|
||||
const char *&PrevSpec,
|
||||
unsigned &DiagID,
|
||||
|
|
|
@ -742,7 +742,7 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
|
|||
void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
|
||||
bool EnterScope, bool OnDefinition) {
|
||||
for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {
|
||||
LAs[i]->setDecl(D);
|
||||
LAs[i]->addDecl(D);
|
||||
ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);
|
||||
}
|
||||
LAs.clear();
|
||||
|
@ -774,33 +774,43 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
|
|||
ParsedAttributes Attrs(AttrFactory);
|
||||
SourceLocation endLoc;
|
||||
|
||||
// If the Decl is templatized, add template parameters to scope.
|
||||
bool HasTemplateScope = EnterScope && LA.D && LA.D->isTemplateDecl();
|
||||
ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope);
|
||||
if (HasTemplateScope)
|
||||
Actions.ActOnReenterTemplateScope(Actions.CurScope, LA.D);
|
||||
// Late parsed attributes must be attached to Decls by hand. If there
|
||||
// are no Decls, then this was not done properly.
|
||||
assert(LA.Decls.size() > 0 && "No decls attached to late parsed attribute");
|
||||
|
||||
// If the Decl is on a function, add function parameters to the scope.
|
||||
bool HasFunctionScope = EnterScope && LA.D &&
|
||||
LA.D->isFunctionOrFunctionTemplate();
|
||||
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope);
|
||||
if (HasFunctionScope)
|
||||
Actions.ActOnReenterFunctionContext(Actions.CurScope, LA.D);
|
||||
if (LA.Decls.size() == 1) {
|
||||
Decl *D = LA.Decls[0];
|
||||
|
||||
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
|
||||
// If the Decl is templatized, add template parameters to scope.
|
||||
bool HasTemplateScope = EnterScope && D->isTemplateDecl();
|
||||
ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope);
|
||||
if (HasTemplateScope)
|
||||
Actions.ActOnReenterTemplateScope(Actions.CurScope, D);
|
||||
|
||||
if (HasFunctionScope) {
|
||||
Actions.ActOnExitFunctionContext();
|
||||
FnScope.Exit(); // Pop scope, and remove Decls from IdResolver
|
||||
}
|
||||
if (HasTemplateScope) {
|
||||
TempScope.Exit();
|
||||
// If the Decl is on a function, add function parameters to the scope.
|
||||
bool HasFunctionScope = EnterScope && D->isFunctionOrFunctionTemplate();
|
||||
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope);
|
||||
if (HasFunctionScope)
|
||||
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
|
||||
|
||||
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
|
||||
|
||||
if (HasFunctionScope) {
|
||||
Actions.ActOnExitFunctionContext();
|
||||
FnScope.Exit(); // Pop scope, and remove Decls from IdResolver
|
||||
}
|
||||
if (HasTemplateScope) {
|
||||
TempScope.Exit();
|
||||
}
|
||||
} else {
|
||||
// If there are multiple decls, then the decl cannot be within the
|
||||
// function scope.
|
||||
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
|
||||
}
|
||||
|
||||
// Late parsed attributes must be attached to Decls by hand. If the
|
||||
// LA.D is not set, then this was not done properly.
|
||||
assert(LA.D && "No decl attached to late parsed attribute");
|
||||
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.D, Attrs);
|
||||
for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) {
|
||||
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
|
||||
}
|
||||
|
||||
if (Tok.getLocation() != OrigLoc) {
|
||||
// Due to a parsing error, we either went over the cached tokens or
|
||||
|
@ -1702,7 +1712,8 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
|
|||
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS,
|
||||
DeclSpecContext DSContext) {
|
||||
DeclSpecContext DSContext,
|
||||
LateParsedAttrList *LateAttrs) {
|
||||
if (DS.getSourceRange().isInvalid()) {
|
||||
DS.SetRangeStart(Tok.getLocation());
|
||||
DS.SetRangeEnd(Tok.getLocation());
|
||||
|
@ -2033,7 +2044,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
|
||||
// GNU attributes support.
|
||||
case tok::kw___attribute:
|
||||
ParseGNUAttributes(DS.getAttributes());
|
||||
ParseGNUAttributes(DS.getAttributes(), 0, LateAttrs);
|
||||
continue;
|
||||
|
||||
// Microsoft declspec support.
|
||||
|
|
|
@ -1782,11 +1782,15 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
return;
|
||||
}
|
||||
|
||||
// Hold late-parsed attributes so we can attach a Decl to them later.
|
||||
LateParsedAttrList CommonLateParsedAttrs;
|
||||
|
||||
// decl-specifier-seq:
|
||||
// Parse the common declaration-specifiers piece.
|
||||
ParsingDeclSpec DS(*this, TemplateDiags);
|
||||
DS.takeAttributesFrom(attrs);
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
|
||||
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
|
||||
&CommonLateParsedAttrs);
|
||||
|
||||
MultiTemplateParamsArg TemplateParams(Actions,
|
||||
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
|
||||
|
@ -1893,8 +1897,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
|
||||
VS, DefinitionKind, Init);
|
||||
|
||||
for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
|
||||
CommonLateParsedAttrs[i]->addDecl(FunDecl);
|
||||
}
|
||||
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
|
||||
LateParsedAttrs[i]->setDecl(FunDecl);
|
||||
LateParsedAttrs[i]->addDecl(FunDecl);
|
||||
}
|
||||
LateParsedAttrs.clear();
|
||||
|
||||
|
@ -1981,8 +1988,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
|||
}
|
||||
|
||||
// Set the Decl for any late parsed attributes
|
||||
for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
|
||||
CommonLateParsedAttrs[i]->addDecl(ThisDecl);
|
||||
}
|
||||
for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
|
||||
LateParsedAttrs[i]->setDecl(ThisDecl);
|
||||
LateParsedAttrs[i]->addDecl(ThisDecl);
|
||||
}
|
||||
LateParsedAttrs.clear();
|
||||
|
||||
|
|
|
@ -2130,4 +2130,28 @@ void test1() {
|
|||
}
|
||||
}
|
||||
|
||||
} // end namespace NoReturnTest
|
||||
|
||||
|
||||
namespace TestMultiDecl {
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int GUARDED_BY(mu_) a;
|
||||
int GUARDED_BY(mu_) b, c;
|
||||
|
||||
void foo() {
|
||||
a = 0; // \
|
||||
// expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
|
||||
b = 0; // \
|
||||
// expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
|
||||
c = 0; // \
|
||||
// expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex mu_;
|
||||
};
|
||||
|
||||
} // end namespace TestMultiDecl
|
||||
|
||||
|
|
|
@ -1287,5 +1287,21 @@ template <class T>
|
|||
void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { }
|
||||
|
||||
void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { }
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
namespace TestMultiDecl {
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int __attribute__((guarded_by(mu_))) a;
|
||||
int __attribute__((guarded_by(mu_))) b, c;
|
||||
|
||||
private:
|
||||
Mu mu_;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace TestMultiDecl
|
||||
|
||||
|
|
Loading…
Reference in New Issue