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:
DeLesley Hutchins 2012-03-02 22:12:59 +00:00
parent a2587ef26d
commit bd2ee13e78
5 changed files with 94 additions and 32 deletions

View File

@ -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,

View File

@ -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.

View File

@ -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();

View File

@ -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

View File

@ -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