Visibility attribute (was: proposed change: weak symbol support for Darwin)

Matt Austern austern@apple.com
Thu Oct 16 07:47:00 GMT 2003


On Wednesday, October 15, 2003, at 06:33  PM, Matt Austern wrote:

> On Monday, October 13, 2003, at 05:46  PM, Alexandre Oliva wrote:
>
>> On Oct 13, 2003, Matt Austern <austern@apple.com> wrote:
>>
>>> symbols that are public within a dynamic library but that aren't
>>> exported beyond the scope of the library boundary.
>>
>> Like attribute hidden?
>
> I didn't know about the visibility attribute until Alexandre
> pointed it out to me.  But now that I've looked at it, I can
> answer that question...
>
> Yes, Apple's notion of private extern symbols looks very much
> like __attribute__ ((visibility("hidden"))).  It looks so
> similar that it would be silly to have two separate
> mechanisms.
>
> So I have changed my mind.  I don't want to take one bit in a
> decl node for private_extern.  Instead I want to take two bits
> and use them for enum symbol_visibility.  Attributes are a
> fine user-level syntax, but I don't like using the attribute
> mechanism internally for this.

To be more precise, this is the sort of thing I have in mind.
Caveat: I haven't tested this code yet, so it's quite possible
there are typos and such.  I'm posting it to show the general
idea I have in mind.  If people agree it's the right approach,
then I'll test it and submit it as an official patch.

			--Matt

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.463
diff -p -r1.463 c-common.c
*** gcc/c-common.c	12 Oct 2003 22:09:20 -0000	1.463
--- gcc/c-common.c	16 Oct 2003 03:48:50 -0000
*************** handle_visibility_attribute (tree *node,
*** 4915,4947 ****
   			     bool *no_add_attrs)
   {
     tree decl = *node;

     if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
       {
         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
!       *no_add_attrs = true;
       }
-   else
-     {
-       tree id;

!       id = TREE_VALUE (args);
!       if (TREE_CODE (id) != STRING_CST)
! 	{
! 	  error ("visibility arg not a string");
! 	  *no_add_attrs = true;
! 	  return NULL_TREE;
! 	}
!       if (strcmp (TREE_STRING_POINTER (id), "hidden")
! 	  && strcmp (TREE_STRING_POINTER (id), "protected")
! 	  && strcmp (TREE_STRING_POINTER (id), "internal")
! 	  && strcmp (TREE_STRING_POINTER (id), "default"))
! 	{
! 	  error ("visibility arg must be one of \"default\", \"hidden\", 
\"protected\" or \"internal\"");
! 	  *no_add_attrs = true;
! 	  return NULL_TREE;
! 	}
       }

     return NULL_TREE;
   }
--- 4915,4946 ----
   			     bool *no_add_attrs)
   {
     tree decl = *node;
+   tree id = TREE_VALUE (args);
+
+   *no_add_attrs = true;

     if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
       {
         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
!       return NULL_TREE;
       }

!   if (TREE_CODE (id) != STRING_CST)
!     {
!       error ("visibility arg not a string");
!       return NULL_TREE;
       }
+
+   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
+     DECL_VISIBILIY (decl) == VISIBILITY_DEFAULT;
+   else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
+     DECL_VISIBILIY (decl) == VISIBILITY_INTERNAL;
+   else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
+     DECL_VISIBILIY (decl) == VISIBILITY_HIDDEN;
+   else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
+     DECL_VISIBILIY (decl) == VISIBILITY_PROTECTED;
+   else
+     error ("visibility arg must be one of \"default\", \"hidden\", 
\"protected\" or \"internal\"");

     return NULL_TREE;
   }
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.448
diff -p -r1.448 tree.h
*** gcc/tree.h	9 Oct 2003 05:44:51 -0000	1.448
--- gcc/tree.h	16 Oct 2003 03:48:53 -0000
*************** struct tree_type GTY(())
*** 1489,1494 ****
--- 1489,1497 ----
   #define DECL_DECLARED_INLINE_P(NODE) \
     (FUNCTION_DECL_CHECK (NODE)->decl.declared_inline_flag)

+ /* Value of the decls's visibility attribute */
+ #define DECL_VISIBILITY(NODE) (DECL_CHECK (node)->decl.visibility)
+
   /* In a FUNCTION_DECL, nonzero if the function cannot be inlined.  */
   #define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK 
(NODE)->decl.uninlinable)

*************** struct tree_type GTY(())
*** 1629,1634 ****
--- 1632,1647 ----
     (! DECL_CONTEXT (EXP)						\
      || TREE_CODE (DECL_CONTEXT (EXP)) == TRANSLATION_UNIT_DECL)

