]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/32470 (fvisibility=hidden without effect in some cases)
authorJason Merrill <jason@redhat.com>
Thu, 4 Oct 2007 08:48:23 +0000 (04:48 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 4 Oct 2007 08:48:23 +0000 (04:48 -0400)
        PR c++/32470
        * name-lookup.c (push_namespace_with_attrs): Fold back into...
        (push_namespace): Here.
        (handle_namespace_attrs): New fn for the attr code.
        (leave_scope): Don't pop_visibility.
        * name-lookup.h (struct cp_binding_level): Remove has_visibility.
        * parser.c (cp_parser_namespace_definition): Call
        handle_namespace_attrs and pop_visibility as appropriate.

From-SVN: r129003

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/parser.c
gcc/testsuite/g++.dg/ext/visibility/namespace2.C [new file with mode: 0644]

index 2e3353400544b5c0e2e7893884642ab553802fc4..0cec0879fe799230ead2a55d24286543c4a28d9b 100644 (file)
@@ -1,5 +1,14 @@
 2007-10-03  Jason Merrill  <jason@redhat.com>
 
+       PR c++/32470
+       * name-lookup.c (push_namespace_with_attrs): Fold back into...
+       (push_namespace): Here.
+       (handle_namespace_attrs): New fn for the attr code.
+       (leave_scope): Don't pop_visibility.
+       * name-lookup.h (struct cp_binding_level): Remove has_visibility.
+       * parser.c (cp_parser_namespace_definition): Call
+       handle_namespace_attrs and pop_visibility as appropriate. 
+
        PR c++/11756
        * mangle.c (write_type) [TYPEOF_TYPE]: Just sorry.
 
index 70a395b2f3c5500ddc9397050bf636361e90df88..a7bb710dace4b5101c3f5af999226b83cc2ddbd7 100644 (file)
@@ -1364,11 +1364,6 @@ leave_scope (void)
       is_class_level = 0;
     }
 
-#ifdef HANDLE_PRAGMA_VISIBILITY
-  if (scope->has_visibility)
-    pop_visibility ();
-#endif
-
   /* Move one nesting level up.  */
   current_binding_level = scope->level_chain;
 
@@ -3027,20 +3022,59 @@ current_decl_namespace (void)
   return result;
 }
 
-/* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then we
-   select a name that is unique to this compilation unit.  */
+/* Process any ATTRIBUTES on a namespace definition.  Currently only
+   attribute visibility is meaningful, which is a property of the syntactic
+   block rather than the namespace as a whole, so we don't touch the
+   NAMESPACE_DECL at all.  Returns true if attribute visibility is seen.  */
 
-void
-push_namespace (tree name)
+bool
+handle_namespace_attrs (tree ns, tree attributes)
 {
-  push_namespace_with_attribs (name, NULL_TREE);
-}
+  tree d;
+  bool saw_vis = false;
+
+  for (d = attributes; d; d = TREE_CHAIN (d))
+    {
+      tree name = TREE_PURPOSE (d);
+      tree args = TREE_VALUE (d);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+      if (is_attribute_p ("visibility", name))
+       {
+         tree x = args ? TREE_VALUE (args) : NULL_TREE;
+         if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
+           {
+             warning (OPT_Wattributes,
+                      "%qD attribute requires a single NTBS argument",
+                      name);
+             continue;
+           }
+
+         if (!TREE_PUBLIC (ns))
+           warning (OPT_Wattributes,
+                    "%qD attribute is meaningless since members of the "
+                    "anonymous namespace get local symbols", name);
+
+         push_visibility (TREE_STRING_POINTER (x));
+         saw_vis = true;
+       }
+      else
+#endif
+       {
+         warning (OPT_Wattributes, "%qD attribute directive ignored",
+                  name);
+         continue;
+       }
+    }
 
-/* Same, but specify attributes to apply to the namespace.  The attributes
-   only apply to the current namespace-body, not to any later extensions. */
+  return saw_vis;
+}
+  
+/* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then we
+   select a name that is unique to this compilation unit.  */
 
 void
