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: Improve DECL_VISIBILIITY machinery


This patch fixes a couple of bugs with the new DECL_VISIBILITY stuff:
neither implicit methods nor library functions were getting their
libraries set correctly.  The original patch also had a variety of
formatting problems, which I corrected.  Finally, I moved the
machinery for setting DECL_VISIBILITY into a single function, which
makes it much easier to change the way this stuff works if necessary.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-08-03  Mark Mitchell  <mark@codesourcery.com>

	* class.c (build_vtable): Do not set DECL_VISIBILITY here.
	(check_field_decls): Or here.
	(check_methods): Or here.
	(initialize_array): Don't mess with DECL_CONTEXT.
	* cp-tree.h (start_decl): Adjust prototype.
	(determine_visibility): New function.
	* decl.c (duplicate_decls): Remove checks for hidden "operator
	new".
	(build_library_fn_1): Give all library functions default
	visibility.
	(start_decl): Add pop_scope_p parameter.  Tidy.
	(cp_finish_decl): Do not pop scopes here.  Call
	determine_visibility for variable definitions.
	(start_preparsed_function): Call determine_visibility.
	* decl2.c (determine_visibility): New function.
	* method.c (use_thunk): Fix formatting.
	* parser.c (cp_parser_condition): Adjust calls to start_decl.
	(cp_parser_init_declarator): Likewise.
	* pt.c (instantiate_decl): Always call pop_nested_class.
	* rtti.c (get_tinfo_decl): Do not set DECL_VISIBILITY.
	(tinfo_base_init): Likewise.

2004-08-03  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/ext/visibility/assign1.C: New test.
	* g++.dg/ext/visibility/new1.C: Likewise.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.647
diff -c -5 -p -r1.647 class.c
*** cp/class.c	29 Jul 2004 17:59:25 -0000	1.647
--- cp/class.c	4 Aug 2004 03:26:15 -0000
*************** build_vtable (tree class_type, tree name
*** 657,671 ****
         attached to the member list for `S' before the debug info for
         `S' get written (which would solve the problem) but that would
         require more intrusive changes to the g++ front end.  */
      DECL_IGNORED_P (decl) = 1;
  
-   /* The vtable's visibility is the class visibility.  There is no way
-      to override the visibility for just the vtable. */
-   DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
-   DECL_VISIBILITY_SPECIFIED (decl) = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
- 
    return decl;
  }
  
  /* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
     or even complete.  If this does not exist, create it.  If COMPLETE is
--- 657,666 ----
*************** check_field_decls (tree t, tree *access_
*** 2969,2997 ****
  
        if (type == error_mark_node)
  	continue;
  	  
        if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
! 	{
! 	  /* Apply the class's visibility attribute to static members
! 	     which do not have a visibility attribute. */
! 	  if (! lookup_attribute ("visibility", DECL_ATTRIBUTES (x)))
!             {
!               if (visibility_options.inlines_hidden && DECL_INLINE (x))
!                 {
!                   DECL_VISIBILITY (x) = VISIBILITY_HIDDEN;
!                   DECL_VISIBILITY_SPECIFIED (x) = 1;
!                 }
!               else
!                 {
!                   DECL_VISIBILITY (x) = CLASSTYPE_VISIBILITY (current_class_type);
!                   DECL_VISIBILITY_SPECIFIED (x) = CLASSTYPE_VISIBILITY_SPECIFIED (current_class_type);
!                 }
!             }
! 
! 	  continue;
! 	}
  
        /* Now it can only be a FIELD_DECL.  */
  
        if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
  	CLASSTYPE_NON_AGGREGATE (t) = 1;
--- 2964,2974 ----
  
        if (type == error_mark_node)
  	continue;
  	  
        if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
! 	continue;
  
        /* Now it can only be a FIELD_DECL.  */
  
        if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
  	CLASSTYPE_NON_AGGREGATE (t) = 1;
