aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNiall Douglas <s_fsfeurope2@nedprod.com>2004-07-25 22:52:22 +0000
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-07-25 22:52:22 +0000
commitd7afec4b079f40ba7857ae1c898ed537b5c14313 (patch)
treef9985edc87f0241509ea6f38be708082bb83209a /gcc/cp
parent28dab13236a7f958a8dc533363dcbe8e18eeeae5 (diff)
downloadgcc-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/ChangeLog22
-rw-r--r--gcc/cp/class.c41
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/decl.c35
-rw-r--r--gcc/cp/method.c1
-rw-r--r--gcc/cp/optimize.c1
-rw-r--r--gcc/cp/rtti.c11
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. */