From: DeLesley Hutchins Date: Mon, 20 Aug 2012 21:32:18 +0000 (+0000) Subject: Thread-safety analysis: fix scoping issues related to 'this', including an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d30fb9e2462d3cfe04d4f32cb40bf1edd9e3b383;p=clang 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 --- 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(D); + RecordDecl *RD = dyn_cast_or_null(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 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 + + +