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] [PR 9283] Implement per-class visibility (new patch)



This patch implement per class/struct visibility for C++. I've revised the patch per suggestions from Jason Merrill, and also improved the testcase based on suggestions from Jakub Jelinek.


The main change from my previous patch is to use the class type's TYPE_NAME decl to hold the class visibility, rather than storing it on the class stack. Additionally, I made the visibility attribute be added to the DECL_ATTRIBUTES list (previously it was not)... this is needed to determine that a member explicitly overrides the class visibility with visibility("default").

I do have a couple of things in the patch I'm not 100% sure about:
- In c-common.c (handle_visibility_attribute), is the TREE_CODE (*node) != RECORD_TYPE correct?
- In rtti.c (tinfo_base_init), is 'target' the correct type to get the visibility from?


Bootstrapped and passed all test suites on i686-pc-linux-gnu.

--
-Brian Ryner
bryner@brianryner.com
gcc/
2004-04-05  Brian Ryner  <bryner@brianryner.com>
	PR c++/9283
	* c-common.c (c_common_attribute_table): Allow
	handle_visibility_attribute to be called for types.
	(handle_visibility_attribute) When given a type, set the visibility
	bits on the TYPE_NAME.  When given a decl, don't set no_add_attrs
	so that we can check later whether the attribute was present.

gcc/cp
2004-04-05  Brian Ryner  <bryner@brianryner.com>
	PR c++/9283
	* class.c (CURRENT_VISIBILITY): Add macro.
	(build_vtable): Set vtable visibility to class visibility.
	(check_field_decls): Default static member visibility to class
	visibility.
	(check_methods): Default method visibility to class visibility.
	* rtti.c (get_tinfo_decl): Set typeinfo visibility to class visibility.
	(tinfo_base_init): Set typeinfo name visibility to class visibility.
Index: c-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.494
diff -u -p -c -3 -p -r1.494 c-common.c
*** c-common.c	1 Apr 2004 03:50:26 -0000	1.494
--- c-common.c	5 Apr 2004 10:56:34 -0000
*************** const struct attribute_spec c_common_att
*** 832,838 ****
  			      handle_deprecated_attribute },
    { "vector_size",	      1, 1, false, true, false,
  			      handle_vector_size_attribute },
!   { "visibility",	      1, 1, true,  false, false,
  			      handle_visibility_attribute },
    { "tls_model",	      1, 1, true,  false, false,
  			      handle_tls_model_attribute },
--- 832,838 ----
  			      handle_deprecated_attribute },
    { "vector_size",	      1, 1, false, true, false,
  			      handle_vector_size_attribute },
!   { "visibility",	      1, 1, false, false, false,
  			      handle_visibility_attribute },
    { "tls_model",	      1, 1, true,  false, false,
  			      handle_tls_model_attribute },
*************** handle_visibility_attribute (tree *node,
*** 4855,4861 ****
  
    *no_add_attrs = true;
  
!   if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
      {
        warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
        return NULL_TREE;
--- 4855,4870 ----
  
    *no_add_attrs = true;
  
!   /*  If this is a type, set the visibility on the type decl.  */
!   if (TYPE_P (decl))
!     {
!       decl = TYPE_NAME (decl);
!       if (! decl)
! 	return NULL_TREE;
!     }
! 
!   if (TREE_CODE (*node) != RECORD_TYPE
!       && (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)))
      {
        warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
        return NULL_TREE;
*************** handle_visibility_attribute (tree *node,
*** 4877,4882 ****
--- 4886,4898 ----
      DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
    else
      error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ 
+   /* For decls only, go ahead and attach the attribute to the node as well.
+      This is needed so we can determine whether we have VISIBILITY_DEFAULT
+      because the visibility was not specified, or because it was explicitly
+      overridden from the class visibility.  */
+   if (DECL_P (*node))
+     *no_add_attrs = false;
  
    return NULL_TREE;
  }
Index: cp/class.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.606
diff -u -p -c -3 -p -r1.606 class.c
*** cp/class.c	1 Apr 2004 13:41:36 -0000	1.606
--- cp/class.c	5 Apr 2004 10:56:38 -0000
*************** typedef int (*subobject_offset_fn) (tree
*** 102,107 ****
--- 102,110 ----
  static int current_class_stack_size;
  static class_stack_node_t current_class_stack;
  
+ /* Convenience macro for class visibility.  */
+ #define CURRENT_VISIBILITY  DECL_VISIBILITY (TYPE_NAME (current_class_type))
+ 
  /* An array of all local classes present in this translation unit, in
     declaration order.  */
  varray_type local_classes;
*************** build_vtable (tree class_type, tree name
*** 524,529 ****
--- 527,535 ----
    DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
  			   DECL_ALIGN (decl));
  
+   /* The vtable's visibility is the class visibility.  There is no way
+      to override the visibility for just the vtable. */
+   DECL_VISIBILITY (decl) = DECL_VISIBILITY (TYPE_NAME (class_type));
    import_export_vtable (decl, class_type, 0);
  
    return decl;
*************** check_field_decls (tree t, tree *access_
*** 2971,2977 ****
  	continue;
  	  
        if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
! 	continue;
  
        /* Now it can only be a FIELD_DECL.  */
  
--- 2977,2990 ----
  	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)))
! 	    DECL_VISIBILITY (x) = CURRENT_VISIBILITY;
! 
! 	  continue;
! 	}
  
        /* Now it can only be a FIELD_DECL.  */
  
