diff options
author | Niall Douglas <s_fsfeurope2@nedprod.com> | 2004-07-25 22:52:22 +0000 |
---|---|---|
committer | Giovanni Bajo <giovannibajo@gcc.gnu.org> | 2004-07-25 22:52:22 +0000 |
commit | d7afec4b079f40ba7857ae1c898ed537b5c14313 (patch) | |
tree | f9985edc87f0241509ea6f38be708082bb83209a /gcc/cp | |
parent | 28dab13236a7f958a8dc533363dcbe8e18eeeae5 (diff) | |
download | gcc-d7afec4b079f40ba7857ae1c898ed537b5c14313.zip gcc-d7afec4b079f40ba7857ae1c898ed537b5c14313.tar.gz gcc-d7afec4b079f40ba7857ae1c898ed537b5c14313.tar.bz2 |
re PR c++/9283 (__attribute__((visibility ("hidden"))) not supported for class/struct)
PR c++/9283
PR c++/15000
* 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. Added
warning if attribute applied to non class type.
* c-decl.c (diagnose_mismatched_decls): Updated rules for merging
decls and checking that they are consistent.
* common.opt: Added -fvisibility.
* c.opt, c-opts.c: Added -fvisibility-inlines-hidden.
* c-pragma.h, c-pragma.c: Added handle_pragma_visibility().
* flags.h, tree.h: Added assorted support defines for overall patch
* opts.c: Added parsing support for -fvisibility.
* tree.c (build_decl): Set visibility for all decls to be whatever
is in force at that time.
* varasm.c (default_binds_local_p_1): Reworked logic determining
when to make a symbol locally bound.
* doc/invoke.texi: Added documentation for -fvisibility and
-fvisibility-inlines-hidden.
PR c++/15000
PR c++/9283
* class.c (check_field_decls): Apply hidden visibility if
-fvisibility-inlines-hidden and inlined unless otherwise specified
(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.
* cp-tree.h: Added CLASSTYPE_VISIBILITY and
CLASSTYPE_VISIBILITY_SPECIFIED macro.
* decl.c (duplicate_decls): New logic for merging definition decls
with declaration decls. Added ignore & warning when non default
applied to global operator new or delete.
* method.c, optimize.c, rtti.c: Added setting of VISIBILITY_SPECIFIED
wherever VISIBILITY was changed
* rtti.c (get_tinfo_decl): Set typeinfo visibility to class
visibility.
(tinfo_base_init): Set typeinfo name visibility to class visibility.
PR c++/9283
PR c++/15000
* gcc.dg/visibility-9.c, gcc.dg/visibility-a.c: New tests.
* g++.dg/ext/visibility/: New directory.
* g++.dg/ext/visibility-1.C, g++.dg/ext/visibility-2.C
g++.dg/ext/visibility-3.C, g++.dg/ext/visibility-4.C,
g++.dg/ext/visibility-5.C, g++.dg/ext/visibility-6.C,
g++.dg/ext/visibility-7.C: Move to g++.dg/ext/visibility/.
* g++.dg/ext/visibility/fvisibility.C,
g++.dg/ext/visibility/fvisibility-inlines-hidden.C,
g++.dg/ext/visibility/fvisibility-override1.C
g++.dg/ext/visibility/fvisibility-override2.C
g++.dg/ext/visibility/memfuncts.C
g++.dg/ext/visibility/noPLT.C
g++.dg/ext/visibility/pragma.C
g++.dg/ext/visibility/pragma-override1.C
g++.dg/ext/visibility/pragma-override2.C
g++.dg/ext/visibility/staticmemfuncts.C
g++.dg/ext/visibility/virtual.C: New tests.
Co-Authored-By: Brian Ryner <bryner@brianryner.com>
From-SVN: r85167
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/cp/class.c | 41 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 35 | ||||
-rw-r--r-- | gcc/cp/method.c | 1 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 1 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 11 |
7 files changed, 106 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bbcd038..182f373 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +2004-07-26 Niall Douglas <s_fsfeurope2@nedprod.com>
+ Brian Ryner <bryner@brianryner.com>
+
+ PR c++/15000
+ PR c++/9283
+ * class.c (check_field_decls): Apply hidden visibility if
+ -fvisibility-inlines-hidden and inlined unless otherwise specified
+ (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.
+ * cp-tree.h: Added CLASSTYPE_VISIBILITY and
+ CLASSTYPE_VISIBILITY_SPECIFIED macro.
+ * decl.c (duplicate_decls): New logic for merging definition decls
+ with declaration decls. Added ignore & warning when non default
+ applied to global operator new or delete.
+ * method.c, optimize.c, rtti.c: Added setting of VISIBILITY_SPECIFIED
+ wherever VISIBILITY was changed
+ * rtti.c (get_tinfo_decl): Set typeinfo visibility to class
+ visibility.
+ (tinfo_base_init): Set typeinfo name visibility to class visibility.
+ 2004-07-25 Bernardo Innocenti <bernie@develer.com> * decl.c: Rename all identifiers named `class' to `cl'. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 6c0988c..f30d519 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -607,6 +607,10 @@ build_vtable (tree class_type, tree name, tree vtable_type) 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_VISIBILITY_SPECIFIED (decl) = CLASSTYPE_VISIBILITY_SPECIFIED (class_type); import_export_vtable (decl, class_type, 0); return decl; @@ -2914,7 +2918,25 @@ check_field_decls (tree t, tree *access_decls, 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.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. */ @@ -3669,6 +3691,22 @@ check_methods (tree t) 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. */ @@ -7763,3 +7801,4 @@ cp_fold_obj_type_ref (tree ref, tree known_type) return build_address (fndecl); } + diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bcbf793..e7eed5e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -931,7 +931,12 @@ enum languages { lang_c, lang_cplusplus, lang_java }; #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_VISIBILITY_SPECIFIED(TYPE) DECL_VISIBILITY_SPECIFIED (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 --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 17b391b..2a9e61f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1866,17 +1866,34 @@ duplicate_decls (tree newdecl, tree olddecl) 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_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)) { - 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_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) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d2d52bb..07fbacf 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -368,6 +368,7 @@ use_thunk (tree thunk_fndecl, bool emit_p) 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); diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 8a3ebe6..000d6cc 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -112,6 +112,7 @@ maybe_clone_body (tree fn) DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); TREE_PUBLIC (clone) = TREE_PUBLIC (fn); DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); + DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); /* Adjust the parameter names and locations. */ parm = DECL_ARGUMENTS (fn); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index b1ae3dd..7332a9a 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -360,7 +360,11 @@ get_tinfo_decl (tree type) 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_VISIBILITY_SPECIFIED (d) = CLASSTYPE_VISIBILITY_SPECIFIED (type); + } /* Remember the type it is for. */ TREE_TYPE (name) = type; @@ -758,6 +762,11 @@ tinfo_base_init (tree desc, tree target) 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_VISIBILITY_SPECIFIED (name_decl) = CLASSTYPE_VISIBILITY_SPECIFIED (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. */ |