]> granicus.if.org Git - clang/commitdiff
Thread-safety analysis: fix scoping issues related to 'this', including an
authorDeLesley Hutchins <delesley@google.com>
Mon, 20 Aug 2012 21:32:18 +0000 (21:32 +0000)
committerDeLesley Hutchins <delesley@google.com>
Mon, 20 Aug 2012 21:32:18 +0000 (21:32 +0000)
ICE in friend functions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162229 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseDecl.cpp
test/SemaCXX/warn-thread-safety-parsing.cpp

index 4d33106aa85d8a7364eac1de7e7915ad0c11977e..4129950ea6e971a5facdd06c69c654645b3dde66 100644 (file)
@@ -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();
   }
index 8aa6a91a9d2d487bab9fdaecb5ee1d1c05af9528..92c4b107a13f6aa54a4080a19e8cb563a5491abc 100644 (file)
@@ -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
+
+
+