diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-03-02 22:12:59 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-03-02 22:12:59 +0000 |
commit | 2287c5e2352fc51cd74e8a9a7725cbf87e41c007 (patch) | |
tree | ae07c0784e322a4900199e6cbf277d0cdba8d316 | |
parent | 2a35be803c405221f5f23c7bdedb91f09efdd3ac (diff) |
Make late-parsed attributes follow the conventions of ordinary
GNU attributes to a better extent, by allowing them in more
places on a declator.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151945 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 9 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 61 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 16 | ||||
-rw-r--r-- | test/SemaCXX/warn-thread-safety-analysis.cpp | 24 | ||||
-rw-r--r-- | test/SemaCXX/warn-thread-safety-parsing.cpp | 16 |
5 files changed, 94 insertions, 32 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 89d1bb80da..3fc1fd9fb2 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 591fe9ef3d..476f476dab 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 @@ -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. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 3bf7005769..983bd7ee15 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -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(); diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 78a276c4da..ec9f00f94b 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -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 + diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index c58ff9314e..2e5106ce8a 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 + |