*************** check_methods (tree t)
*** 3703,3708 ****
--- 3716,3726 ----
        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)))
+ 	DECL_VISIBILITY (x) = CURRENT_VISIBILITY;
  
        /* The name of the field is the original field name
  	 Save this in auxiliary field for later overloading.  */
Index: cp/rtti.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.179
diff -u -p -c -3 -p -r1.179 rtti.c
*** cp/rtti.c	8 Mar 2004 22:24:35 -0000	1.179
--- cp/rtti.c	5 Apr 2004 10:56:38 -0000
*************** get_tinfo_decl (tree type)
*** 361,367 ****
        pushdecl_top_level_and_finish (d, NULL_TREE);
  
        if (CLASS_TYPE_P (type))
! 	CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
  
        /* Remember the type it is for.  */
        TREE_TYPE (name) = type;
--- 361,370 ----
        pushdecl_top_level_and_finish (d, NULL_TREE);
  
        if (CLASS_TYPE_P (type))
! 	{
! 	  CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
! 	  DECL_VISIBILITY (d) = DECL_VISIBILITY (TYPE_NAME (type));
! 	}
  
        /* Remember the type it is for.  */
        TREE_TYPE (name) = type;
*************** tinfo_base_init (tree desc, tree target)
*** 759,764 ****
--- 762,769 ----
      TREE_STATIC (name_decl) = 1;
      DECL_EXTERNAL (name_decl) = 0;
      TREE_PUBLIC (name_decl) = 1;
+     if (CLASS_TYPE_P (target))
+       DECL_VISIBILITY (name_decl) = DECL_VISIBILITY (TYPE_NAME (target));
      import_export_tinfo (name_decl, target, typeinfo_in_lib_p (target));
      /* External name of the string containing the type's name has a
         special name.  */
/* Test class visibility specification. */
/* { dg-do compile { target *86-*-linux* } } */
/* { dg-final { scan-assembler "\.hidden\[ \t\]*_ZN1A7hidden1Ev" } } */
/* { dg-final { scan-assembler "\.hidden\[ \t\]*_ZN1A7hidden2Ev" } } */
/* { dg-final { scan-assembler-not "\.hidden\[ \t\]*_ZN1A8visible1Ev" } } */
/* { dg-final { scan-assembler "\.hidden\[ \t\]*_ZTV1A" } } */
/* { dg-final { scan-assembler "\.hidden\[ \t\]*_ZTI1A" } } */
/* { dg-final { scan-assembler "\.hidden\[ \t\]*_ZTS1A" } } */

struct __attribute__((visibility ("hidden"))) A
{
  virtual void hidden1();
  void hidden2() __attribute__((visibility ("hidden")));
  void visible1() __attribute__((visibility ("default")));
};

void
A::hidden1()
{
}

void
A::hidden2()
{
}

void
A::visible1()
{
}

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