diff options
author | DeLesley Hutchins <delesley@google.com> | 2012-08-20 21:32:18 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2012-08-20 21:32:18 +0000 |
commit | d30fb9e2462d3cfe04d4f32cb40bf1edd9e3b383 (patch) | |
tree | 96a3b752c06b85446939c72b59c5d4ef0421b1c6 | |
parent | f0a26499c0ef62c7940b596be092315922a46ab7 (diff) |
Thread-safety analysis: fix scoping issues related to 'this', including an
ICE in friend functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162229 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 63 | ||||
-rw-r--r-- | test/SemaCXX/warn-thread-safety-parsing.cpp | 27 |
2 files changed, 60 insertions, 30 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4d33106aa8..4129950ea6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -851,10 +851,6 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); if (!Class.LateParsedDeclarations.empty()) { - // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, - /*TypeQuals=*/0); - for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ Class.LateParsedDeclarations[i]->ParseLexedAttributes(); } @@ -904,34 +900,43 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, ParsedAttributes Attrs(AttrFactory); SourceLocation endLoc; - if (LA.Decls.size() == 1) { + if (LA.Decls.size() > 0) { Decl *D = LA.Decls[0]; + NamedDecl *ND = dyn_cast<NamedDecl>(D); + RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); - // 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 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(); + // Allow 'this' within late-parsed attributes. + Sema::CXXThisScopeRAII ThisScope(Actions, RD, + /*TypeQuals=*/0, + ND && RD && ND->isCXXInstanceMember()); + + if (LA.Decls.size() == 1) { + // 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 the Decl is on a function, add function parameters to the scope. + bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope); + if (HasFunScope) + Actions.ActOnReenterFunctionContext(Actions.CurScope, D); + + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc); + + if (HasFunScope) { + 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); } - } else if (LA.Decls.size() > 0) { - // If there are multiple decls, then the decl cannot be within the - // function scope. - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc); } else { Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index 8aa6a91a9d..92c4b107a1 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -1255,7 +1255,7 @@ public: void foo4(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu); static void foo5() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ - // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + // expected-error {{invalid use of member 'mu' in static member function}} template <class T> void foo6() EXCLUSIVE_LOCKS_REQUIRED(T::statmu) { } @@ -1440,3 +1440,28 @@ void Foo::bar(Mutex* mu) LOCKS_EXCLUDED(mu) { } // \ } // end namespace InvalidDeclTest + +namespace StaticScopeTest { + +class FooStream; + +class Foo { + mutable Mutex mu; + int a GUARDED_BY(mu); + + static int si GUARDED_BY(mu); // \ + // expected-error {{invalid use of non-static data member 'mu'}} + + static void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ + // expected-error {{invalid use of member 'mu' in static member function}} + + friend FooStream& operator<<(FooStream& s, const Foo& f) + EXCLUSIVE_LOCKS_REQUIRED(mu); // \ + // expected-error {{invalid use of non-static data member 'mu'}} +}; + + +} // end namespace StaticScopeTest + + + |