This patch makes late-parsed attributes behave more like ordinary GNU
attributes, by allowing them to appear in additional places on the
declarator, including declarators with multiple declarations.
Currently this change only affects thread safety attributes. For
example:
class Foo {
int __attribute__((guarded_by(mu))) a, b; // both a and b are guarded by mu_
Mutex mu_;
};
http://codereview.appspot.com/5687084/
--
DeLesley Hutchins | Software Engineer | [email protected] | 505-206-0315
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 242ef38..d5d58a4 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -792,15 +792,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.
@@ -1667,7 +1667,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,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e9032cd..c43e24d 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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
@@ -1709,7 +1719,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());
@@ -2040,7 +2051,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.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 5edc30b..bdc2c8e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1773,11 +1773,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,
@@ -1884,8 +1888,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();
@@ -1972,8 +1979,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();
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 065d072..dc6d090 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -2132,3 +2132,25 @@ class Foo {
} // end namespace InvalidNonStatic
+
+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
diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp
index c58ff93..2e5106c 100644
--- a/test/SemaCXX/warn-thread-safety-parsing.cpp
+++ b/test/SemaCXX/warn-thread-safety-parsing.cpp
@@ -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
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits