2002-02-26 Jakub Jelinek * attribs.c (c_common_attribute_table): Add visibility. (handle_visibility_attribute): New function. * varasm.c (assemble_visibility): New function. * output.h (assemble_visibility): Add prototype. * tree.h (MODULE_LOCAL_P): Define. * crtstuff.c (__dso_handle): Use visibility attribute. * config/i386/i386.h (ENCODE_SECTION_INFO): Set SYMBOL_REF_FLAG for MODULE_LOCAL_P symbols too. * config/ia64/ia64.c (ia64_encode_section_info): Handle MODULE_LOCAL_P symbols the same way as local symbols. Add SDATA_NAME_FLAG_CHAR even if decl was explicitely forced into .sdata/.sbss by the user. * doc/extend.texi (Function Attributes): Document visibility attribute. * gcc.dg/ia64-visibility-1.c: New test. --- gcc/attribs.c 2002/02/25 22:38:52 1.14 +++ gcc/attribs.c 2002/02/26 21:17:14 1.15 @@ -75,6 +75,8 @@ static tree handle_weak_attribute PARAMS bool *)); static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, bool *)); +static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int, + bool *)); static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, tree, int, bool *)); @@ -148,6 +150,8 @@ static const struct attribute_spec c_com handle_deprecated_attribute }, { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute }, + { "visibility", 1, 1, true, false, false, + handle_visibility_attribute }, { NULL, 0, 0, false, false, false, NULL } }; @@ -1061,6 +1065,50 @@ handle_alias_attribute (node, name, args return NULL_TREE; } +/* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_visibility_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + 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")) + { + error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\""); + *no_add_attrs = true; + return NULL_TREE; + } + + assemble_visibility (decl, TREE_STRING_POINTER (id)); + } + + return NULL_TREE; +} + /* Handle a "no_instrument_function" attribute; arguments as in struct attribute_spec.handler. */ --- gcc/varasm.c 2002/02/20 23:19:19 1.250 +++ gcc/varasm.c 2002/02/26 21:17:14 1.251 @@ -5160,6 +5160,25 @@ assemble_alias (decl, target) #endif } +/* Emit an assembler directive to set symbol for DECL visibility to + VISIBILITY_TYPE. */ + +void +assemble_visibility (decl, visibility_type) + tree decl; + const char *visibility_type ATTRIBUTE_UNUSED; +{ + const char *name; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + +#ifdef HAVE_GAS_HIDDEN + fprintf (asm_out_file, "\t.%s\t%s\n", visibility_type, name); +#else + warning ("visibility attribute not supported in this configuration; ignored"); +#endif +} + /* Returns 1 if the target configuration supports defining public symbols so that one of them will be chosen at link time instead of generating a multiply-defined symbol error, whether through the use of weak symbols or --- gcc/output.h 2002/02/17 14:23:50 1.94 +++ gcc/output.h 2002/02/26 21:17:14 1.95 @@ -255,6 +255,8 @@ extern void assemble_constant_align PARA extern void assemble_alias PARAMS ((tree, tree)); +extern void assemble_visibility PARAMS ((tree, const char *)); + /* Output a string of literal assembler code for an `asm' keyword used between functions. */ extern void assemble_asm PARAMS ((tree)); --- gcc/tree.h 2002/02/20 00:19:33 1.308 +++ gcc/tree.h 2002/02/26 21:17:14 1.309 @@ -2283,6 +2283,11 @@ extern tree merge_attributes PARAMS ((t extern tree merge_dllimport_decl_attributes PARAMS ((tree, tree)); #endif +/* Return true if DECL will be always resolved to a symbol defined in the + same module (shared library or program). */ +#define MODULE_LOCAL_P(DECL) \ + (lookup_attribute ("visibility", DECL_ATTRIBUTES (DECL)) != NULL) + /* Return a version of the TYPE, qualified as indicated by the TYPE_QUALS, if one exists. If no qualified version exists yet, return NULL_TREE. */ --- gcc/crtstuff.c 2002/02/05 10:31:01 1.54 +++ gcc/crtstuff.c 2002/02/26 21:17:14 1.55 @@ -213,13 +213,9 @@ STATIC void *__JCR_LIST__[] in one DSO or the main program is not used in another object. The dynamic linker takes care of this. */ -/* XXX Ideally the following should be implemented using - __attribute__ ((__visibility__ ("hidden"))) - but the __attribute__ support is not yet there. */ #ifdef HAVE_GAS_HIDDEN -asm (".hidden\t__dso_handle"); +extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); #endif - #ifdef CRTSTUFFS_O void *__dso_handle = &__dso_handle; #else --- gcc/config/i386/i386.h 2002/02/17 07:52:12 1.243 +++ gcc/config/i386/i386.h 2002/02/26 21:17:18 1.244 @@ -2266,7 +2266,9 @@ do { \ \ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ - || ! TREE_PUBLIC (DECL)); \ + || ! TREE_PUBLIC (DECL) \ + || (TREE_CODE (DECL) == VAR_DECL \ + && MODULE_LOCAL_P (DECL))); \ } \ } \ } while (0) --- gcc/config/ia64/ia64.c 2002/01/21 02:24:02 1.139 +++ gcc/config/ia64/ia64.c 2002/02/26 22:41:48 1.141 @@ -6897,13 +6904,14 @@ ia64_encode_section_info (decl) statically allocated, but the space is allocated somewhere else. Such decls can not be own data. */ if (! TARGET_NO_SDATA - && TREE_STATIC (decl) && ! DECL_EXTERNAL (decl) - && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl)) - && ! (TREE_PUBLIC (decl) - && (flag_pic - || (DECL_COMMON (decl) - && (DECL_INITIAL (decl) == 0 - || DECL_INITIAL (decl) == error_mark_node)))) + && ((TREE_STATIC (decl) && ! DECL_EXTERNAL (decl) + && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl)) + && ! (TREE_PUBLIC (decl) + && (flag_pic + || (DECL_COMMON (decl) + && (DECL_INITIAL (decl) == 0 + || DECL_INITIAL (decl) == error_mark_node))))) + || MODULE_LOCAL_P (decl)) /* Either the variable must be declared without a section attribute, or the section must be sdata or sbss. */ && (DECL_SECTION_NAME (decl) == 0 @@ -6923,9 +6931,12 @@ ia64_encode_section_info (decl) ; /* If this is an incomplete type with size 0, then we can't put it in - sdata because it might be too big when completed. */ - else if (size > 0 - && size <= (HOST_WIDE_INT) ia64_section_threshold + sdata because it might be too big when completed. + Objects bigger than threshold should have SDATA_NAME_FLAG_CHAR + added if they are in .sdata or .sbss explicitely. */ + else if (((size > 0 + && size <= (HOST_WIDE_INT) ia64_section_threshold) + || DECL_SECTION_NAME (decl)) && symbol_str[0] != SDATA_NAME_FLAG_CHAR) { size_t len = strlen (symbol_str); --- gcc/doc/extend.texi 2002/02/23 12:59:07 1.64 +++ gcc/doc/extend.texi 2002/02/26 21:17:17 1.65 @@ -2198,7 +2198,7 @@ The @code{alias} attribute causes the de alias for another symbol, which must be specified. For instance, @smallexample -void __f () @{ /* do something */; @} +void __f () @{ /* @r{Do something.} */; @} void f () __attribute__ ((weak, alias ("__f"))); @end smallexample @@ -2206,6 +2206,19 @@ declares @samp{f} to be a weak alias for mangled name for the target must be used. Not all target machines support this attribute. + +@item visibility ("@var{visibility_type}") +@cindex @code{visibility} attribute +The @code{visibility} attribute on ELF targets causes the declaration +to be emitted with hidden, protected or internal visibility. + +@smallexample +void __attribute__ ((visibility ("protected"))) +f () @{ /* @r{Do something.} */; @} +int i __attribute__ ((visibility ("hidden"))); +@end smallexample + +Not all ELF targets support this attribute. @item regparm (@var{number}) @cindex functions that are passed arguments in registers on the 386 --- gcc/testsuite/gcc.dg/ia64-visibility-1.c.jj Tue Feb 26 12:30:32 2002 +++ gcc/testsuite/gcc.dg/ia64-visibility-1.c Tue Feb 26 12:33:26 2002 @@ -0,0 +1,36 @@ +/* Test visibility attribute. */ +/* { dg-do compile { target ia64*-*-linux* } } */ +/* { dg-options "-O2 -fpic" } */ +/* { dg-final { scan-assembler "\\.hidden.*variable_j" } } */ +/* { dg-final { scan-assembler "\\.hidden.*variable_m" } } */ +/* { dg-final { scan-assembler "\\.protected.*baz" } } */ +/* { dg-final { scan-assembler "gprel.*variable_i" } } */ +/* { dg-final { scan-assembler "gprel.*variable_j" } } */ +/* { dg-final { scan-assembler "ltoff.*variable_k" } } */ +/* { dg-final { scan-assembler "gprel.*variable_l" } } */ +/* { dg-final { scan-assembler "gprel.*variable_m" } } */ +/* { dg-final { scan-assembler "ltoff.*variable_n" } } */ + +static int variable_i; +int variable_j __attribute__((visibility ("hidden"))); +int variable_k; +struct A { char a[64]; }; +static struct A variable_l __attribute__((section (".sbss"))); +struct A variable_m __attribute__((visibility ("hidden"), section(".sbss"))); +struct A variable_n __attribute__((section (".sbss"))); + +int foo (void) +{ + return variable_i + variable_j + variable_k; +} + +void bar (void) +{ + variable_l.a[10] = 0; + variable_m.a[10] = 0; + variable_n.a[10] = 0; +} + +void __attribute__((visibility ("protected"))) baz (void) +{ +}