*************** check_methods (tree t)
*** 3742,3768 ****
    for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
      {
        check_for_override (x, t);
        if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
  	cp_error_at ("initializer specified for non-virtual method `%D'", x);
-  
-       /* Apply the class's visibility attribute to methods which do
- 	 not have a visibility attribute. */
-       if (! lookup_attribute ("visibility", DECL_ATTRIBUTES (x)))
-         {
-           if (visibility_options.inlines_hidden && DECL_INLINE (x))
-             {
-               DECL_VISIBILITY (x) = VISIBILITY_HIDDEN;
-               DECL_VISIBILITY_SPECIFIED (x) = 1;
-             }
-           else
-             {
-               DECL_VISIBILITY (x) = CLASSTYPE_VISIBILITY (current_class_type);
-               DECL_VISIBILITY_SPECIFIED (x) = CLASSTYPE_VISIBILITY_SPECIFIED (current_class_type);
-             }
-         }
- 
        /* The name of the field is the original field name
  	 Save this in auxiliary field for later overloading.  */
        if (DECL_VINDEX (x))
  	{
  	  TYPE_POLYMORPHIC_P (t) = 1;
--- 3719,3728 ----
*************** initialize_vtable (tree binfo, tree init
*** 6738,6754 ****
     the INITS.  */
  
  static void
  initialize_array (tree decl, tree inits)
  {
-   tree context;
- 
-   context = DECL_CONTEXT (decl);
-   DECL_CONTEXT (decl) = NULL_TREE;
    DECL_INITIAL (decl) = build_constructor (NULL_TREE, inits);
    cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
-   DECL_CONTEXT (decl) = context;
  }
  
  /* Build the VTT (virtual table table) for T.
     A class requires a VTT if it has virtual bases.
     
--- 6698,6709 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1027
diff -c -5 -p -r1.1027 cp-tree.h
*** cp/cp-tree.h	2 Aug 2004 01:58:50 -0000	1.1027
--- cp/cp-tree.h	4 Aug 2004 03:26:15 -0000
*************** extern tree push_void_library_fn		(tree,
*** 3738,3748 ****
  extern tree push_throw_library_fn		(tree, tree);
  extern int init_type_desc			(void);
  extern tree check_tag_decl			(cp_decl_specifier_seq *);
  extern tree shadow_tag				(cp_decl_specifier_seq *);
  extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *);
! extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree);
  extern void start_decl_1			(tree);
  extern void cp_finish_decl			(tree, tree, tree, int);
  extern void finish_decl				(tree, tree, tree);
  extern int complete_array_type			(tree, tree, int);
  extern tree build_ptrmemfunc_type		(tree);
--- 3738,3748 ----
  extern tree push_throw_library_fn		(tree, tree);
  extern int init_type_desc			(void);
  extern tree check_tag_decl			(cp_decl_specifier_seq *);
  extern tree shadow_tag				(cp_decl_specifier_seq *);
  extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *);
! extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, bool *);
  extern void start_decl_1			(tree);
  extern void cp_finish_decl			(tree, tree, tree, int);
  extern void finish_decl				(tree, tree, tree);
  extern int complete_array_type			(tree, tree, int);
  extern tree build_ptrmemfunc_type		(tree);
*************** extern void cplus_decl_attributes (tree 
*** 3823,3832 ****
--- 3823,3833 ----
  extern void finish_anon_union (tree);
  extern tree finish_table (tree, tree, tree, int);
  extern tree coerce_new_type (tree);
  extern tree coerce_delete_type (tree);
  extern void comdat_linkage (tree);
+ extern void determine_visibility (tree);
  extern void import_export_decl (tree);
  extern tree build_cleanup			(tree);
  extern tree build_offset_ref_call_from_tree     (tree, tree);
  extern void check_default_args (tree);
  extern void mark_used (tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1266
diff -c -5 -p -r1.1266 decl.c
*** cp/decl.c	2 Aug 2004 01:58:50 -0000	1.1266
--- cp/decl.c	4 Aug 2004 03:26:16 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1879,1916 ****
    TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
    DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
    COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
  
    /* Warn about conflicting visibility specifications.  */
!   if (DECL_VISIBILITY_SPECIFIED (olddecl) && DECL_VISIBILITY_SPECIFIED (newdecl)
        && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
      {
        warning ("%J'%D': visibility attribute ignored because it",
!         newdecl, newdecl);
        warning ("%Jconflicts with previous declaration here", olddecl);
      }
    /* Choose the declaration which specified visibility.  */
    if (DECL_VISIBILITY_SPECIFIED (olddecl))
      {
        DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
        DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
      }
-   /* If it's a definition of a global operator new or operator
-      delete, it must be default visibility.  */
-   if (NEW_DELETE_OPNAME_P (DECL_NAME (newdecl)) && DECL_INITIAL (newdecl) != NULL_TREE)
-     {
-       if (!DECL_FUNCTION_MEMBER_P (newdecl) && VISIBILITY_DEFAULT != DECL_VISIBILITY (newdecl))
-         {
-           warning ("%J`%D': ignoring non-default symbol",
-             newdecl, newdecl);
-           warning ("%Jvisibility on global operator new or delete", newdecl);
-           DECL_VISIBILITY (olddecl) = VISIBILITY_DEFAULT;
-           DECL_VISIBILITY_SPECIFIED (olddecl) = 1;
-           DECL_VISIBILITY (newdecl) = VISIBILITY_DEFAULT;
-           DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
-         }
-     }
  
    if (TREE_CODE (newdecl) == FUNCTION_DECL)
      {
        int function_size;
  
--- 1879,1902 ----
    TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
    DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
    COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
  
    /* Warn about conflicting visibility specifications.  */
!   if (DECL_VISIBILITY_SPECIFIED (olddecl) 
!       && DECL_VISIBILITY_SPECIFIED (newdecl)
        && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
      {
        warning ("%J'%D': visibility attribute ignored because it",
! 	       newdecl, newdecl);
        warning ("%Jconflicts with previous declaration here", olddecl);
      }
    /* Choose the declaration which specified visibility.  */
    if (DECL_VISIBILITY_SPECIFIED (olddecl))
      {
        DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
        DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
      }
  
    if (TREE_CODE (newdecl) == FUNCTION_DECL)
      {
        int function_size;
  
*************** build_library_fn_1 (tree name, enum tree
*** 3274,3283 ****
--- 3260,3273 ----
    TREE_PUBLIC (fn) = 1;
    DECL_ARTIFICIAL (fn) = 1;
    TREE_NOTHROW (fn) = 1;
    SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
    SET_DECL_LANGUAGE (fn, lang_c);
+   /* Runtime library routines are, by definition, available in an
+      external shared object.  */
+   DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+   DECL_VISIBILITY_SPECIFIED (fn) = 1;
    return fn;
  }
  
  /* Returns the _DECL for a library function with C linkage.
     We assume that such functions never throw; if this is incorrect,
*************** groktypename (cp_decl_specifier_seq *typ
*** 3605,3615 ****
  tree
  start_decl (const cp_declarator *declarator,
  	    cp_decl_specifier_seq *declspecs,
              int initialized,
              tree attributes,
!             tree prefix_attributes)
  {
    tree decl;
    tree type, tem;
    tree context;
  
--- 3595,3606 ----
  tree
  start_decl (const cp_declarator *declarator,
  	    cp_decl_specifier_seq *declspecs,
              int initialized,
              tree attributes,
!             tree prefix_attributes, 
! 	    bool *pop_scope_p)
  {
    tree decl;
    tree type, tem;
    tree context;
  
*************** start_decl (const cp_declarator *declara
*** 3640,3657 ****
    if (type == error_mark_node)
      return NULL_TREE;
  
    context = DECL_CONTEXT (decl);
  
!   if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
!       && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
!     {
!       /* When parsing the initializer, lookup should use the object's
! 	 namespace.  */
!       push_decl_namespace (context);
!     }
! 
    /* We are only interested in class contexts, later.  */
    if (context && TREE_CODE (context) == NAMESPACE_DECL)
      context = NULL_TREE;
  
    if (initialized)
--- 3631,3645 ----
    if (type == error_mark_node)
      return NULL_TREE;
  
    context = DECL_CONTEXT (decl);
  
!   if (context)
!     *pop_scope_p = push_scope (context);
!   else
!     *pop_scope_p = false;
!   
    /* We are only interested in class contexts, later.  */
    if (context && TREE_CODE (context) == NAMESPACE_DECL)
      context = NULL_TREE;
  
    if (initialized)
*************** start_decl (const cp_declarator *declara
*** 3703,3714 ****
        && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
      warning ("%Jinline function '%D' given attribute noinline", decl, decl);
  
    if (context && COMPLETE_TYPE_P (complete_type (context)))
      {
-       push_nested_class (context);
- 
        if (TREE_CODE (decl) == VAR_DECL)
  	{
  	  tree field = lookup_field (context, DECL_NAME (decl), 0, false);
  	  if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
  	    error ("`%#D' is not a static member of `%#T'", decl, context);
--- 3691,3700 ----
*************** cp_finish_decl (tree decl, tree init, tr
*** 4713,4736 ****
        && CP_DECL_CONTEXT (decl) == current_class_type
        && TYPE_BEING_DEFINED (current_class_type)
        && (DECL_INITIAL (decl) || init))
      DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
  
-   if (TREE_CODE (decl) == VAR_DECL
-       && DECL_CONTEXT (decl)
-       && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
-       && DECL_CONTEXT (decl) != current_namespace
-       && init)
-     {
-       /* Leave the namespace of the object.  */
-       pop_decl_namespace ();
-     }
- 
    type = TREE_TYPE (decl);
  
    if (type == error_mark_node)
!     goto finish_end0;
  
    if (TYPE_HAS_MUTABLE_P (type))
      TREE_READONLY (decl) = 0;
  
    if (processing_template_decl)
--- 4699,4712 ----
        && CP_DECL_CONTEXT (decl) == current_class_type
        && TYPE_BEING_DEFINED (current_class_type)
        && (DECL_INITIAL (decl) || init))
      DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
  
    type = TREE_TYPE (decl);
  
    if (type == error_mark_node)
!     goto finish_end;
  
    if (TYPE_HAS_MUTABLE_P (type))
      TREE_READONLY (decl) = 0;
  
    if (processing_template_decl)
*************** cp_finish_decl (tree decl, tree init, tr
*** 4743,4753 ****
  	DECL_INITIAL (decl) = init;
        if (TREE_CODE (decl) == VAR_DECL
  	  && !DECL_PRETTY_FUNCTION_P (decl)
  	  && !dependent_type_p (TREE_TYPE (decl)))
  	maybe_deduce_size_from_array_init (decl, init);
!       goto finish_end0;
      }
  
    /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
    my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
  
--- 4719,4729 ----
  	DECL_INITIAL (decl) = init;
        if (TREE_CODE (decl) == VAR_DECL
  	  && !DECL_PRETTY_FUNCTION_P (decl)
  	  && !dependent_type_p (TREE_TYPE (decl)))
  	maybe_deduce_size_from_array_init (decl, init);
!       goto finish_end;
      }
  
    /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
    my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
  
*************** cp_finish_decl (tree decl, tree init, tr
*** 4831,4840 ****
--- 4807,4819 ----
  						   /*nelts=*/NULL_TREE,
  						   /*static_storage_p=*/true);
  	  /* Remember that the initialization for this variable has
  	     taken place.  */
  	  DECL_INITIALIZED_P (decl) = 1;
+ 	  /* The variable is being defined, so determine its
+ 	     visibility.  */
+ 	  determine_visibility (decl);
  	}
        /* If the variable has an array type, lay out the type, even if
  	 there is no initializer.  It is valid to index through the
  	 array, and we must get TYPE_ALIGN set correctly on the array
  	 type.  */
*************** cp_finish_decl (tree decl, tree init, tr
*** 4897,4926 ****
  	    }
  
  	  if (TREE_STATIC (decl))
  	    expand_static_init (decl, init);
  	}
-     finish_end0:
- 
-       /* Undo call to `pushclass' that was done in `start_decl'
- 	 due to initialization of qualified member variable.
- 	 I.e., Foo::x = 10;  */
-       {
- 	tree context = CP_DECL_CONTEXT (decl);
- 	if (context
- 	    && TYPE_P (context)
- 	    && (TREE_CODE (decl) == VAR_DECL
- 		/* We also have a pushclass done that we need to undo here
- 		   if we're at top level and declare a method.  */
- 		|| TREE_CODE (decl) == FUNCTION_DECL)
- 	    /* If size hasn't been set, we're still defining it,
- 	       and therefore inside the class body; don't pop
- 	       the binding level..  */
- 	    && COMPLETE_TYPE_P (context)
- 	    && context == current_class_type)
- 	  pop_nested_class ();
-       }
      }
  
    /* If a CLEANUP_STMT was created to destroy a temporary bound to a
       reference, insert it in the statement-tree now.  */
    if (cleanup)
--- 4876,4885 ----
*************** start_preparsed_function (tree decl1, tr
*** 9661,9670 ****
--- 9620,9632 ----
  
    if (DECL_DECLARED_INLINE_P (decl1)
        && lookup_attribute ("noinline", attrs))
      warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
  
+   /* Determine the ELF visibility attribute for the function.  */
+   determine_visibility (decl1);
+ 
    if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
      /* This is a constructor, we must ensure that any default args
         introduced by this definition are propagated to the clones
         now. The clones are used directly in overload resolution.  */
      adjust_clone_args (decl1);
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.730
diff -c -5 -p -r1.730 decl2.c
*** cp/decl2.c	29 Jul 2004 17:59:27 -0000	1.730
--- cp/decl2.c	4 Aug 2004 03:26:16 -0000
*************** maybe_emit_vtables (tree ctype)
*** 1614,1623 ****
--- 1614,1676 ----
    note_debug_info_needed (ctype);
  
    return true;
  }
  
+ /* Determine the ELF symbol visibility for DECL.  */
+ 
+ void
+ determine_visibility (tree decl)
+ {
+   tree class_type;
+ 
+   /* Cloned constructors and destructors get the same visibility as
+      the underlying function.  That should be set up in
+      maybe_clone_body.  */
+   if (DECL_CLONED_FUNCTION_P (decl))
+     return;
+ 
+   if (DECL_CLASS_SCOPE_P (decl))
+     class_type = DECL_CONTEXT (decl);
+   else if (TREE_CODE (decl) == VAR_DECL
+ 	   && DECL_TINFO_P (decl)
+ 	   && CLASS_TYPE_P (TREE_TYPE (DECL_NAME (decl))))
+     class_type = TREE_TYPE (DECL_NAME (decl));
+   else
+     {
+       /* Virtual tables have DECL_CONTEXT set to their associated class,
+ 	 so they are automatically handled above.  */
+       my_friendly_assert (!(TREE_CODE (decl) == VAR_DECL
+ 			    && DECL_VTABLE_OR_VTT_P (decl)), 20040803);
+       /* Entities not associated with any class just get the
+ 	 visibility specified by their attributes.  */
+       return;
+     }
+ 
+   /* By default, static data members and function members receive
+      the visibility of their containing class.  */
+   if (class_type
+       && (TREE_CODE (decl) == VAR_DECL 
+ 	  || TREE_CODE (decl) == FUNCTION_DECL)
+       && !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
+     {
+       if (TREE_CODE (decl) == FUNCTION_DECL
+ 	  && DECL_DECLARED_INLINE_P (decl)
+ 	  && visibility_options.inlines_hidden)
+ 	{
+ 	  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ 	  DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ 	}
+       else
+ 	{
+ 	  DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
+ 	  DECL_VISIBILITY_SPECIFIED (decl)
+ 	    = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
+ 	}
+     }
+ }
+ 
  /* DECL is a FUNCTION_DECL or VAR_DECL.  If the object file linkage
     for DECL has not already been determined, do so now by setting
     DECL_EXTERNAL, DECL_COMDAT and other related flags.  Until this
     function is called entities with vague linkage whose definitions
     are available must have TREE_PUBLIC set.
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.305
diff -c -5 -p -r1.305 method.c
*** cp/method.c	29 Jul 2004 17:59:28 -0000	1.305
--- cp/method.c	4 Aug 2004 03:26:16 -0000
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 366,376 ****
    DECL_EXTERNAL (thunk_fndecl) = 0;
    /* The linkage of the function may have changed.  FIXME in linkage
       rewrite.  */
    TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
    DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
!   DECL_VISIBILITY_SPECIFIED (thunk_fndecl) = DECL_VISIBILITY_SPECIFIED (function);
    if (flag_weak && TREE_PUBLIC (thunk_fndecl))
      comdat_linkage (thunk_fndecl);
  
    if (flag_syntax_only)
      {
--- 366,377 ----
    DECL_EXTERNAL (thunk_fndecl) = 0;
    /* The linkage of the function may have changed.  FIXME in linkage
       rewrite.  */
    TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
    DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
!   DECL_VISIBILITY_SPECIFIED (thunk_fndecl) 
!     = DECL_VISIBILITY_SPECIFIED (function);
    if (flag_weak && TREE_PUBLIC (thunk_fndecl))
      comdat_linkage (thunk_fndecl);
  
    if (flag_syntax_only)
      {
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.231
diff -c -5 -p -r1.231 parser.c
*** cp/parser.c	25 Jul 2004 17:19:39 -0000	1.231
--- cp/parser.c	4 Aug 2004 03:26:16 -0000
*************** cp_parser_condition (cp_parser* parser)
*** 6310,6331 ****
        cp_parser_require (parser, CPP_EQ, "`='");
        /* If we did see an `=', then we are looking at a declaration
  	 for sure.  */
        if (cp_parser_parse_definitely (parser))
  	{
  	  /* Create the declaration.  */
  	  decl = start_decl (declarator, &type_specifiers,
  			     /*initialized_p=*/true,
! 			     attributes, /*prefix_attributes=*/NULL_TREE);
  	  /* Parse the assignment-expression.  */
  	  initializer = cp_parser_assignment_expression (parser);
  
  	  /* Process the initializer.  */
  	  cp_finish_decl (decl,
  			  initializer,
  			  asm_specification,
  			  LOOKUP_ONLYCONVERTING);
  
  	  return convert_from_reference (decl);
  	}
      }
    /* If we didn't even get past the declarator successfully, we are
--- 6310,6336 ----
        cp_parser_require (parser, CPP_EQ, "`='");
        /* If we did see an `=', then we are looking at a declaration
  	 for sure.  */
        if (cp_parser_parse_definitely (parser))
  	{
+ 	  bool pop_p;
+ 
  	  /* Create the declaration.  */
  	  decl = start_decl (declarator, &type_specifiers,
  			     /*initialized_p=*/true,
! 			     attributes, /*prefix_attributes=*/NULL_TREE,
! 			     &pop_p);
  	  /* Parse the assignment-expression.  */
  	  initializer = cp_parser_assignment_expression (parser);
  
  	  /* Process the initializer.  */
  	  cp_finish_decl (decl,
  			  initializer,
  			  asm_specification,
  			  LOOKUP_ONLYCONVERTING);
+ 	  if (pop_p)
+ 	    pop_scope (DECL_CONTEXT (decl));
  
  	  return convert_from_reference (decl);
  	}
      }
    /* If we didn't even get past the declarator successfully, we are
*************** cp_parser_init_declarator (cp_parser* pa
*** 10628,10643 ****
  	{
  	  decl_specifiers->storage_class = sc_extern;
  	  have_extern_spec = false;
  	}
        decl = start_decl (declarator, decl_specifiers,
! 			 is_initialized, attributes, prefix_attributes);
      }
! 
!   /* Enter the SCOPE.  That way unqualified names appearing in the
!      initializer will be looked up in SCOPE.  */
!   if (scope)
      pop_p = push_scope (scope);
  
    /* Perform deferred access control checks, now that we know in which
       SCOPE the declared entity resides.  */
    if (!member_p && decl)
--- 10633,10648 ----
  	{
  	  decl_specifiers->storage_class = sc_extern;
  	  have_extern_spec = false;
  	}
        decl = start_decl (declarator, decl_specifiers,
! 			 is_initialized, attributes, prefix_attributes,
! 			 &pop_p);
      }
!   else if (scope)
!     /* Enter the SCOPE.  That way unqualified names appearing in the
!        initializer will be looked up in SCOPE.  */
      pop_p = push_scope (scope);
  
    /* Perform deferred access control checks, now that we know in which
       SCOPE the declared entity resides.  */
    if (!member_p && decl)
*************** cp_parser_init_declarator (cp_parser* pa
*** 10680,10719 ****
       attributes -- but ignores them.  */
    if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
      if (cp_parser_attributes_opt (parser))
        warning ("attributes after parenthesized initializer ignored");
  
-   /* Leave the SCOPE, now that we have processed the initializer.  It
-      is important to do this before calling cp_finish_decl because it
-      makes decisions about whether to create DECL_EXPRs or not based
-      on the current scope.  */
-   if (pop_p)
-     pop_scope (scope);
- 
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
      {
        decl = grokfield (declarator, decl_specifiers,
  			initializer, /*asmspec=*/NULL_TREE,
  			/*attributes=*/NULL_TREE);
        if (decl && TREE_CODE (decl) == FUNCTION_DECL)
  	cp_parser_save_default_args (parser, decl);
      }
  
    /* Finish processing the declaration.  But, skip friend
       declarations.  */
    if (!friend_p && decl)
!     cp_finish_decl (decl,
! 		    initializer,
! 		    asm_specification,
! 		    /* If the initializer is in parentheses, then this is
! 		       a direct-initialization, which means that an
! 		       `explicit' constructor is OK.  Otherwise, an
! 		       `explicit' constructor cannot be used.  */
! 		    ((is_parenthesized_init || !is_initialized)
  		     ? 0 : LOOKUP_ONLYCONVERTING));
  
    /* Remember whether or not variables were initialized by
       constant-expressions.  */
    if (decl && TREE_CODE (decl) == VAR_DECL
        && is_initialized && !is_non_constant_init)
--- 10685,10723 ----
       attributes -- but ignores them.  */
    if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
      if (cp_parser_attributes_opt (parser))
        warning ("attributes after parenthesized initializer ignored");
  
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
      {
+       if (pop_p)
+ 	pop_scope (scope);
        decl = grokfield (declarator, decl_specifiers,
  			initializer, /*asmspec=*/NULL_TREE,
  			/*attributes=*/NULL_TREE);
        if (decl && TREE_CODE (decl) == FUNCTION_DECL)
  	cp_parser_save_default_args (parser, decl);
      }
  
    /* Finish processing the declaration.  But, skip friend
       declarations.  */
    if (!friend_p && decl)
!     {
!       cp_finish_decl (decl,
! 		      initializer,
! 		      asm_specification,
! 		      /* If the initializer is in parentheses, then this is
! 			 a direct-initialization, which means that an
! 			 `explicit' constructor is OK.  Otherwise, an
! 			 `explicit' constructor cannot be used.  */
! 		      ((is_parenthesized_init || !is_initialized)
  		     ? 0 : LOOKUP_ONLYCONVERTING));
+       if (pop_p)
+ 	pop_scope (DECL_CONTEXT (decl));
+     }
  
    /* Remember whether or not variables were initialized by
       constant-expressions.  */
    if (decl && TREE_CODE (decl) == VAR_DECL
        && is_initialized && !is_non_constant_init)
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.900
diff -c -5 -p -r1.900 pt.c
*** cp/pt.c	2 Aug 2004 06:25:32 -0000	1.900
--- cp/pt.c	4 Aug 2004 03:26:16 -0000
*************** instantiate_decl (tree d, int defer_ok, 
*** 11160,11183 ****
        /* Clear DECL_EXTERNAL so that cp_finish_decl will process the
  	 initializer.  That function will defer actual emission until
  	 we have a chance to determine linkage.  */
        DECL_EXTERNAL (d) = 0;
  
!       /* This is done in analogous to `start_decl'.  It is required
! 	 for correct access checking.  */
        push_nested_class (DECL_CONTEXT (d));
        cp_finish_decl (d, 
  		      (!DECL_INITIALIZED_IN_CLASS_P (d) 
  		       ? DECL_INITIAL (d) : NULL_TREE),
  		      NULL_TREE, 0);
!       /* Normally, pop_nested_class is called by cp_finish_decl above.
! 	 But when instantiate_decl is triggered during
! 	 instantiate_class_template processing, its DECL_CONTEXT is
! 	 still not completed yet, and pop_nested_class isn't
! 	 called.  */
!       if (!COMPLETE_TYPE_P (DECL_CONTEXT (d)))
! 	pop_nested_class ();
      }
    else if (TREE_CODE (d) == FUNCTION_DECL)
      {
        htab_t saved_local_specializations;
        tree subst_decl;
--- 11160,11176 ----
        /* Clear DECL_EXTERNAL so that cp_finish_decl will process the
  	 initializer.  That function will defer actual emission until
  	 we have a chance to determine linkage.  */
        DECL_EXTERNAL (d) = 0;
  
!       /* Enter the scope of D so that access-checking works correctly.  */
        push_nested_class (DECL_CONTEXT (d));
        cp_finish_decl (d, 
  		      (!DECL_INITIALIZED_IN_CLASS_P (d) 
  		       ? DECL_INITIAL (d) : NULL_TREE),
  		      NULL_TREE, 0);
!       pop_nested_class ();
      }
    else if (TREE_CODE (d) == FUNCTION_DECL)
      {
        htab_t saved_local_specializations;
        tree subst_decl;
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.193
diff -c -5 -p -r1.193 rtti.c
*** cp/rtti.c	29 Jul 2004 17:59:28 -0000	1.193
--- cp/rtti.c	4 Aug 2004 03:26:16 -0000
*************** get_tinfo_decl (tree type)
*** 344,375 ****
      {
        tree var_desc = get_pseudo_ti_desc (type);
  
        d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
        SET_DECL_ASSEMBLER_NAME (d, name);
        DECL_TINFO_P (d) = 1;
        DECL_ARTIFICIAL (d) = 1;
        TREE_READONLY (d) = 1;
        TREE_STATIC (d) = 1;
        /* Mark the variable as undefined -- but remember that we can
  	 define it later if we need to do so.  */
        DECL_EXTERNAL (d) = 1;
        DECL_NOT_REALLY_EXTERN (d) = 1;
        set_linkage_according_to_type (type, d);
- 
        pushdecl_top_level_and_finish (d, NULL_TREE);
  
-       if (CLASS_TYPE_P (type))
- 	{
- 	  CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
- 	  DECL_VISIBILITY (d) = CLASSTYPE_VISIBILITY (type);
- 	  DECL_VISIBILITY_SPECIFIED (d) = CLASSTYPE_VISIBILITY_SPECIFIED (type);
- 	}
- 
-       /* Remember the type it is for.  */
-       TREE_TYPE (name) = type;
- 
        /* Add decl to the global array of tinfo decls.  */
        my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
        VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);
      }
  
--- 344,368 ----
      {
        tree var_desc = get_pseudo_ti_desc (type);
  
        d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
        SET_DECL_ASSEMBLER_NAME (d, name);
+       /* Remember the type it is for.  */
+       TREE_TYPE (name) = type;
        DECL_TINFO_P (d) = 1;
        DECL_ARTIFICIAL (d) = 1;
        TREE_READONLY (d) = 1;
        TREE_STATIC (d) = 1;
        /* Mark the variable as undefined -- but remember that we can
  	 define it later if we need to do so.  */
        DECL_EXTERNAL (d) = 1;
        DECL_NOT_REALLY_EXTERN (d) = 1;
+       if (CLASS_TYPE_P (type))
+ 	CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
        set_linkage_according_to_type (type, d);
        pushdecl_top_level_and_finish (d, NULL_TREE);
  
        /* Add decl to the global array of tinfo decls.  */
        my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
        VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);
      }
  
*************** tinfo_base_init (tree desc, tree target)
*** 789,822 ****
         type it is associated.  */
      name_name = mangle_typeinfo_string_for_type (target);
      TREE_TYPE (name_name) = target;
  
      name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
!     
      DECL_ARTIFICIAL (name_decl) = 1;
      TREE_READONLY (name_decl) = 1;
      TREE_STATIC (name_decl) = 1;
      DECL_EXTERNAL (name_decl) = 0;
      DECL_TINFO_P (name_decl) = 1;
-     if (CLASS_TYPE_P (target))
-       {
-         DECL_VISIBILITY (name_decl) = CLASSTYPE_VISIBILITY (target);
-         DECL_VISIBILITY_SPECIFIED (name_decl) 
- 	  = CLASSTYPE_VISIBILITY_SPECIFIED (target);
-       }
      if (involves_incomplete_p (target))
        {
  	TREE_PUBLIC (name_decl) = 0;
  	DECL_INTERFACE_KNOWN (name_decl) = 1;
        }
      else
        set_linkage_according_to_type (target, name_decl);
      import_export_decl (name_decl);
-     /* External name of the string containing the type's name has a
-        special name.  */
-     SET_DECL_ASSEMBLER_NAME (name_decl,
- 			     mangle_typeinfo_string_for_type (target));
      DECL_INITIAL (name_decl) = name_string;
      mark_used (name_decl);
      pushdecl_top_level_and_finish (name_decl, name_string);
    }
  
--- 782,805 ----
         type it is associated.  */
      name_name = mangle_typeinfo_string_for_type (target);
      TREE_TYPE (name_name) = target;
  
      name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
!     SET_DECL_ASSEMBLER_NAME (name_decl, name_name);
      DECL_ARTIFICIAL (name_decl) = 1;
      TREE_READONLY (name_decl) = 1;
      TREE_STATIC (name_decl) = 1;
      DECL_EXTERNAL (name_decl) = 0;
      DECL_TINFO_P (name_decl) = 1;
      if (involves_incomplete_p (target))
        {
  	TREE_PUBLIC (name_decl) = 0;
  	DECL_INTERFACE_KNOWN (name_decl) = 1;
        }
      else
        set_linkage_according_to_type (target, name_decl);
      import_export_decl (name_decl);
      DECL_INITIAL (name_decl) = name_string;
      mark_used (name_decl);
      pushdecl_top_level_and_finish (name_decl, name_string);
    }
  
Index: testsuite/g++.dg/ext/visibility/assign1.C
===================================================================
RCS file: testsuite/g++.dg/ext/visibility/assign1.C
diff -N testsuite/g++.dg/ext/visibility/assign1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/visibility/assign1.C	4 Aug 2004 03:26:16 -0000
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ /* { dg-require-visibility "" } */
+ /* { dg-final { scan-assembler "\\.hidden.*_ZN1DaSERKS_" } } */
+ 
+ struct B {
+   B& operator=(const B&);
+ };
+ 
+ struct D : public B {
+   // The implicit assignment operator should be hidden.
+ } __attribute__((visibility("hidden")));
+ 
+ D d1, d2;
+ 
+ void f() {
+   d1 = d2;
+ }
Index: testsuite/g++.dg/ext/visibility/new1.C
===================================================================
RCS file: testsuite/g++.dg/ext/visibility/new1.C
diff -N testsuite/g++.dg/ext/visibility/new1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/visibility/new1.C	4 Aug 2004 03:26:16 -0000
***************
*** 0 ****
--- 1,14 ----
+ // { dg-require-visibility }
+ // { dg-do compile }
+ // { dg-options "-fvisibility=hidden" }
+ // { dg-final { scan-assembler-not "\\.hidden\[^\n\]*_Znwj" } }
+ 
+ void f() {
+   new int;
+ }
+ 
+ void *g();
+ 
+ void *operator new(__SIZE_TYPE__) {
+   return g();
+ }


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