-push_namespace_with_attribs (tree name, tree attributes)
+push_namespace (tree name)
 {
   tree d = NULL_TREE;
   int need_new = 1;
@@ -3107,38 +3141,6 @@ push_namespace_with_attribs (tree name, tree attributes)
   /* Enter the name space.  */
   current_namespace = d;
 
-#ifdef HANDLE_PRAGMA_VISIBILITY
-  /* Clear has_visibility in case a previous namespace-definition had a
-     visibility attribute and this one doesn't.  */
-  current_binding_level->has_visibility = 0;
-  for (d = attributes; d; d = TREE_CHAIN (d))
-    {
-      tree name = TREE_PURPOSE (d);
-      tree args = TREE_VALUE (d);
-      tree x;
-
-      if (! is_attribute_p ("visibility", name))
-       {
-         warning (OPT_Wattributes, "%qs attribute directive ignored",
-                  IDENTIFIER_POINTER (name));
-         continue;
-       }
-
-      x = args ? TREE_VALUE (args) : NULL_TREE;
-      if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
-       {
-         warning (OPT_Wattributes, "%qs attribute requires a single NTBS argument",
-                  IDENTIFIER_POINTER (name));
-         continue;
-       }
-
-      current_binding_level->has_visibility = 1;
-      push_visibility (TREE_STRING_POINTER (x));
-      goto found;
-    }
- found:
-#endif
-
   timevar_pop (TV_NAME_LOOKUP);
 }
 
index 88551f2b8acafdfdb22e29296c69e25e129d63b3..7da57be9f1f9da88c53b549344b2ad9be5e1add2 100644 (file)
@@ -255,11 +255,7 @@ struct cp_binding_level GTY(())
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if this level has associated visibility which we should pop
-       when leaving the scope. */
-    unsigned has_visibility : 1;
-
-    /* 23 bits left to fill a 32-bit word.  */
+    /* 24 bits left to fill a 32-bit word.  */
   };
 
 /* The binding level currently in effect.  */
@@ -307,10 +303,10 @@ extern void pop_inner_scope (tree, tree);
 extern void push_binding_level (struct cp_binding_level *);
 \f
 extern void push_namespace (tree);
-extern void push_namespace_with_attribs (tree, tree);
 extern void pop_namespace (void);
 extern void push_nested_namespace (tree);
 extern void pop_nested_namespace (tree);
+extern bool handle_namespace_attrs (tree, tree);
 extern void pushlevel_class (void);
 extern void poplevel_class (void);
 extern tree pushdecl_with_scope (tree, cxx_scope *, bool);
index ede0d7e324467ef3e5ee9b822e1ad0b83e1f6d7a..3720b5567a5c708c1677ac45bcf21dc6b2852e0f 100644 (file)
@@ -11475,6 +11475,7 @@ static void
 cp_parser_namespace_definition (cp_parser* parser)
 {
   tree identifier, attribs;
+  bool has_visibility;
 
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
@@ -11494,9 +11495,18 @@ cp_parser_namespace_definition (cp_parser* parser)
   /* Look for the `{' to start the namespace.  */
   cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
   /* Start the namespace.  */
-  push_namespace_with_attribs (identifier, attribs);
+  push_namespace (identifier);
+
+  has_visibility = handle_namespace_attrs (current_namespace, attribs);
+
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+  if (has_visibility)
+    pop_visibility ();
+#endif
+
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
diff --git a/gcc/testsuite/g++.dg/ext/visibility/namespace2.C b/gcc/testsuite/g++.dg/ext/visibility/namespace2.C
new file mode 100644 (file)
index 0000000..5e6e71f
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/32470
+
+// { dg-require-visibility }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-hidden "_ZN4Test4testEv" } }
+
+namespace std __attribute__((__visibility__("default"))) {
+  template<typename _CharT>
+  class basic_streambuf
+  {
+    friend void getline();
+  };
+  extern template class basic_streambuf<char>;
+}
+
+class Test
+{
+  void test();
+};
+void Test::test() { }