+ /* Enumerate visibility settings.  */
+
+ enum symbol_visibility
+ {
+   VISIBILITY_DEFAULT,
+   VISIBILITY_INTERNAL,
+   VISIBILITY_HIDDEN,
+   VISIBILITY_PROTECTED
+ };
+
   struct function;

   struct tree_decl GTY(())
*************** struct tree_decl GTY(())
*** 1670,1677 ****
     unsigned uninlinable : 1;
     unsigned thread_local_flag : 1;
     unsigned declared_inline_flag : 1;
!   unsigned unused : 3;
!   /* three unused bits.  */

     unsigned lang_flag_0 : 1;
     unsigned lang_flag_1 : 1;
--- 1683,1691 ----
     unsigned uninlinable : 1;
     unsigned thread_local_flag : 1;
     unsigned declared_inline_flag : 1;
!   enum symbol_visibility visibility : 2;
!   unsigned unused : 1;
!   /* one unused bit.  */

     unsigned lang_flag_0 : 1;
     unsigned lang_flag_1 : 1;
*************** enum tls_model {
*** 2005,2019 ****

   extern enum tls_model flag_tls_default;

- /* Enumerate visibility settings.  */
-
- enum symbol_visibility
- {
-   VISIBILITY_DEFAULT,
-   VISIBILITY_INTERNAL,
-   VISIBILITY_HIDDEN,
-   VISIBILITY_PROTECTED
- };
   
   /* A pointer-to-function member type looks like:

--- 2019,2024 ----
*************** extern void make_decl_one_only (tree);
*** 2967,2973 ****
   extern int supports_one_only (void);
   extern void variable_section (tree, int);
   enum tls_model decl_tls_model (tree);
- enum symbol_visibility decl_visibility (tree);
   extern void resolve_unique_section (tree, int, int);
   extern void mark_referenced (tree);
   extern void notice_global_symbol (tree);
--- 2972,2977 ----
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.391
diff -p -r1.391 varasm.c
*** gcc/varasm.c	11 Oct 2003 17:38:28 -0000	1.391
--- gcc/varasm.c	16 Oct 2003 03:48:56 -0000
*************** default_assemble_visibility (tree decl,
*** 4417,4423 ****
   static void
   maybe_assemble_visibility (tree decl)
   {
!   enum symbol_visibility vis = decl_visibility (decl);

     if (vis != VISIBILITY_DEFAULT)
       (* targetm.asm_out.visibility) (decl, vis);
--- 4417,4423 ----
   static void
   maybe_assemble_visibility (tree decl)
   {
!   enum symbol_visibility vis = DECL_VISIBILITY (decl);

     if (vis != VISIBILITY_DEFAULT)
       (* targetm.asm_out.visibility) (decl, vis);
*************** decl_tls_model (tree decl)
*** 4519,4548 ****
     return kind;
   }

- enum symbol_visibility
- decl_visibility (tree decl)
- {
-   tree attr = lookup_attribute ("visibility", DECL_ATTRIBUTES (decl));
-
-   if (attr)
-     {
-       const char *which = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE 
(attr)));
-
-       if (strcmp (which, "default") == 0)
- 	return VISIBILITY_DEFAULT;
-       if (strcmp (which, "internal") == 0)
- 	return VISIBILITY_INTERNAL;
-       if (strcmp (which, "hidden") == 0)
- 	return VISIBILITY_HIDDEN;
-       if (strcmp (which, "protected") == 0)
- 	return VISIBILITY_PROTECTED;
-
-       abort ();
-     }
-
-   return VISIBILITY_DEFAULT;
- }
-
   /* Select a set of attributes for section NAME based on the properties
      of DECL and whether or not RELOC indicates that DECL's initializer
      might contain runtime relocations.
--- 4519,4524 ----
*************** default_binds_local_p_1 (tree exp, int s
*** 5118,5124 ****
     else if (! TREE_PUBLIC (exp))
       local_p = true;
     /* A variable is local if the user tells us so.  */
!   else if (decl_visibility (exp) != VISIBILITY_DEFAULT)
       local_p = true;
     /* Otherwise, variables defined outside this object may not be 
local.  */
     else if (DECL_EXTERNAL (exp))
--- 5094,5100 ----
     else if (! TREE_PUBLIC (exp))
       local_p = true;
     /* A variable is local if the user tells us so.  */
!   else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
       local_p = true;
     /* Otherwise, variables defined outside this object may not be 
local.  */
     else if (DECL_EXTERNAL (exp))



More information about the Gcc mailing list