diff -aur gcc-3.4.0orig/gcc/c-common.c gcc-3.4.0/gcc/c-common.c --- gcc-3.4.0orig/gcc/c-common.c 2004-03-19 01:32:59.000000000 +0000 +++ gcc-3.4.0/gcc/c-common.c 2004-05-10 21:05:33.000000000 +0100 @@ -833,7 +833,7 @@ handle_deprecated_attribute }, { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute }, - { "visibility", 1, 1, true, false, false, + { "visibility", 1, 1, false, false, false, handle_visibility_attribute }, { "tls_model", 1, 1, true, false, false, handle_tls_model_attribute }, @@ -4886,7 +4886,16 @@ *no_add_attrs = true; - if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)) + if (TYPE_P (*node)) + { + if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) + { + warning ("`%s' attribute ignored on non-class types", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + } + else if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)) { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); return NULL_TREE; @@ -4897,6 +4906,14 @@ error ("visibility arg not a string"); return NULL_TREE; } + + /* 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 (strcmp (TREE_STRING_POINTER (id), "default") == 0) DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; @@ -4908,6 +4925,14 @@ DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; else error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + DECL_VISIBILITYSPECIFIED (decl) = 1; + + /* 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; } diff -aur gcc-3.4.0orig/gcc/c-decl.c gcc-3.4.0/gcc/c-decl.c --- gcc-3.4.0orig/gcc/c-decl.c 2004-03-22 17:58:18.000000000 +0000 +++ gcc-3.4.0/gcc/c-decl.c 2004-05-10 15:16:27.000000000 +0100 @@ -1164,9 +1164,8 @@ } /* warnings */ - /* All decls must agree on a non-default visibility. */ - if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT - && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT + /* All decls must agree on a visibility. */ + if (DECL_VISIBILITYSPECIFIED (newdecl) && DECL_VISIBILITYSPECIFIED (olddecl) && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) { warning ("%Jredeclaration of '%D' with different visibility " @@ -1361,9 +1360,12 @@ Currently, it can only be defined in the prototype. */ COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); - /* If either declaration has a nondefault visibility, use it. */ - if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT) - DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); + /* Use visibility of whichever declaration had it specified */ + if (DECL_VISIBILITYSPECIFIED (olddecl)) + { + DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); + DECL_VISIBILITYSPECIFIED (newdecl) = 1; + } if (TREE_CODE (newdecl) == FUNCTION_DECL) { diff -aur gcc-3.4.0orig/gcc/common.opt gcc-3.4.0/gcc/common.opt --- gcc-3.4.0orig/gcc/common.opt 2004-02-18 00:09:04.000000000 +0000 +++ gcc-3.4.0/gcc/common.opt 2004-05-09 08:10:50.000000000 +0100 @@ -718,6 +718,11 @@ Common Add extra commentary to assembler output +fvisibility= +Common Joined RejectNegative +-fvisibility=[default|internal|hidden|protected] Set the default symbol visibility + + fvpt Common Use expression value profiles in optimizations diff -aur gcc-3.4.0orig/gcc/c.opt gcc-3.4.0/gcc/c.opt --- gcc-3.4.0orig/gcc/c.opt 2004-02-18 00:09:03.000000000 +0000 +++ gcc-3.4.0/gcc/c.opt 2004-05-09 08:10:50.000000000 +0100 @@ -656,6 +656,10 @@ C++ ObjC++ Use __cxa_atexit to register destructors +fvisibility-inlines-hidden +C++ +Marks all inlined methods as having hidden visibility + fvtable-gc C++ ObjC++ Discard unused virtual functions diff -aur gcc-3.4.0orig/gcc/c-opts.c gcc-3.4.0/gcc/c-opts.c --- gcc-3.4.0orig/gcc/c-opts.c 2004-02-18 00:09:03.000000000 +0000 +++ gcc-3.4.0/gcc/c-opts.c 2004-05-09 08:10:50.000000000 +0100 @@ -912,6 +912,10 @@ case OPT_fuse_cxa_atexit: flag_use_cxa_atexit = value; break; + + case OPT_fvisibility_inlines_hidden: + visibility_options.inlineshidden = value; + break; case OPT_fweak: flag_weak = value; diff -aur gcc-3.4.0orig/gcc/cp/class.c gcc-3.4.0/gcc/cp/class.c --- gcc-3.4.0orig/gcc/cp/class.c 2004-03-09 07:27:23.000000000 +0000 +++ gcc-3.4.0/gcc/cp/class.c 2004-05-10 21:06:50.000000000 +0100 @@ -524,6 +524,10 @@ 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) = CLASSTYPE_VISIBILITY (class_type); + DECL_VISIBILITYSPECIFIED (decl) = CLASSTYPE_VISIBILITYSPECIFIED (class_type); import_export_vtable (decl, class_type, 0); return decl; @@ -2971,7 +2975,25 @@ continue; if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL) - continue; + { + /* 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.inlineshidden && DECL_INLINE (x)) + { + DECL_VISIBILITY (x) = VISIBILITY_HIDDEN; + DECL_VISIBILITYSPECIFIED (x) = 1; + } + else + { + DECL_VISIBILITY (x) = CLASSTYPE_VISIBILITY (current_class_type); + DECL_VISIBILITYSPECIFIED (x) = CLASSTYPE_VISIBILITYSPECIFIED (current_class_type); + } + } + + continue; + } /* Now it can only be a FIELD_DECL. */ @@ -3708,6 +3730,22 @@ 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.inlineshidden && DECL_INLINE (x)) + { + DECL_VISIBILITY (x) = VISIBILITY_HIDDEN; + DECL_VISIBILITYSPECIFIED (x) = 1; + } + else + { + DECL_VISIBILITY (x) = CLASSTYPE_VISIBILITY (current_class_type); + DECL_VISIBILITYSPECIFIED (x) = CLASSTYPE_VISIBILITYSPECIFIED (current_class_type); + } + } /* The name of the field is the original field name Save this in auxiliary field for later overloading. */ @@ -7830,3 +7868,4 @@ *vid->last_init = build_tree_list (NULL_TREE, init); vid->last_init = &TREE_CHAIN (*vid->last_init); } + diff -aur gcc-3.4.0orig/gcc/cp/cp-tree.h gcc-3.4.0/gcc/cp/cp-tree.h --- gcc-3.4.0orig/gcc/cp/cp-tree.h 2004-03-20 00:13:08.000000000 +0000 +++ gcc-3.4.0/gcc/cp/cp-tree.h 2004-05-10 20:56:56.000000000 +0100 @@ -1008,7 +1008,12 @@ #define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \ (lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL) \ != NULL_TREE) - + +/* Gives the visibility specification for a class type. */ +#define CLASSTYPE_VISIBILITY(TYPE) DECL_VISIBILITY (TYPE_NAME (TYPE)) +#define CLASSTYPE_VISIBILITYSPECIFIED(TYPE) DECL_VISIBILITYSPECIFIED (TYPE_NAME (TYPE)) + + /* This is a few header flags for 'struct lang_type'. Actually, all but the first are used only for lang_type_class; they are put in this structure to save space. */ diff -aur gcc-3.4.0orig/gcc/cp/decl.c gcc-3.4.0/gcc/cp/decl.c --- gcc-3.4.0orig/gcc/cp/decl.c 2004-04-01 21:47:21.000000000 +0100 +++ gcc-3.4.0/gcc/cp/decl.c 2004-05-28 21:16:11.000000000 +0100 @@ -1869,17 +1869,34 @@ DECL_COMMON (newdecl) = DECL_COMMON (olddecl); COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); - /* If either declaration has a nondefault visibility, use it. */ - if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT) + /* Warn about conflicting visibility specifications. */ + if (DECL_VISIBILITYSPECIFIED (olddecl) && DECL_VISIBILITYSPECIFIED (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_VISIBILITYSPECIFIED (olddecl)) { - if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT - && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) - { - warning ("%J'%D': visibility attribute ignored because it", - newdecl, newdecl); - warning ("%Jconflicts with previous declaration here", olddecl); - } DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl); + DECL_VISIBILITYSPECIFIED (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_VISIBILITYSPECIFIED (olddecl) = 1; + DECL_VISIBILITY (newdecl) = VISIBILITY_DEFAULT; + DECL_VISIBILITYSPECIFIED (newdecl) = 1; + } } if (TREE_CODE (newdecl) == FUNCTION_DECL) diff -aur gcc-3.4.0orig/gcc/cp/method.c gcc-3.4.0/gcc/cp/method.c --- gcc-3.4.0orig/gcc/cp/method.c 2004-04-08 23:15:58.000000000 +0100 +++ gcc-3.4.0/gcc/cp/method.c 2004-05-09 08:10:52.000000000 +0100 @@ -394,6 +394,7 @@ rewrite. */ TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); + DECL_VISIBILITYSPECIFIED (thunk_fndecl) = DECL_VISIBILITYSPECIFIED (function); if (flag_syntax_only) { diff -aur gcc-3.4.0orig/gcc/cp/optimize.c gcc-3.4.0/gcc/cp/optimize.c --- gcc-3.4.0orig/gcc/cp/optimize.c 2004-02-08 01:52:50.000000000 +0000 +++ gcc-3.4.0/gcc/cp/optimize.c 2004-05-09 08:10:52.000000000 +0100 @@ -155,6 +155,7 @@ DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); TREE_PUBLIC (clone) = TREE_PUBLIC (fn); DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); + DECL_VISIBILITYSPECIFIED (clone) = DECL_VISIBILITYSPECIFIED (fn); /* Adjust the parameter names and locations. */ parm = DECL_ARGUMENTS (fn); diff -aur gcc-3.4.0orig/gcc/cp/rtti.c gcc-3.4.0/gcc/cp/rtti.c --- gcc-3.4.0orig/gcc/cp/rtti.c 2004-03-08 23:00:26.000000000 +0000 +++ gcc-3.4.0/gcc/cp/rtti.c 2004-05-10 21:09:21.000000000 +0100 @@ -361,7 +361,11 @@ pushdecl_top_level_and_finish (d, NULL_TREE); if (CLASS_TYPE_P (type)) - CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; + { + CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; + DECL_VISIBILITY (d) = CLASSTYPE_VISIBILITY (type); + DECL_VISIBILITYSPECIFIED (d) = CLASSTYPE_VISIBILITYSPECIFIED (type); + } /* Remember the type it is for. */ TREE_TYPE (name) = type; @@ -759,6 +763,11 @@ TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; TREE_PUBLIC (name_decl) = 1; + if (CLASS_TYPE_P (target)) + { + DECL_VISIBILITY (name_decl) = CLASSTYPE_VISIBILITY (target); + DECL_VISIBILITYSPECIFIED (name_decl) = CLASSTYPE_VISIBILITYSPECIFIED (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. */ diff -aur gcc-3.4.0orig/gcc/c-pragma.c gcc-3.4.0/gcc/c-pragma.c --- gcc-3.4.0orig/gcc/c-pragma.c 2004-01-23 23:35:53.000000000 +0000 +++ gcc-3.4.0/gcc/c-pragma.c 2004-05-09 08:10:52.000000000 +0100 @@ -480,6 +480,86 @@ return asmname; } + +#ifdef HANDLE_PRAGMA_VISIBILITY +static void handle_pragma_visibility (cpp_reader *); + +/* Sets the default visibility for symbols to something other than that + specified on the command line. */ +static void +handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) +{ /* Form is #pragma GCC visibility push(hidden)|pop */ + static int visstack [16], visidx; + tree x; + enum cpp_ttype token; + enum { bad, push, pop } action = bad; + + token = c_lex (&x); + if (token == CPP_NAME) + { + const char *op = IDENTIFIER_POINTER (x); + if (!strcmp (op, "push")) + action = push; + else if (!strcmp (op, "pop")) + action = pop; + } + if (bad == action) + GCC_BAD ("#pragma GCC visibility must be followed by push or pop"); + else + { + if (pop == action) + { + if (!visidx) + { + GCC_BAD ("No matching push for '#pragma GCC visibility pop'"); + } + else + { + default_visibility = visstack[--visidx]; + visibility_options.inpragma = (visidx>0); + } + } + else + { + if (c_lex (&x) != CPP_OPEN_PAREN) + GCC_BAD ("missing '(' after '#pragma GCC visibility push' - ignored"); + token = c_lex (&x); + if (token != CPP_NAME) + { + GCC_BAD ("malformed #pragma GCC visibility push"); + } + else if (visidx >= 16) + { + GCC_BAD ("No more than sixteen #pragma GCC visibility pushes allowed at once"); + } + else + { + const char *str = IDENTIFIER_POINTER (x); + visstack[visidx++] = default_visibility; + if (!strcmp (str, "default")) + default_visibility = VISIBILITY_DEFAULT; + else if (!strcmp (str, "internal")) + default_visibility = VISIBILITY_INTERNAL; + else if (!strcmp (str, "hidden")) + default_visibility = VISIBILITY_HIDDEN; + else if (!strcmp (str, "protected")) + default_visibility = VISIBILITY_PROTECTED; + else + { + GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected"); + } + visibility_options.inpragma = 1; + } + if (c_lex (&x) != CPP_CLOSE_PAREN) + GCC_BAD ("missing '(' after '#pragma GCC visibility push' - ignored"); + } + } + if (c_lex (&x) != CPP_EOF) + warning ("junk at end of '#pragma GCC visibility'"); +} + +#endif + /* Front-end wrapper for pragma registration to avoid dragging cpplib.h in almost everywhere. */ void @@ -505,6 +585,9 @@ #ifdef HANDLE_PRAGMA_EXTERN_PREFIX c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix); #endif +#ifdef HANDLE_PRAGMA_VISIBILITY + c_register_pragma ("GCC", "visibility", handle_pragma_visibility); +#endif #ifdef REGISTER_TARGET_PRAGMAS REGISTER_TARGET_PRAGMAS (); diff -aur gcc-3.4.0orig/gcc/c-pragma.h gcc-3.4.0/gcc/c-pragma.h --- gcc-3.4.0orig/gcc/c-pragma.h 2004-01-31 06:18:05.000000000 +0000 +++ gcc-3.4.0/gcc/c-pragma.h 2004-05-09 08:10:53.000000000 +0100 @@ -44,6 +44,11 @@ #define HANDLE_PRAGMA_PACK 1 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */ +/* It's safe to always leave visibility pragma enabled as if + visibility is not supported on the host OS platform the + statements are ignored. */ +#define HANDLE_PRAGMA_VISIBILITY 1 + extern void init_pragma (void); /* Front-end wrapper for pragma registration to avoid dragging diff -aur gcc-3.4.0orig/gcc/doc/invoke.texi gcc-3.4.0/gcc/doc/invoke.texi --- gcc-3.4.0orig/gcc/doc/invoke.texi 2004-04-19 00:05:36.000000000 +0100 +++ gcc-3.4.0/gcc/doc/invoke.texi 2004-05-28 21:29:36.000000000 +0100 @@ -183,7 +183,8 @@ -fno-optional-diags -fpermissive @gol -frepo -fno-rtti -fstats -ftemplate-depth-@var{n} @gol -fuse-cxa-atexit -fno-weak -nostdinc++ @gol --fno-default-inline -Wabi -Wctor-dtor-privacy @gol +-fno-default-inline -fvisibility-inlines-hidden @gol +-Wabi -Wctor-dtor-privacy @gol -Wnon-virtual-dtor -Wreorder @gol -Weffc++ -Wno-deprecated @gol -Wno-non-template-friend -Wold-style-cast @gol @@ -674,7 +675,8 @@ -fargument-alias -fargument-noalias @gol -fargument-noalias-global -fleading-underscore @gol -ftls-model=@var{model} @gol --ftrapv -fwrapv -fbounds-check} +-ftrapv -fwrapv -fbounds-check @gol +-fvisibility} @end table @menu @@ -1433,6 +1435,20 @@ destructors, but will only work if your C library supports @code{__cxa_atexit}. +@item -fvisibility-inlines-hidden +@opindex fvisibility-inlines-hidden +Causes all inlined methods to be marked with +@code{__attribute__ ((visibility ("hidden")))} so that they do not +appear in the export table of a DSO and do not require a PLT indirection +when used within the DSO. Enabling this option can have a dramatic effect +on load and link times of a DSO as it massively reduces the size of the +dynamic export table when the library makes heavy use of templates. While +it can cause bloating through duplication of code within each DSO where +it is used, often the wastage is less than the considerable space occupied +by a long symbol name in the export table which is typical when using +templates and namespaces. For even more savings, combine with the +@code{-fvisibility=hidden} switch. + @item -fno-weak @opindex fno-weak Do not use weak symbol support, even if it is provided by the linker. @@ -11198,6 +11214,54 @@ The default without @option{-fpic} is @code{initial-exec}; with @option{-fpic} the default is @code{global-dynamic}. + +@item -fvisibility=@var{default|internal|hidden|protected} +@opindex fvisibility +Set the default ELF image symbol visibility to the specified option - all +symbols will be marked with this unless overrided within the code. +Using this feature can very substantially improve linking and +load times of shared object libraries, produce more optimised +code, provide near-perfect API export and prevent symbol clashes. +It is @strong{strongly} recommended that you use this in any shared objects +you distribute. + +Despite the nomenclature, @code{default} always means public ie; +available to be linked against from outside the shared object. +@code{protected} and @code{internal} are pretty useless in real-world +usage so the only other commonly used option will be @code{hidden}. +The default if -fvisibility isn't specified is @code{default} ie; make every +symbol public - this causes the same behaviour as previous versions of +GCC. + +A good explanation of the benefits offered by ensuring ELF +symbols have the correct visibility is given by ``How To Write +Shared Libraries'' by Ulrich Drepper (which can be found at +@w{@uref{http://people.redhat.com/~drepper/}}) - however a superior +solution made possible by this option to marking things hidden when +the default is public is to make the default hidden and mark things +public. This is the norm with DLL's on Windows and with @option{-fvisibility=hidden} +and @code{__attribute__ ((visibility("default")))} instead of +@code{__declspec(dllexport)} you get almost identical semantics with +identical syntax. This is a great boon to those working with +cross-platform projects. + +For those adding visibility support to existing code, you may find +@samp{#pragma GCC visibility} of use. This works by you enclosing +the declarations you wish to set visibility for with (for example) +@samp{#pragma GCC visibility push(hidden)} and +@samp{#pragma GCC visibility pop}. These can be nested up to sixteen +times. Bear in mind that symbol visibility should be viewed @strong{as +part of the API interface contract} and thus all new code should +always specify visibility when it is not the default ie; declarations +only for use within the local DSO should @strong{always} be marked explicitly +as hidden as so to avoid PLT indirection overheads - making this +abundantly clear also aids readability and self-documentation of the code. +Note that due to ISO C++ specification requirements, operator new and +operator delete must always be of default visibility. + +An overview of these techniques, their benefits and how to use them +is at @w{@uref{http://www.nedprod.com/programs/gccvisibility.html}}. + @end table @c man end diff -aur gcc-3.4.0orig/gcc/flags.h gcc-3.4.0/gcc/flags.h --- gcc-3.4.0orig/gcc/flags.h 2004-02-18 00:09:04.000000000 +0000 +++ gcc-3.4.0/gcc/flags.h 2004-05-09 08:10:53.000000000 +0100 @@ -60,6 +60,30 @@ /* Nonzero means emit debugging information only for symbols which are used. */ extern int flag_debug_only_used_symbols; +/* Enumerate visibility settings. */ +#ifndef SYMBOL_VISIBILITY_DEFINED +#define SYMBOL_VISIBILITY_DEFINED +enum symbol_visibility +{ + VISIBILITY_DEFAULT, + VISIBILITY_INTERNAL, + VISIBILITY_HIDDEN, + VISIBILITY_PROTECTED +}; +#endif + +/* The default visibility for all symbols (unless overridden). */ +extern enum symbol_visibility default_visibility; + +struct visibility_flags +{ + unsigned inpragma : 1; /* True when in #pragma GCC visibility. */ + unsigned inlineshidden : 1; /* True when -finlineshidden in effect. */ +}; + +/* Global visibility options. */ +extern struct visibility_flags visibility_options; + /* Nonzero means do optimizations. -opt. */ extern int optimize; diff -aur gcc-3.4.0orig/gcc/opts.c gcc-3.4.0/gcc/opts.c --- gcc-3.4.0orig/gcc/opts.c 2004-02-18 00:09:04.000000000 +0000 +++ gcc-3.4.0/gcc/opts.c 2004-05-09 08:10:53.000000000 +0100 @@ -142,6 +142,12 @@ write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ bool use_gnu_debug_info_extensions; +/* The default visibility for all symbols (unless overridden) */ +enum symbol_visibility default_visibility = VISIBILITY_DEFAULT; + +/* Global visibility options. */ +struct visibility_flags visibility_options; + /* Columns of --help display. */ static unsigned int columns = 80; @@ -1440,6 +1446,21 @@ flag_verbose_asm = value; break; + case OPT_fvisibility_: + { + if(!strcmp(arg, "default")) + default_visibility=VISIBILITY_DEFAULT; + else if(!strcmp(arg, "internal")) + default_visibility=VISIBILITY_INTERNAL; + else if(!strcmp(arg, "hidden")) + default_visibility=VISIBILITY_HIDDEN; + else if(!strcmp(arg, "protected")) + default_visibility=VISIBILITY_PROTECTED; + else + error("unrecognised visibility value \"%s\"", arg); + } + break; + case OPT_fweb: flag_web = value; break; diff -aur gcc-3.4.0orig/gcc/tree.c gcc-3.4.0/gcc/tree.c --- gcc-3.4.0orig/gcc/tree.c 2004-02-05 22:01:35.000000000 +0000 +++ gcc-3.4.0/gcc/tree.c 2004-05-10 15:22:52.000000000 +0100 @@ -2563,6 +2563,11 @@ layout_decl (t, 0); else if (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; + + /* Set default visibility to whatever the user supplied with + visibility_specified depending on #pragma GCC visibility. */ + DECL_VISIBILITY (t) = default_visibility; + DECL_VISIBILITYSPECIFIED (t) = visibility_options.inpragma; return t; } diff -aur gcc-3.4.0orig/gcc/tree.h gcc-3.4.0/gcc/tree.h --- gcc-3.4.0orig/gcc/tree.h 2004-02-08 01:52:43.000000000 +0000 +++ gcc-3.4.0/gcc/tree.h 2004-05-09 08:10:54.000000000 +0100 @@ -1499,6 +1499,10 @@ /* Value of the decls's visibility attribute */ #define DECL_VISIBILITY(NODE) (DECL_CHECK (NODE)->decl.visibility) +/* Nonzero means that the decl had its visibility specified rather than + being inferred. */ +#define DECL_VISIBILITYSPECIFIED(NODE) (DECL_CHECK (NODE)->decl.visibility_specified) + /* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */ #define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable) @@ -1633,7 +1637,8 @@ || TREE_CODE (DECL_CONTEXT (EXP)) == TRANSLATION_UNIT_DECL) /* Enumerate visibility settings. */ - +#ifndef SYMBOL_VISIBILITY_DEFINED +#define SYMBOL_VISIBILITY_DEFINED enum symbol_visibility { VISIBILITY_DEFAULT, @@ -1641,6 +1646,7 @@ VISIBILITY_HIDDEN, VISIBILITY_PROTECTED }; +#endif struct function; @@ -1684,8 +1690,7 @@ unsigned thread_local_flag : 1; unsigned declared_inline_flag : 1; ENUM_BITFIELD(symbol_visibility) visibility : 2; - unsigned unused : 1; - /* one unused bit. */ + unsigned visibility_specified : 1; unsigned lang_flag_0 : 1; unsigned lang_flag_1 : 1; diff -aur gcc-3.4.0orig/gcc/varasm.c gcc-3.4.0/gcc/varasm.c --- gcc-3.4.0orig/gcc/varasm.c 2004-04-14 22:14:08.000000000 +0100 +++ gcc-3.4.0/gcc/varasm.c 2004-05-09 08:10:54.000000000 +0100 @@ -5150,8 +5150,8 @@ /* Static variables are always local. */ 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) + /* A variable is local if the user explicitly tells us so. */ + else if (DECL_VISIBILITYSPECIFIED (exp) && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) local_p = true; /* Otherwise, variables defined outside this object may not be local. */ else if (DECL_EXTERNAL (exp)) @@ -5159,6 +5159,9 @@ /* Linkonce and weak data are never local. */ else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp)) local_p = false; + /* If none of the above and visibility is not default, make local. */ + else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) + local_p = true; /* If PIC, then assume that any global name can be overridden by symbols resolved from other modules. */ else if (shlib)