diff options
author | Jason Merrill <jason@redhat.com> | 2006-06-29 21:15:56 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2006-06-29 21:15:56 -0400 |
commit | b9e75696307f710a22c726e72b00e7a7161ad89f (patch) | |
tree | 93c1ec7ec5a70cb4b7384fa239594ed2f1288585 /gcc/cp/decl2.c | |
parent | dc2843f38c04c81e9f20a6e9e6ae9637ace6e08c (diff) | |
download | gcc-b9e75696307f710a22c726e72b00e7a7161ad89f.zip gcc-b9e75696307f710a22c726e72b00e7a7161ad89f.tar.gz gcc-b9e75696307f710a22c726e72b00e7a7161ad89f.tar.bz2 |
re PR c++/26905 (default-visibility class symbol improperly resolved as hidden-visibility)
PR c++/26905
PR c++/26612
PR c++/27000
PR c++/26984
PR c++/19134
* tree.c (build_decl_stat): Don't hande #pragma visibility here.
* c-common.c (c_determine_visibility): Handle it here.
* c-decl.c (finish_decl): Call c_determine_visibility for
functions, too.
* flags.h (enum symbol_visibility): Sort from most to least visibility.
* tree.h: Likewise.
* varasm.c (default_assemble_visibility): Likewise.
* c-common.c (handle_visibility_attribute): Complain about trying
to give visibility to an already defined class, or trying to change
declared visibility. Always attach the attribute.
* cp/decl2.c (determine_visibility): Overhaul.
(determine_visibility_from_class): Likewise.
(min_vis_r, type_visibility, constrain_visibility): New fns.
(constrain_visibility_for_template): Likewise.
(constrain_class_visibility): Likewise.
* cp/decl.c (cp_finish_decl): Call determine_visibility for function
decls, too.
* cp/name-lookup.c (pushtag): Call determine_visibility.
* cp/decl.c (duplicate_decls): Don't copy visibility from template to
specialization.
* cp/pt.c (check_explicit_specialization): Likewise.
(lookup_template_class, tsubst_decl): Call determine_visibility.
* cp/class.c (finish_struct_1): Call constrain_class_visibility.
PR c++/26905
PR c++/21675
PR c++/17470
* cp/parser.c (cp_parser_explicit_instantiation): Pass the attributes
to grokdeclarator.
(cp_parser_type_specifier): Allow 'enum __attribute ((...)) E'.
(cp_parser_enum_specifier): Likewise.
(cp_parser_elaborated_type_specifier): Apply attributes if this
declares only the class.
(cp_parser_class_specifier): Apply leading attributes immediately.
* cp/semantics.c (begin_class_definition): Add attributes parameter,
apply them to the type.
* attribs.c (decl_attributes): Ignore type-in-place attributes
once the type has been defined.
PR c++/21581
PR c++/25915
* cp/tree.c (decl_anon_ns_mem_p): New function.
* cp/cp-tree.h: Declare it.
* cp/decl2.c (determine_visibility): Make anonymous namespace
members static.
(min_vis_r, constrain_visibility): Likewise.
* cp/rtti.c (create_pseudo_type_info): Set TREE_PUBLIC on
pseudo-types.
* cp/decl.c (cxx_init_decl_processing): Set TREE_PUBLIC on
global_namespace.
* cp/name-lookup.c (push_namespace_with_attribs): Don't set TREE_PUBLIC
on anonymous namespaces.
From-SVN: r115086
Diffstat (limited to 'gcc/cp/decl2.c')
-rw-r--r-- | gcc/cp/decl2.c | 320 |
1 files changed, 257 insertions, 63 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 80fcc29..0a12a38 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1533,6 +1533,110 @@ maybe_emit_vtables (tree ctype) return true; } +/* A special return value from type_visibility meaning internal + linkage. */ + +enum { VISIBILITY_STATIC = VISIBILITY_INTERNAL+1 }; + +/* walk_tree helper function for type_visibility. */ + +static tree +min_vis_r (tree *tp, int *walk_subtrees, void *data) +{ + int *vis_p = (int *)data; + if (! TYPE_P (*tp)) + { + *walk_subtrees = 0; + } + else if (CLASS_TYPE_P (*tp)) + { + if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp))) + { + *vis_p = VISIBILITY_STATIC; + return *tp; + } + else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p) + *vis_p = CLASSTYPE_VISIBILITY (*tp); + } + return NULL; +} + +/* Returns the visibility of TYPE, which is the minimum visibility of its + component types. */ + +static int +type_visibility (tree type) +{ + int vis = VISIBILITY_DEFAULT; + walk_tree_without_duplicates (&type, min_vis_r, &vis); + return vis; +} + +/* Limit the visibility of DECL to VISIBILITY. SPECIFIED is true if the + constraint comes from an attribute or pragma; REASON is the source of + the constraint. */ + +static bool +constrain_visibility (tree decl, int visibility, bool specified, + const char *reason) +{ + if (visibility == VISIBILITY_STATIC) + { + TREE_PUBLIC (decl) = 0; + DECL_INTERFACE_KNOWN (decl) = 1; + if (DECL_LANG_SPECIFIC (decl)) + DECL_NOT_REALLY_EXTERN (decl) = 1; + } + else if (visibility > DECL_VISIBILITY (decl)) + { + if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + warning (OPT_Wattributes, "%q+D: visibility attribute requests " + "greater visibility than its %s allows", decl, reason); + DECL_VISIBILITY (decl) = visibility; + if (!DECL_VISIBILITY_SPECIFIED (decl)) + DECL_VISIBILITY_SPECIFIED (decl) = specified; + return true; + } + return false; +} + +/* Constrain the visibility of DECL based on the visbility of its template + arguments. */ + +static void +constrain_visibility_for_template (tree decl, tree targs) +{ + /* If this is a template instantiation, check the innermost + template args for visibility constraints. The outer template + args are covered by the class check. */ + tree args = INNERMOST_TEMPLATE_ARGS (targs); + int i; + for (i = TREE_VEC_LENGTH (args); i > 0; --i) + { + int vis = 0; + + tree arg = TREE_VEC_ELT (args, i-1); + if (TYPE_P (arg)) + vis = type_visibility (arg); + else if (TREE_TYPE (arg) && POINTER_TYPE_P (TREE_TYPE (arg))) + { + STRIP_NOPS (arg); + if (TREE_CODE (arg) == ADDR_EXPR) + arg = TREE_OPERAND (arg, 0); + if (TREE_CODE (arg) == VAR_DECL + || TREE_CODE (arg) == FUNCTION_DECL) + { + if (! TREE_PUBLIC (arg)) + vis = VISIBILITY_STATIC; + else + vis = DECL_VISIBILITY (arg); + } + } + if (vis) + constrain_visibility (decl, vis, false, "template parameter"); + } +} + /* Like c_determine_visibility, but with additional C++-specific behavior. @@ -1544,12 +1648,18 @@ maybe_emit_vtables (tree ctype) Note that because namespaces have multiple independent definitions, namespace visibility is handled elsewhere using the #pragma visibility - machinery rather than by decorating the namespace declaration. */ + machinery rather than by decorating the namespace declaration. + + The goal is for constraints from the type to give a diagnostic, and + other constraints to be applied silently. */ void determine_visibility (tree decl) { - tree class_type; + tree class_type = NULL_TREE; + bool use_template; + + /* Remember that all decls get VISIBILITY_DEFAULT when built. */ /* Only relevant for names with external linkage. */ if (!TREE_PUBLIC (decl)) @@ -1560,9 +1670,30 @@ determine_visibility (tree decl) maybe_clone_body. */ gcc_assert (!DECL_CLONED_FUNCTION_P (decl)); - /* Give the common code a chance to make a determination. */ - if (c_determine_visibility (decl)) - return; + if (TREE_CODE (decl) == TYPE_DECL) + { + if (CLASS_TYPE_P (TREE_TYPE (decl))) + use_template = CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)); + else if (TYPE_TEMPLATE_INFO (TREE_TYPE (decl))) + use_template = 1; + else + use_template = 0; + } + else if (DECL_LANG_SPECIFIC (decl)) + use_template = DECL_USE_TEMPLATE (decl); + else + use_template = 0; + + /* Anything that is exported must have default visibility. */ + if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllexport", + TREE_CODE (decl) == TYPE_DECL + ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) + : DECL_ATTRIBUTES (decl))) + { + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (decl) = 1; + } /* If DECL is a member of a class, visibility specifiers on the class can influence the visibility of the DECL. */ @@ -1574,6 +1705,8 @@ determine_visibility (tree decl) class_type = TREE_TYPE (DECL_NAME (decl)); else { + /* Not a class member. */ + /* Virtual tables have DECL_CONTEXT set to their associated class, so they are automatically handled above. */ gcc_assert (TREE_CODE (decl) != VAR_DECL @@ -1581,77 +1714,138 @@ determine_visibility (tree decl) if (DECL_FUNCTION_SCOPE_P (decl)) { + /* Local statics and classes get the visibility of their + containing function. */ tree fn = DECL_CONTEXT (decl); DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); - } - /* Entities not associated with any class just get the - visibility specified by their attributes. */ - return; + /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set, + but have no TEMPLATE_INFO, so don't try to check it. */ + use_template = 0; + } + else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)) + { + /* tinfo visibility is based on the type it's for. */ + constrain_visibility + (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), + false, "type"); + } + else if (use_template) + /* Template instantiations and specializations get visibility based + on their template unless they override it with an attribute. */; + else if (! DECL_VISIBILITY_SPECIFIED (decl)) + { + /* Set default visibility to whatever the user supplied with + #pragma GCC visibility or a namespace visibility attribute. */ + DECL_VISIBILITY (decl) = default_visibility; + DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma; + } } - /* By default, static data members and function members receive - the visibility of their containing class. */ - if (class_type) + if (use_template) { - determine_visibility_from_class (decl, class_type); - - /* Give the target a chance to override the visibility associated - with DECL. */ - if (TREE_CODE (decl) == VAR_DECL - && (DECL_TINFO_P (decl) - || (DECL_VTABLE_OR_VTT_P (decl) - /* Construction virtual tables are not exported because - they cannot be referred to from other object files; - their name is not standardized by the ABI. */ - && !DECL_CONSTRUCTION_VTABLE_P (decl))) - && TREE_PUBLIC (decl) - && !DECL_REALLY_EXTERN (decl) - && DECL_VISIBILITY_SPECIFIED (decl) - && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))) - targetm.cxx.determine_class_data_visibility (decl); + tree tinfo = (TREE_CODE (decl) == TYPE_DECL + ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl)) + : DECL_TEMPLATE_INFO (decl)); + tree args = TI_ARGS (tinfo); + int depth = TMPL_ARGS_DEPTH (args); + + /* If the template has explicit visibility and the specialization + doesn't, use the visibility from the template. */ + if (!DECL_VISIBILITY_SPECIFIED (decl)) + { + tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo)); + DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern); + } + + /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */ + if (args && depth > template_class_depth (class_type)) + /* Don't let it have more visibility than its template type + arguments. */ + constrain_visibility_for_template (decl, args); } + + if (class_type) + determine_visibility_from_class (decl, class_type); + + /* Don't let it have more visibility than its type. */ + if (TREE_CODE (decl) != TYPE_DECL) + if (constrain_visibility (decl, type_visibility (TREE_TYPE (decl)), + false, "type")) + warning (OPT_Wattributes, "\ +%q+D declared with greater visibility than its type", + decl); + + if (decl_anon_ns_mem_p (decl)) + /* Names in an anonymous namespace get internal linkage. + This might change once we implement export. */ + constrain_visibility (decl, VISIBILITY_STATIC, + false, "namespace"); } +/* By default, static data members and function members receive + the visibility of their containing class. */ + static void determine_visibility_from_class (tree decl, tree class_type) { - if (TARGET_DLLIMPORT_DECL_ATTRIBUTES - && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type))) - { - DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; - DECL_VISIBILITY_SPECIFIED (decl) = 1; - } - else if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (decl) - && visibility_options.inlines_hidden) - { - /* Don't change it if it has been set explicitly by user. */ - if (!DECL_VISIBILITY_SPECIFIED (decl)) - { - DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; - DECL_VISIBILITY_SPECIFIED (decl) = 1; - } - } - else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type)) - { - DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); - DECL_VISIBILITY_SPECIFIED (decl) = 1; - } - else if (TYPE_CLASS_SCOPE_P (class_type)) - determine_visibility_from_class (decl, TYPE_CONTEXT (class_type)); - else if (TYPE_FUNCTION_SCOPE_P (class_type)) - { - tree fn = TYPE_CONTEXT (class_type); - DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); - DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); - } - else if (!DECL_VISIBILITY_SPECIFIED (decl)) - { - DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type); - DECL_VISIBILITY_SPECIFIED (decl) = 0; - } + if (visibility_options.inlines_hidden + /* Don't do this for inline templates; specializations might not be + inline, and we don't want them to inherit the hidden + visibility. We'll set it here for all inline instantiations. */ + && !processing_template_decl + && ! DECL_VISIBILITY_SPECIFIED (decl) + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (decl)) + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + + /* The decl can't have more visibility than its class. */ + constrain_visibility (decl, CLASSTYPE_VISIBILITY (class_type), + CLASSTYPE_VISIBILITY_SPECIFIED (class_type), + "class"); + + /* Give the target a chance to override the visibility associated + with DECL. */ + if (TREE_CODE (decl) == VAR_DECL + && (DECL_TINFO_P (decl) + || (DECL_VTABLE_OR_VTT_P (decl) + /* Construction virtual tables are not exported because + they cannot be referred to from other object files; + their name is not standardized by the ABI. */ + && !DECL_CONSTRUCTION_VTABLE_P (decl))) + && TREE_PUBLIC (decl) + && !DECL_REALLY_EXTERN (decl) + && DECL_VISIBILITY_SPECIFIED (decl) + && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))) + targetm.cxx.determine_class_data_visibility (decl); +} + +/* Constrain the visibility of a class TYPE based on the visibility of its + field types. Warn if any fields require lesser visibility. */ + +void +constrain_class_visibility (tree type) +{ + tree decl = TYPE_MAIN_DECL (type); + tree binfo = TYPE_BINFO (type); + tree t; + int i; + + for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == FIELD_DECL) + if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)), + false, "field type")) + warning (OPT_Wattributes, "\ +%qT declared with greater visibility than the type of its field %qD", + type, t); + + for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i) + if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)), + false, "base type")) + warning (OPT_Wattributes, "\ +%qT declared with greater visibility than its base %qT", + type, TREE_TYPE (t)); } /* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage |