This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/32470 (namespace visibility bug)


My earlier implementation of namespace visibility assumed that only the parser would be calling push_namespace_with_attrs, which of course is not actually the case. So this patch fixes the bug by moving the visibility handling out of push_namespace into the parser.

Tested x86_64-pc-linux-gnu, applied to trunk. Will apply to 4.2 when it unfreezes.

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. 

Index: cp/name-lookup.c
===================================================================
*** cp/name-lookup.c	(revision 128889)
--- cp/name-lookup.c	(working copy)
*************** leave_scope (void)
*** 1364,1374 ****
        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;
  
--- 1364,1369 ----
*************** current_decl_namespace (void)
*** 3027,3046 ****
    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.  */
  
! void
! push_namespace (tree name)
  {
!   push_namespace_with_attribs (name, NULL_TREE);
! }
  
! /* Same, but specify attributes to apply to the namespace.  The attributes
!    only apply to the current namespace-body, not to any later extensions. */
  
  void
! push_namespace_with_attribs (tree name, tree attributes)
  {
    tree d = NULL_TREE;
    int need_new = 1;
--- 3022,3080 ----
    return result;
  }
  
! /* 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.  */
  
! bool
! handle_namespace_attrs (tree ns, tree attributes)
  {
!   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;
! 	}
!     }
  
!   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 (tree name)
  {
    tree d = NULL_TREE;
    int need_new = 1;
*************** push_namespace_with_attribs (tree name, 
*** 3107,3144 ****
    /* 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);
  }
  
--- 3141,3146 ----
Index: cp/name-lookup.h
===================================================================
*** cp/name-lookup.h	(revision 128889)
--- cp/name-lookup.h	(working copy)
*************** struct cp_binding_level GTY(())
*** 255,265 ****
      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.  */
    };
  
  /* The binding level currently in effect.  */
--- 255,261 ----
      unsigned more_cleanups_ok : 1;
      unsigned have_cleanups : 1;
  
!     /* 24 bits left to fill a 32-bit word.  */
    };
  
  /* The binding level currently in effect.  */
*************** extern void pop_inner_scope (tree, tree)
*** 307,316 ****
  extern void push_binding_level (struct cp_binding_level *);
  
  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 void pushlevel_class (void);
  extern void poplevel_class (void);
  extern tree pushdecl_with_scope (tree, cxx_scope *, bool);
--- 303,312 ----
  extern void push_binding_level (struct cp_binding_level *);
  
  extern void push_namespace (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: cp/parser.c
===================================================================
*** cp/parser.c	(revision 128889)
--- cp/parser.c	(working copy)
*************** static void
*** 11475,11480 ****
--- 11475,11481 ----
  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'");
*************** cp_parser_namespace_definition (cp_parse
*** 11494,11502 ****
    /* Look for the `{' to start the namespace.  */
    cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
    /* Start the namespace.  */
!   push_namespace_with_attribs (identifier, attribs);
    /* Parse the body of the namespace.  */
    cp_parser_namespace_body (parser);
    /* Finish the namespace.  */
    pop_namespace ();
    /* Look for the final `}'.  */
--- 11495,11512 ----
    /* Look for the `{' to start the namespace.  */
    cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
    /* Start the namespace.  */
!   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 `}'.  */
Index: testsuite/g++.dg/ext/visibility/namespace2.C
===================================================================
*** testsuite/g++.dg/ext/visibility/namespace2.C	(revision 0)
--- testsuite/g++.dg/ext/visibility/namespace2.C	(revision 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() { }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]