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
This commit is contained in:
parent
dc2843f38c
commit
b9e7569630
41 changed files with 887 additions and 207 deletions
|
@ -1,3 +1,27 @@
|
|||
2006-06-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
PR c++/26905
|
||||
PR c++/21675
|
||||
PR c++/17470
|
||||
* attribs.c (decl_attributes): Ignore type-in-place attributes
|
||||
once the type has been defined.
|
||||
|
||||
2006-06-29 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR middle-end/27428
|
||||
|
|
|
@ -250,6 +250,14 @@ decl_attributes (tree *node, tree attributes, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
if (TYPE_P (*anode)
|
||||
&& (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
|
||||
&& TYPE_SIZE (*anode) != NULL_TREE)
|
||||
{
|
||||
warning (OPT_Wattributes, "type attributes ignored after type is already defined");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spec->handler != NULL)
|
||||
returned_attrs = chainon ((*spec->handler) (anode, name, args,
|
||||
flags, &no_add_attrs),
|
||||
|
|
|
@ -4876,21 +4876,28 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
|
|||
static tree
|
||||
handle_visibility_attribute (tree *node, tree name, tree args,
|
||||
int ARG_UNUSED (flags),
|
||||
bool *no_add_attrs)
|
||||
bool *ARG_UNUSED (no_add_attrs))
|
||||
{
|
||||
tree decl = *node;
|
||||
tree id = TREE_VALUE (args);
|
||||
|
||||
*no_add_attrs = true;
|
||||
enum symbol_visibility vis;
|
||||
|
||||
if (TYPE_P (*node))
|
||||
{
|
||||
if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
|
||||
name);
|
||||
return NULL_TREE;
|
||||
}
|
||||
if (TREE_CODE (*node) == ENUMERAL_TYPE)
|
||||
/* OK */;
|
||||
else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
|
||||
name);
|
||||
return NULL_TREE;
|
||||
}
|
||||
else if (TYPE_FIELDS (*node))
|
||||
{
|
||||
error ("%qE attribute ignored because %qT is already defined",
|
||||
name, *node);
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
|
||||
{
|
||||
|
@ -4919,23 +4926,33 @@ handle_visibility_attribute (tree *node, tree name, tree args,
|
|||
}
|
||||
|
||||
if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
||||
vis = VISIBILITY_DEFAULT;
|
||||
else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
|
||||
vis = VISIBILITY_INTERNAL;
|
||||
else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
|
||||
vis = VISIBILITY_HIDDEN;
|
||||
else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
|
||||
vis = VISIBILITY_PROTECTED;
|
||||
else
|
||||
error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
|
||||
{
|
||||
error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
|
||||
vis = VISIBILITY_DEFAULT;
|
||||
}
|
||||
|
||||
if (DECL_VISIBILITY_SPECIFIED (decl)
|
||||
&& vis != DECL_VISIBILITY (decl)
|
||||
&& lookup_attribute ("visibility", (TYPE_P (*node)
|
||||
? TYPE_ATTRIBUTES (*node)
|
||||
: DECL_ATTRIBUTES (decl))))
|
||||
error ("%qD redeclared with different visibility", decl);
|
||||
|
||||
DECL_VISIBILITY (decl) = vis;
|
||||
DECL_VISIBILITY_SPECIFIED (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;
|
||||
/* 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 containing scope. */
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
@ -4972,6 +4989,13 @@ c_determine_visibility (tree decl)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Set default visibility to whatever the user supplied with
|
||||
visibility_specified depending on #pragma GCC visibility. */
|
||||
if (!DECL_VISIBILITY_SPECIFIED (decl))
|
||||
{
|
||||
DECL_VISIBILITY (decl) = default_visibility;
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
10
gcc/c-decl.c
10
gcc/c-decl.c
|
@ -3459,18 +3459,16 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
/* If #pragma weak was used, mark the decl weak now. */
|
||||
maybe_apply_pragma_weak (decl);
|
||||
|
||||
/* If this is a variable definition, determine its ELF visibility. */
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& TREE_STATIC (decl)
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
c_determine_visibility (decl);
|
||||
|
||||
/* Output the assembler code and/or RTL code for variables and functions,
|
||||
unless the type is an undefined structure or union.
|
||||
If not, it will get done when the type is completed. */
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
/* Determine the ELF visibility. */
|
||||
if (TREE_PUBLIC (decl))
|
||||
c_determine_visibility (decl);
|
||||
|
||||
/* This is a no-op in c-lang.c or something real in objc-act.c. */
|
||||
if (c_dialect_objc ())
|
||||
objc_check_decl (decl);
|
||||
|
|
|
@ -1,3 +1,51 @@
|
|||
2006-06-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/26905
|
||||
PR c++/26612
|
||||
PR c++/27000
|
||||
PR c++/26984
|
||||
PR c++/19134
|
||||
* 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.
|
||||
* decl.c (cp_finish_decl): Call determine_visibility for function
|
||||
decls, too.
|
||||
* name-lookup.c (pushtag): Call determine_visibility.
|
||||
* decl.c (duplicate_decls): Don't copy visibility from template to
|
||||
specialization.
|
||||
* pt.c (check_explicit_specialization): Likewise.
|
||||
(lookup_template_class, tsubst_decl): Call determine_visibility.
|
||||
* class.c (finish_struct_1): Call constrain_class_visibility.
|
||||
|
||||
PR c++/26905
|
||||
PR c++/21675
|
||||
PR c++/17470
|
||||
* 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.
|
||||
* semantics.c (begin_class_definition): Add attributes parameter,
|
||||
apply them to the type.
|
||||
|
||||
PR c++/21581
|
||||
PR c++/25915
|
||||
* tree.c (decl_anon_ns_mem_p): New function.
|
||||
* cp-tree.h: Declare it.
|
||||
* decl2.c (determine_visibility): Make anonymous namespace
|
||||
members static.
|
||||
(min_vis_r, constrain_visibility): Likewise.
|
||||
* rtti.c (create_pseudo_type_info): Set TREE_PUBLIC on
|
||||
pseudo-types.
|
||||
* decl.c (cxx_init_decl_processing): Set TREE_PUBLIC on
|
||||
global_namespace.
|
||||
* name-lookup.c (push_namespace_with_attribs): Don't set TREE_PUBLIC
|
||||
on anonymous namespaces.
|
||||
|
||||
2006-06-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/27424
|
||||
|
|
|
@ -5084,6 +5084,9 @@ finish_struct_1 (tree t)
|
|||
DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
|
||||
}
|
||||
|
||||
/* Complain if one of the field types requires lower visibility. */
|
||||
constrain_class_visibility (t);
|
||||
|
||||
/* Make the rtl for any new vtables we have created, and unmark
|
||||
the base types we marked. */
|
||||
finish_vtbls (t);
|
||||
|
|
|
@ -3965,6 +3965,8 @@ extern tree coerce_new_type (tree);
|
|||
extern tree coerce_delete_type (tree);
|
||||
extern void comdat_linkage (tree);
|
||||
extern void determine_visibility (tree);
|
||||
extern void constrain_class_visibility (tree);
|
||||
extern void update_member_visibility (tree);
|
||||
extern void import_export_decl (tree);
|
||||
extern tree build_cleanup (tree);
|
||||
extern tree build_offset_ref_call_from_tree (tree, tree);
|
||||
|
@ -4271,7 +4273,7 @@ extern tree finish_fname (tree);
|
|||
extern void finish_translation_unit (void);
|
||||
extern tree finish_template_type_parm (tree, tree);
|
||||
extern tree finish_template_template_parm (tree, tree);
|
||||
extern tree begin_class_definition (tree);
|
||||
extern tree begin_class_definition (tree, tree);
|
||||
extern void finish_template_decl (tree);
|
||||
extern tree finish_template_type (tree, tree, int);
|
||||
extern tree finish_base_specifier (tree, tree, bool);
|
||||
|
@ -4353,6 +4355,7 @@ extern tree array_type_nelts_top (tree);
|
|||
extern tree break_out_target_exprs (tree);
|
||||
extern tree get_type_decl (tree);
|
||||
extern tree decl_namespace_context (tree);
|
||||
extern bool decl_anon_ns_mem_p (tree);
|
||||
extern tree lvalue_type (tree);
|
||||
extern tree error_type (tree);
|
||||
extern int varargs_function_p (tree);
|
||||
|
|
|
@ -1857,6 +1857,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|
|||
|
||||
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
|
||||
|
||||
/* Don't propagate visibility from the template to the
|
||||
specialization here. We'll do that in determine_visibility if
|
||||
appropriate. */
|
||||
DECL_VISIBILITY_SPECIFIED (olddecl) = 0;
|
||||
|
||||
/* [temp.expl.spec/14] We don't inline explicit specialization
|
||||
just because the primary template says so. */
|
||||
}
|
||||
|
@ -3119,6 +3124,7 @@ cxx_init_decl_processing (void)
|
|||
gcc_assert (global_namespace == NULL_TREE);
|
||||
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
|
||||
void_type_node);
|
||||
TREE_PUBLIC (global_namespace) = 1;
|
||||
begin_scope (sk_namespace, global_namespace);
|
||||
|
||||
current_lang_name = NULL_TREE;
|
||||
|
@ -5240,6 +5246,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
|||
else
|
||||
abstract_virtuals_error (decl, type);
|
||||
|
||||
/* This needs to happen after the linkage is set. */
|
||||
determine_visibility (decl);
|
||||
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||
|| TREE_TYPE (decl) == error_mark_node)
|
||||
/* No initialization required. */
|
||||
|
@ -5263,10 +5272,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
|||
initialize_local_var (decl, init);
|
||||
}
|
||||
|
||||
/* The variable is being defined, so determine its visibility.
|
||||
This needs to happen after the linkage is set. */
|
||||
determine_visibility (decl);
|
||||
|
||||
/* If a variable is defined, and then a subsequent
|
||||
definition with external linkage is encountered, we will
|
||||
get here twice for the same variable. We want to avoid
|
||||
|
|
320
gcc/cp/decl2.c
320
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_template)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* Entities not associated with any class just get the
|
||||
visibility specified by their attributes. */
|
||||
return;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* By default, static data members and function members receive
|
||||
the visibility of their containing class. */
|
||||
|
||||
if (class_type)
|
||||
{
|
||||
determine_visibility_from_class (decl, class_type);
|
||||
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);
|
||||
}
|
||||
/* 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
|
||||
|
|
|
@ -3039,7 +3039,12 @@ push_namespace_with_attribs (tree name, tree attributes)
|
|||
/* Make a new namespace, binding the name to it. */
|
||||
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
|
||||
DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
|
||||
TREE_PUBLIC (d) = 1;
|
||||
/* The name of this namespace is not visible to other translation
|
||||
units if it is an anonymous namespace or member thereof. */
|
||||
if (anon || decl_anon_ns_mem_p (current_namespace))
|
||||
TREE_PUBLIC (d) = 0;
|
||||
else
|
||||
TREE_PUBLIC (d) = 1;
|
||||
pushdecl (d);
|
||||
if (anon)
|
||||
{
|
||||
|
@ -3086,15 +3091,6 @@ push_namespace_with_attribs (tree name, tree attributes)
|
|||
push_visibility (TREE_STRING_POINTER (x));
|
||||
goto found;
|
||||
}
|
||||
#if 0
|
||||
if (anon)
|
||||
{
|
||||
/* Anonymous namespaces default to hidden visibility. This might
|
||||
change once we implement export. */
|
||||
current_binding_level->has_visibility = 1;
|
||||
push_visibility ("hidden");
|
||||
}
|
||||
#endif
|
||||
found:
|
||||
#endif
|
||||
|
||||
|
@ -4914,6 +4910,10 @@ pushtag (tree name, tree type, tag_scope scope)
|
|||
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
|
||||
TYPE_STUB_DECL (type) = decl;
|
||||
|
||||
/* Set type visibility now if this is a forward declaration. */
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
determine_visibility (decl);
|
||||
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
|
||||
}
|
||||
|
||||
|
|
|
@ -9412,7 +9412,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
|
|||
if (declarator != cp_error_declarator)
|
||||
{
|
||||
decl = grokdeclarator (declarator, &decl_specifiers,
|
||||
NORMAL, 0, NULL);
|
||||
NORMAL, 0, &decl_specifiers.attributes);
|
||||
/* Turn access control back on for names used during
|
||||
template instantiation. */
|
||||
pop_deferring_access_checks ();
|
||||
|
@ -9561,22 +9561,11 @@ cp_parser_type_specifier (cp_parser* parser,
|
|||
switch (keyword)
|
||||
{
|
||||
case RID_ENUM:
|
||||
/* 'enum' [identifier] '{' introduces an enum-specifier;
|
||||
'enum' <anything else> introduces an elaborated-type-specifier. */
|
||||
if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
|
||||
|| (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
|
||||
&& cp_lexer_peek_nth_token (parser->lexer, 3)->type
|
||||
== CPP_OPEN_BRACE))
|
||||
/* Look for the enum-specifier. */
|
||||
type_spec = cp_parser_enum_specifier (parser);
|
||||
/* If that worked, we're done. */
|
||||
if (type_spec)
|
||||
{
|
||||
if (parser->num_template_parameter_lists)
|
||||
{
|
||||
error ("template declaration of %qs", "enum");
|
||||
cp_parser_skip_to_end_of_block_or_statement (parser);
|
||||
type_spec = error_mark_node;
|
||||
}
|
||||
else
|
||||
type_spec = cp_parser_enum_specifier (parser);
|
||||
|
||||
if (declares_class_or_enum)
|
||||
*declares_class_or_enum = 2;
|
||||
if (decl_specs)
|
||||
|
@ -10078,6 +10067,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
|||
/*type_p=*/true,
|
||||
is_declaration);
|
||||
/* For everything but enumeration types, consider a template-id. */
|
||||
/* For an enumeration type, consider only a plain identifier. */
|
||||
if (tag_type != enum_type)
|
||||
{
|
||||
bool template_p = false;
|
||||
|
@ -10109,7 +10099,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
|||
type = TREE_TYPE (decl);
|
||||
}
|
||||
|
||||
/* For an enumeration type, consider only a plain identifier. */
|
||||
if (!type)
|
||||
{
|
||||
identifier = cp_parser_identifier (parser);
|
||||
|
@ -10237,11 +10226,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
|||
else
|
||||
ts = ts_global;
|
||||
|
||||
/* Warn about attributes. They are ignored. */
|
||||
if (attributes)
|
||||
warning (OPT_Wattributes,
|
||||
"type attributes are honored only at type definition");
|
||||
|
||||
template_p =
|
||||
(parser->num_template_parameter_lists
|
||||
&& (cp_parser_next_token_starts_class_definition_p (parser)
|
||||
|
@ -10254,6 +10238,21 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
|||
type = xref_tag (tag_type, identifier, ts, template_p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow attributes on forward declarations of classes. */
|
||||
if (attributes)
|
||||
{
|
||||
if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
|
||||
&& ! processing_explicit_instantiation)
|
||||
warning (OPT_Wattributes,
|
||||
"attributes ignored on template instantiation");
|
||||
else if (is_declaration && cp_parser_declares_only_class_p (parser))
|
||||
cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
|
||||
else
|
||||
warning (OPT_Wattributes,
|
||||
"attributes ignored on elaborated-type-specifier that is not a forward declaration");
|
||||
}
|
||||
|
||||
if (tag_type != enum_type)
|
||||
cp_parser_check_class_key (tag_type, type);
|
||||
|
||||
|
@ -10270,15 +10269,22 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
|||
enum identifier [opt] { enumerator-list [opt] }
|
||||
|
||||
GNU Extensions:
|
||||
enum identifier [opt] { enumerator-list [opt] } attributes
|
||||
enum attributes[opt] identifier [opt] { enumerator-list [opt] }
|
||||
attributes[opt]
|
||||
|
||||
Returns an ENUM_TYPE representing the enumeration. */
|
||||
Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
|
||||
if the token stream isn't an enum-specifier after all. */
|
||||
|
||||
static tree
|
||||
cp_parser_enum_specifier (cp_parser* parser)
|
||||
{
|
||||
tree identifier;
|
||||
tree type;
|
||||
tree attributes;
|
||||
|
||||
/* Parse tentatively so that we can back up if we don't find a
|
||||
enum-specifier. */
|
||||
cp_parser_parse_tentatively (parser);
|
||||
|
||||
/* Caller guarantees that the current token is 'enum', an identifier
|
||||
possibly follows, and the token after that is an opening brace.
|
||||
|
@ -10286,11 +10292,20 @@ cp_parser_enum_specifier (cp_parser* parser)
|
|||
the enumeration being defined. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
attributes = cp_parser_attributes_opt (parser);
|
||||
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
identifier = cp_parser_identifier (parser);
|
||||
else
|
||||
identifier = make_anon_name ();
|
||||
|
||||
/* Look for the `{' but don't consume it yet. */
|
||||
if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
|
||||
cp_parser_simulate_error (parser);
|
||||
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Issue an error message if type-definitions are forbidden here. */
|
||||
cp_parser_check_type_definition (parser);
|
||||
|
||||
|
@ -10302,6 +10317,12 @@ cp_parser_enum_specifier (cp_parser* parser)
|
|||
/* Consume the opening brace. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (type == error_mark_node)
|
||||
{
|
||||
cp_parser_skip_to_end_of_block_or_statement (parser);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* If the next token is not '}', then there are some enumerators. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
|
||||
cp_parser_enumerator_list (parser, type);
|
||||
|
@ -12917,7 +12938,7 @@ cp_parser_class_specifier (cp_parser* parser)
|
|||
scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
|
||||
old_scope = push_inner_scope (scope);
|
||||
}
|
||||
type = begin_class_definition (type);
|
||||
type = begin_class_definition (type, attributes);
|
||||
|
||||
if (type == error_mark_node)
|
||||
/* If the type is erroneous, skip the entire body of the class. */
|
||||
|
@ -12934,10 +12955,7 @@ cp_parser_class_specifier (cp_parser* parser)
|
|||
has_trailing_semicolon = (token->type == CPP_SEMICOLON);
|
||||
/* Look for trailing attributes to apply to this class. */
|
||||
if (cp_parser_allow_gnu_extensions_p (parser))
|
||||
{
|
||||
tree sub_attr = cp_parser_attributes_opt (parser);
|
||||
attributes = chainon (attributes, sub_attr);
|
||||
}
|
||||
attributes = cp_parser_attributes_opt (parser);
|
||||
if (type != error_mark_node)
|
||||
type = finish_struct (type, attributes);
|
||||
if (nested_name_specifier_p)
|
||||
|
|
30
gcc/cp/pt.c
30
gcc/cp/pt.c
|
@ -2140,13 +2140,7 @@ check_explicit_specialization (tree declarator,
|
|||
template it specializes. */
|
||||
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
|
||||
TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
|
||||
/* The specialization has the same visibility as the
|
||||
template it specializes. */
|
||||
if (DECL_VISIBILITY_SPECIFIED (gen_tmpl))
|
||||
{
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = 1;
|
||||
DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl);
|
||||
}
|
||||
|
||||
/* If DECL is a friend declaration, declared using an
|
||||
unqualified name, the namespace associated with DECL may
|
||||
have been set incorrectly. For example, in:
|
||||
|
@ -3592,9 +3586,9 @@ convert_nontype_argument (tree type, tree expr)
|
|||
|
||||
if (!constant_address_p)
|
||||
{
|
||||
error ("%qE is not a valid template argument for type %qT "
|
||||
"because it is not a constant pointer", expr, type);
|
||||
return NULL_TREE;
|
||||
error ("%qE is not a valid template argument for type %qT "
|
||||
"because it is not a constant pointer", expr, type);
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
/* [temp.arg.nontype]/5, bullet 3
|
||||
|
@ -4782,6 +4776,10 @@ lookup_template_class (tree d1,
|
|||
code that generates debugging information will crash. */
|
||||
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
|
||||
|
||||
/* Possibly limit visibility based on template args. */
|
||||
TREE_PUBLIC (type_decl) = 1;
|
||||
determine_visibility (type_decl);
|
||||
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
|
||||
}
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
|
@ -6588,6 +6586,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
|||
SET_DECL_FRIEND_CONTEXT (r,
|
||||
tsubst (DECL_FRIEND_CONTEXT (t),
|
||||
args, complain, in_decl));
|
||||
|
||||
/* Possibly limit visibility based on template args. */
|
||||
DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
determine_visibility (r);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6760,6 +6763,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
|||
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
|
||||
SET_DECL_RTL (r, NULL_RTX);
|
||||
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
|
||||
if (TREE_CODE (r) == VAR_DECL)
|
||||
{
|
||||
/* Possibly limit visibility based on template args. */
|
||||
DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (r) = 0;
|
||||
determine_visibility (r);
|
||||
}
|
||||
|
||||
if (!local_p)
|
||||
{
|
||||
|
|
|
@ -1156,6 +1156,10 @@ create_pseudo_type_info (int tk, const char *real_name, ...)
|
|||
ti->name = get_identifier (real_name);
|
||||
ti->vtable = NULL_TREE;
|
||||
|
||||
/* Pretend this is public so determine_visibility doesn't give vtables
|
||||
internal linkage. */
|
||||
TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1;
|
||||
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
|
|
|
@ -2161,7 +2161,7 @@ check_template_template_default_arg (tree argument)
|
|||
/* Begin a class definition, as indicated by T. */
|
||||
|
||||
tree
|
||||
begin_class_definition (tree t)
|
||||
begin_class_definition (tree t, tree attributes)
|
||||
{
|
||||
if (t == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
@ -2200,6 +2200,9 @@ begin_class_definition (tree t)
|
|||
maybe_process_partial_specialization (t);
|
||||
pushclass (t);
|
||||
TYPE_BEING_DEFINED (t) = 1;
|
||||
|
||||
cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
|
||||
|
||||
if (flag_pack_struct)
|
||||
{
|
||||
tree v;
|
||||
|
|
|
@ -1385,6 +1385,30 @@ decl_namespace_context (tree decl)
|
|||
}
|
||||
}
|
||||
|
||||
/* Returns true if decl is within an anonymous namespace, however deeply
|
||||
nested, or false otherwise. */
|
||||
|
||||
bool
|
||||
decl_anon_ns_mem_p (tree decl)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (decl == NULL_TREE)
|
||||
return false;
|
||||
if (TREE_CODE (decl) == NAMESPACE_DECL
|
||||
&& DECL_NAME (decl) == NULL_TREE)
|
||||
return true;
|
||||
/* Classes and namespaces inside anonymous namespaces have
|
||||
TREE_PUBLIC == 0, so we can shortcut the search. */
|
||||
else if (TYPE_P (decl))
|
||||
return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
|
||||
else if (TREE_CODE (decl) == NAMESPACE_DECL)
|
||||
return (TREE_PUBLIC (decl) == 0);
|
||||
else
|
||||
decl = DECL_CONTEXT (decl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return truthvalue of whether T1 is the same tree structure as T2.
|
||||
Return 1 if they are the same. Return 0 if they are different. */
|
||||
|
||||
|
@ -2181,7 +2205,8 @@ decl_linkage (tree decl)
|
|||
template instantiations have internal linkage (in the object
|
||||
file), but the symbols should still be treated as having external
|
||||
linkage from the point of view of the language. */
|
||||
if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
|
||||
if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_COMDAT (decl))
|
||||
return lk_external;
|
||||
|
||||
/* Things in local scope do not have linkage, if they don't have
|
||||
|
|
|
@ -2409,10 +2409,10 @@ consistently, so that the same entity should not be declared with
|
|||
different settings of the attribute.
|
||||
|
||||
In C++, the visibility attribute applies to types as well as functions
|
||||
and objects, because in C++ types have linkage. There are some bugs
|
||||
in the C++ support for this flag, for example a template which has a
|
||||
hidden type as a parameter is not properly hidden.
|
||||
@c bugzilla 26612
|
||||
and objects, because in C++ types have linkage. A class must not have
|
||||
greater visibility than its non-static data member types and bases,
|
||||
and class members default to the visibility of their class. Also, a
|
||||
declaration must not have greater visibility than its type.
|
||||
|
||||
In C++, you can mark member functions and static member variables of a
|
||||
class with the visibility attribute. This is useful if if you know a
|
||||
|
@ -2423,6 +2423,17 @@ the One Definition Rule; for example, it is not useful to mark a
|
|||
method which is defined inside a class definition as hidden without
|
||||
marking the whole class as hidden.
|
||||
|
||||
A C++ namespace declaration can also have the visibility attribute.
|
||||
This attribute applies only to the particular namespace body, not to
|
||||
other definitions of the same namespace; it is equivalent to using
|
||||
@samp{#pragma GCC visibility} before and after the namespace
|
||||
definition (@pxref{Visibility Pragmas}).
|
||||
|
||||
In C++, if a template argument has limited visibility, this
|
||||
restriction is implicitly propagated to the template instantiation.
|
||||
Otherwise, template instantiations and specializations default to the
|
||||
visibility of their template.
|
||||
|
||||
@item warn_unused_result
|
||||
@cindex @code{warn_unused_result} attribute
|
||||
The @code{warn_unused_result} attribute causes a warning to be emitted
|
||||
|
@ -2604,10 +2615,7 @@ does not arise there.
|
|||
An attribute specifier list may appear as part of a @code{struct},
|
||||
@code{union} or @code{enum} specifier. It may go either immediately
|
||||
after the @code{struct}, @code{union} or @code{enum} keyword, or after
|
||||
the closing brace. It is ignored if the content of the structure, union
|
||||
or enumerated type is not defined in the specifier in which the
|
||||
attribute specifier list is used---that is, in usages such as
|
||||
@code{struct __attribute__((foo)) bar} with no following opening brace.
|
||||
the closing brace. The former syntax is preferred.
|
||||
Where attribute specifiers follow the closing brace, they are considered
|
||||
to relate to the structure, union or enumerated type defined, not to any
|
||||
enclosing declaration the type specifier appears in, and the type
|
||||
|
@ -3382,13 +3390,14 @@ placed in either the @code{.bss_below100} section or the
|
|||
@cindex type attributes
|
||||
|
||||
The keyword @code{__attribute__} allows you to specify special
|
||||
attributes of @code{struct} and @code{union} types when you define such
|
||||
types. This keyword is followed by an attribute specification inside
|
||||
double parentheses. Six attributes are currently defined for types:
|
||||
@code{aligned}, @code{packed}, @code{transparent_union}, @code{unused},
|
||||
@code{deprecated} and @code{may_alias}. Other attributes are defined for
|
||||
functions (@pxref{Function Attributes}) and for variables
|
||||
(@pxref{Variable Attributes}).
|
||||
attributes of @code{struct} and @code{union} types when you define
|
||||
such types. This keyword is followed by an attribute specification
|
||||
inside double parentheses. Seven attributes are currently defined for
|
||||
types: @code{aligned}, @code{packed}, @code{transparent_union},
|
||||
@code{unused}, @code{deprecated}, @code{visibility}, and
|
||||
@code{may_alias}. Other attributes are defined for functions
|
||||
(@pxref{Function Attributes}) and for variables (@pxref{Variable
|
||||
Attributes}).
|
||||
|
||||
You may also specify any one of these attributes with @samp{__}
|
||||
preceding and following its keyword. This allows you to use these
|
||||
|
@ -3396,14 +3405,13 @@ attributes in header files without being concerned about a possible
|
|||
macro of the same name. For example, you may use @code{__aligned__}
|
||||
instead of @code{aligned}.
|
||||
|
||||
You may specify the @code{aligned} and @code{transparent_union}
|
||||
attributes either in a @code{typedef} declaration or just past the
|
||||
closing curly brace of a complete enum, struct or union type
|
||||
@emph{definition} and the @code{packed} attribute only past the closing
|
||||
brace of a definition.
|
||||
You may specify type attributes either in a @code{typedef} declaration
|
||||
or in an enum, struct or union type declaration or definition.
|
||||
|
||||
You may also specify attributes between the enum, struct or union
|
||||
tag and the name of the type rather than after the closing brace.
|
||||
For an enum, struct or union type, you may specify attributes either
|
||||
between the enum, struct or union tag and the name of the type, or
|
||||
just past the closing curly brace of the @emph{definition}. The
|
||||
former syntax is preferred.
|
||||
|
||||
@xref{Attribute Syntax}, for details of the exact syntax for using
|
||||
attributes.
|
||||
|
@ -3652,6 +3660,13 @@ declaration, the above program would abort when compiled with
|
|||
@option{-fstrict-aliasing}, which is on by default at @option{-O2} or
|
||||
above in recent GCC versions.
|
||||
|
||||
@item visibility
|
||||
|
||||
In C++, attribute visibility (@pxref{Function Attributes}) can also be
|
||||
applied to class, struct, union and enum types. Unlike other type
|
||||
attributes, the attribute must appear between the initial keyword and
|
||||
the name of the type; it cannot appear after the body of the type.
|
||||
|
||||
@subsection ARM Type Attributes
|
||||
|
||||
On those ARM targets that support @code{dllimport} (such as Symbian
|
||||
|
@ -9454,6 +9469,7 @@ for further explanation.
|
|||
* Structure-Packing Pragmas::
|
||||
* Weak Pragmas::
|
||||
* Diagnostic Pragmas::
|
||||
* Visibility Pragmas::
|
||||
@end menu
|
||||
|
||||
@node ARM Pragmas
|
||||
|
@ -9750,6 +9766,26 @@ strict control over project policies.
|
|||
|
||||
@end table
|
||||
|
||||
@node Visibility Pragmas
|
||||
@subsection Visibility Pragmas
|
||||
|
||||
@table @code
|
||||
@item #pragma GCC visibility push(@var{visibility})
|
||||
@itemx #pragma GCC visibility pop
|
||||
@cindex pragma, visibility
|
||||
|
||||
This pragma allows the user to set the visibility for multiple
|
||||
declarations without having to give each a visibility attribute
|
||||
@xref{Function Attributes}, for more information about visibility and
|
||||
the attribute syntax.
|
||||
|
||||
In C++, @samp{#pragma GCC visibility} affects only namespace-scope
|
||||
declarations. Class members and template specializations are not
|
||||
affected; if you want to override the visibility for a particular
|
||||
member or instantiation, you must use an attribute.
|
||||
|
||||
@end table
|
||||
|
||||
@node Unnamed Fields
|
||||
@section Unnamed struct/union fields within structs/unions
|
||||
@cindex struct
|
||||
|
|
|
@ -1619,16 +1619,10 @@ 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.
|
||||
|
||||
The behavior of this switch is not quite the same as marking the
|
||||
methods as hidden directly. Normally if there is a class with default
|
||||
visibility which has a hidden method, the effect of this is that the
|
||||
method must be defined in only one shared object. This switch does
|
||||
not have this restriction.
|
||||
|
||||
You may mark a method as having a visibility explicitly to negate the
|
||||
effect of the switch for that method. For example, if you do want to
|
||||
compare pointers to a particular inline method, you might mark it as
|
||||
having default visibility.
|
||||
compare pointers to a particular inline method, or the method has
|
||||
local static data, you might mark it as having default visibility.
|
||||
|
||||
@item -fno-weak
|
||||
@opindex fno-weak
|
||||
|
@ -13506,6 +13500,20 @@ expecting to be compiled with visibility other than the default. You
|
|||
may need to explicitly say @samp{#pragma GCC visibility push(default)}
|
||||
before including any such headers.
|
||||
|
||||
@samp{extern} declarations are not affected by @samp{-fvisibility}, so
|
||||
a lot of code can be recompiled with @samp{-fvisibility=hidden} with
|
||||
no modifications. However, this means that calls to @samp{extern}
|
||||
functions with no explicit visibility will use the PLT, so it is more
|
||||
effective to use @samp{__attribute ((visibility))} and/or
|
||||
@samp{#pragma GCC visibility} to tell the compiler which @samp{extern}
|
||||
declarations should be treated as hidden.
|
||||
|
||||
Note that @samp{-fvisibility} does affect C++ vague linkage
|
||||
entities. This means that, for instance, an exception class that will
|
||||
be thrown between DSOs must be explicitly marked with default
|
||||
visibility so that the @samp{type_info} nodes will be unified between
|
||||
the DSOs.
|
||||
|
||||
An overview of these techniques, their benefits and how to use them
|
||||
is at @w{@uref{http://gcc.gnu.org/wiki/Visibility}}.
|
||||
|
||||
|
|
|
@ -58,15 +58,16 @@ extern enum debug_info_level debug_info_level;
|
|||
debugging information. */
|
||||
extern bool use_gnu_debug_info_extensions;
|
||||
|
||||
/* Enumerate visibility settings. */
|
||||
/* Enumerate visibility settings. This is deliberately ordered from most
|
||||
to least visibility. */
|
||||
#ifndef SYMBOL_VISIBILITY_DEFINED
|
||||
#define SYMBOL_VISIBILITY_DEFINED
|
||||
enum symbol_visibility
|
||||
{
|
||||
VISIBILITY_DEFAULT,
|
||||
VISIBILITY_INTERNAL,
|
||||
VISIBILITY_PROTECTED,
|
||||
VISIBILITY_HIDDEN,
|
||||
VISIBILITY_PROTECTED
|
||||
VISIBILITY_INTERNAL
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// parsing of the class, causing some variants to have it and some not.
|
||||
|
||||
struct __attribute__((bogus)) A
|
||||
{
|
||||
{ // { dg-warning "ignored" "" }
|
||||
virtual ~A();
|
||||
void foo(const A&);
|
||||
void bar(const A&);
|
||||
}; // { dg-warning "ignored" "" }
|
||||
};
|
||||
|
||||
void A::foo(const A&) {}
|
||||
void A::bar(const A& a) { foo(a); }
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
class __attribute__((unused)) C; // { dg-warning "type attributes" }
|
||||
struct __attribute__((unused)) S; // { dg-warning "type attributes" }
|
||||
union __attribute__((unused)) U; // { dg-warning "type attributes" }
|
||||
class __attribute__((unused)) C;
|
||||
struct __attribute__((unused)) S;
|
||||
union __attribute__((unused)) U;
|
||||
enum e {};
|
||||
enum __attribute__((unused)) e; // { dg-warning "type attributes" }
|
||||
enum __attribute__((unused)) e; // { dg-warning "already defined" }
|
||||
|
||||
struct __attribute((unused)) B *p; // { dg-warning "attributes" }
|
||||
|
||||
template <class T> struct A { };
|
||||
struct __attribute((unused)) A<int>; // { dg-warning "attributes" }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// PR c++/21581
|
||||
// Test for anonymous namespace default hidden visibility
|
||||
// Test for anonymous namespace internal linkage
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final-NOT { scan-hidden "_ZN.*1fEv" } }
|
||||
// { dg-do compile }
|
||||
// { dg-final { scan-assembler-not "globl.*_ZN.*1fEv" } }
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
11
gcc/testsuite/g++.dg/ext/visibility/anon2.C
Normal file
11
gcc/testsuite/g++.dg/ext/visibility/anon2.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Test for propagation of anonymous namespace internal linkage
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-final { scan-assembler-not "globl.*_Z1fv" } }
|
||||
|
||||
namespace
|
||||
{
|
||||
struct A { };
|
||||
}
|
||||
|
||||
A f () { }
|
|
@ -6,11 +6,12 @@ struct B {
|
|||
B& operator=(const B&);
|
||||
};
|
||||
|
||||
struct D : public B {
|
||||
struct __attribute__((visibility("hidden"))) D : public B {
|
||||
// The implicit assignment operator should be hidden.
|
||||
} __attribute__((visibility("hidden")));
|
||||
};
|
||||
|
||||
D d1, d2;
|
||||
__attribute__((visibility("hidden"))) D d1;
|
||||
__attribute__((visibility("hidden"))) D d2;
|
||||
|
||||
void f() {
|
||||
d1 = d2;
|
||||
|
|
20
gcc/testsuite/g++.dg/ext/visibility/class1.C
Normal file
20
gcc/testsuite/g++.dg/ext/visibility/class1.C
Normal file
|
@ -0,0 +1,20 @@
|
|||
// PR c++/26905
|
||||
// Init should not be hidden, so calling it should use the PLT.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-options "-fpic" }
|
||||
// { dg-do compile { target i?86-*-* x86_64-*-* } }
|
||||
// { dg-final { scan-assembler "InitEv@PLT" } }
|
||||
|
||||
#pragma GCC visibility push(hidden)
|
||||
struct __attribute__ ((visibility ("default"))) nsINIParser
|
||||
{
|
||||
static void Init();
|
||||
};
|
||||
|
||||
__attribute__ ((visibility ("default")))
|
||||
void
|
||||
CheckCompatibility(void)
|
||||
{
|
||||
nsINIParser::Init();
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
class Foo
|
||||
{
|
||||
__attribute__ ((visibility ("default"))) void method();
|
||||
__attribute__ ((visibility ("internal"))) void method();
|
||||
};
|
||||
|
||||
void Foo::method() { }
|
||||
|
|
23
gcc/testsuite/g++.dg/ext/visibility/prop1.C
Normal file
23
gcc/testsuite/g++.dg/ext/visibility/prop1.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Test for propagation of visibility through template arguments
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final { scan-hidden "_Z1fIN1N1AEEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z1hIXadL_ZN1N1iEEEEvv" } }
|
||||
|
||||
namespace N __attribute ((__visibility__ ("hidden")))
|
||||
{
|
||||
struct A { };
|
||||
int i;
|
||||
}
|
||||
|
||||
template <class T> void f (T) { }
|
||||
template <int *I> void h() { }
|
||||
|
||||
void g()
|
||||
{
|
||||
N::A a;
|
||||
f(a);
|
||||
h<&N::i>();
|
||||
}
|
||||
|
7
gcc/testsuite/g++.dg/ext/visibility/redecl1.C
Normal file
7
gcc/testsuite/g++.dg/ext/visibility/redecl1.C
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Test that we complain about redeclaration with different visibility
|
||||
|
||||
struct __attribute((visibility("hidden"))) B;
|
||||
struct __attribute((visibility("default"))) B; // { dg-warning "visibility" }
|
||||
|
||||
__attribute ((visibility ("hidden"))) void f(); // { dg-warning "previous" }
|
||||
__attribute ((visibility ("default"))) void f(); // { dg-warning "visibility" }
|
35
gcc/testsuite/g++.dg/ext/visibility/template1.C
Normal file
35
gcc/testsuite/g++.dg/ext/visibility/template1.C
Normal file
|
@ -0,0 +1,35 @@
|
|||
// PR c++/19134
|
||||
// -fvisibility-inlines-hidden doesn't apply to non-inline specializations
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-options "-fvisibility-inlines-hidden" }
|
||||
// { dg-final { scan-not-hidden "_ZN1AIiE3fooEv" } }
|
||||
// { dg-final { scan-not-hidden "_ZN1AIiE3barEv" } }
|
||||
// { dg-final { scan-hidden "_ZN1AIlE3fooEv" } }
|
||||
// { dg-final { scan-hidden "_ZN1AIlE3barEv" } }
|
||||
// { dg-final { scan-hidden "_ZN1AIcE3barEv" } }
|
||||
|
||||
template<class T>
|
||||
struct A {
|
||||
void foo() {};
|
||||
__attribute ((visibility ("hidden"))) void bar();
|
||||
};
|
||||
|
||||
// This has default visibility.
|
||||
template<> void A<int>::foo() {}
|
||||
|
||||
// This has hidden visibility because of -fvisibility-inlines-hidden.
|
||||
template<> inline void A<long>::foo() {}
|
||||
// Force the inline out.
|
||||
void f () { A<long> a; a.foo(); }
|
||||
|
||||
// This has default visibility.
|
||||
template<> __attribute ((visibility ("default"))) void A<int>::bar() {}
|
||||
|
||||
// This inherits hidden visibility from its template.
|
||||
template<> void A<long>::bar() { }
|
||||
|
||||
// This also has hidden visibility; #pragma vis doesn't affect class members.
|
||||
#pragma GCC visibility push(default)
|
||||
template<> void A<char>::bar() { }
|
||||
#pragma GCC visibility pop
|
35
gcc/testsuite/g++.dg/ext/visibility/template2.C
Normal file
35
gcc/testsuite/g++.dg/ext/visibility/template2.C
Normal file
|
@ -0,0 +1,35 @@
|
|||
// PR c++/27000
|
||||
// Implicitly instantiated templates should not be affected by
|
||||
// #pragma visibility.
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-visibility "" } */
|
||||
/* { dg-final { scan-not-hidden "_ZN1SIiED1Ev" } } */
|
||||
/* { dg-final { scan-not-hidden "_ZN1SIiEC1ERKi" } } */
|
||||
|
||||
template <class T>
|
||||
struct S
|
||||
{
|
||||
S (const T &);
|
||||
~S ();
|
||||
T t;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
S<T>::S (const T &x)
|
||||
{
|
||||
t = x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
S<T>::~S ()
|
||||
{
|
||||
}
|
||||
|
||||
#pragma GCC visibility push(hidden)
|
||||
struct U
|
||||
{
|
||||
S<int> s;
|
||||
U () : s (6) { }
|
||||
} u;
|
||||
#pragma GCC visibility pop
|
22
gcc/testsuite/g++.dg/ext/visibility/template3.C
Normal file
22
gcc/testsuite/g++.dg/ext/visibility/template3.C
Normal file
|
@ -0,0 +1,22 @@
|
|||
// PR c++/17470
|
||||
// Test that we can give visibility to explicit template instantiations
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final { scan-hidden "_ZN1AIlE1fEl" } }
|
||||
// { dg-final { scan-hidden "_ZN1AIiE1fEi" } }
|
||||
// { dg-final { scan-not-hidden "_ZN1AIcE1fEc" } }
|
||||
// { dg-final { scan-hidden "_Z8identityIdET_S0_" } }
|
||||
// { dg-final { scan-not-hidden "_Z8identityIiET_S0_" } }
|
||||
|
||||
template <class T> T identity(T t) { return t; }
|
||||
template __attribute__((visibility("hidden"))) double identity(double);
|
||||
template int identity(int);
|
||||
|
||||
|
||||
template <class T> struct A { void f (T); };
|
||||
template <class T> void A<T>::f (T) { }
|
||||
template struct __attribute ((visibility ("hidden"))) A<int>;
|
||||
template<> struct __attribute ((visibility ("hidden"))) A<long> { void f(long); };
|
||||
// inherits hidden visibility from its class
|
||||
void A<long>::f (long) { }
|
||||
template struct A<char>;
|
39
gcc/testsuite/g++.dg/ext/visibility/template4.C
Normal file
39
gcc/testsuite/g++.dg/ext/visibility/template4.C
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Test for explicit visibility on template vs. #pragma vis at explicit
|
||||
// instantiation/specialization point for plain function templates.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final { scan-hidden "_Z3fooIdEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3fooIlEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3fooIcEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3fooIiEvT_" } }
|
||||
// { dg-final { scan-not-hidden "_Z3fooIfEvT_" } }
|
||||
// { dg-final { scan-not-hidden "_Z3fooIsEvT_" } }
|
||||
|
||||
// { dg-final { scan-hidden "_Z3barIdEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3barIlEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3barIiEvT_" } }
|
||||
// { dg-final { scan-hidden "_Z3barIcEvT_" } }
|
||||
// { dg-final { scan-not-hidden "_Z3barIfEvT_" } }
|
||||
// { dg-final { scan-not-hidden "_Z3barIsEvT_" } }
|
||||
|
||||
#pragma GCC visibility push(hidden)
|
||||
template <class T> void bar(T) { }
|
||||
#pragma GCC visibility pop
|
||||
template void bar (long);
|
||||
template<> void bar (double) { }
|
||||
template __attribute ((visibility ("default"))) void bar (short);
|
||||
template<> __attribute ((visibility ("default"))) void bar (float) { }
|
||||
#pragma GCC visibility push(default)
|
||||
template<> void bar(char) { }
|
||||
template void bar(int);
|
||||
#pragma GCC visibility pop
|
||||
|
||||
template <class T> __attribute ((visibility ("hidden"))) void foo(T) { }
|
||||
template void foo (long);
|
||||
template<> void foo (double) { }
|
||||
template __attribute ((visibility ("default"))) void foo (short);
|
||||
template<> __attribute ((visibility ("default"))) void foo (float) { }
|
||||
#pragma GCC visibility push(default)
|
||||
template<> void foo(char) { }
|
||||
template void foo(int);
|
||||
#pragma GCC visibility pop
|
19
gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C
Normal file
19
gcc/testsuite/g++.dg/ext/visibility/typeinfo1.C
Normal file
|
@ -0,0 +1,19 @@
|
|||
// PR c++/26984
|
||||
// lazily generated typeinfos should not be affected by #pragma vis, but
|
||||
// they should be affected by the visibility of the type they describe.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-options "-fvisibility-inlines-hidden" }
|
||||
// { dg-final { scan-not-hidden "_ZTIPPi" } }
|
||||
// { dg-final { scan-not-hidden "_ZTSPPi" } }
|
||||
// { dg-final { scan-hidden "_ZTIP1A" } }
|
||||
// { dg-final { scan-hidden "_ZTSP1A" } }
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#pragma GCC visibility push(hidden)
|
||||
const std::type_info* t = &(typeid(int **));
|
||||
struct A { };
|
||||
#pragma GCC visibility pop
|
||||
|
||||
const std::type_info* t2 = &(typeid(A *));
|
|
@ -1,9 +1,15 @@
|
|||
/* Test that setting visibility for class affects virtual table. */
|
||||
/* Test that setting visibility for class affects virtual table, VTT and
|
||||
type_info name and node. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-visibility "" } */
|
||||
/* { dg-final { scan-hidden "ZTV3Foo" } } */
|
||||
/* { dg-final { scan-hidden "ZTT3Foo" } } */
|
||||
/* { dg-final { scan-hidden "ZTS3Foo" } } */
|
||||
/* { dg-final { scan-hidden "ZTI3Foo" } } */
|
||||
|
||||
class __attribute__ ((visibility ("hidden"))) Foo
|
||||
struct A { };
|
||||
|
||||
class __attribute__ ((visibility ("hidden"))) Foo: virtual public A
|
||||
{
|
||||
virtual void method();
|
||||
};
|
||||
|
|
13
gcc/testsuite/g++.dg/ext/visibility/warn1.C
Normal file
13
gcc/testsuite/g++.dg/ext/visibility/warn1.C
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Warn when a declaration is specified with greater visibility than that
|
||||
// of its type.
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-require-visibility "" }
|
||||
// { dg-final { scan-hidden "_Z1fv" } }
|
||||
|
||||
namespace N __attribute ((__visibility__ ("hidden")))
|
||||
{
|
||||
struct A { };
|
||||
}
|
||||
|
||||
N::A f() { } // { dg-warning "visibility" "" }
|
19
gcc/testsuite/g++.dg/ext/visibility/warn2.C
Normal file
19
gcc/testsuite/g++.dg/ext/visibility/warn2.C
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Complain when a class is specified with greater visibility than one of
|
||||
// its members' types or bases, and when a declaration has greater
|
||||
// visibility than its type.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
|
||||
namespace N __attribute ((__visibility__ ("hidden")))
|
||||
{
|
||||
struct A { };
|
||||
}
|
||||
|
||||
struct B
|
||||
{ // { dg-warning "visibility" }
|
||||
N::A a;
|
||||
};
|
||||
|
||||
B f () { } // { dg-warning "visibility" }
|
||||
|
||||
struct C: public N::A { }; // { dg-warning "visibility" }
|
11
gcc/testsuite/g++.dg/ext/visibility/warn3.C
Normal file
11
gcc/testsuite/g++.dg/ext/visibility/warn3.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Warn when a class member is specified to have greater visibility than
|
||||
// its class.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
|
||||
struct __attribute ((visibility ("hidden"))) A
|
||||
{
|
||||
__attribute ((visibility ("default"))) void f (); // { dg-warning "visibility" }
|
||||
};
|
||||
|
||||
void A::f() { }
|
10
gcc/testsuite/g++.dg/ext/visibility/warn4.C
Normal file
10
gcc/testsuite/g++.dg/ext/visibility/warn4.C
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Error if we try to give an instantiation visibility after it's already
|
||||
// been instantiated.
|
||||
|
||||
// { dg-require-visibility "" }
|
||||
|
||||
template <class T> struct A { void f (T); };
|
||||
template <class T> void A<T>::f (T) { }
|
||||
|
||||
A<double> ad;
|
||||
template struct __attribute ((visibility ("hidden"))) A<double>; // { dg-error "already defined" }
|
|
@ -1,4 +1,4 @@
|
|||
// { dg-do assemble }
|
||||
|
||||
template <> // { dg-error "" } template declaration of enum
|
||||
enum E {e};
|
||||
template <>
|
||||
enum E {e}; // { dg-error "" } template declaration of enum
|
||||
|
|
|
@ -3133,14 +3133,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
|
|||
else if (code == FUNCTION_DECL)
|
||||
DECL_MODE (t) = FUNCTION_MODE;
|
||||
|
||||
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
|
||||
{
|
||||
/* Set default visibility to whatever the user supplied with
|
||||
visibility_specified depending on #pragma GCC visibility. */
|
||||
DECL_VISIBILITY (t) = default_visibility;
|
||||
DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -1067,7 +1067,7 @@ extern void omp_clause_range_check_failed (const tree, const char *, int,
|
|||
|
||||
#define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->common.public_flag)
|
||||
|
||||
/* In a VAR_DECL or FUNCTION_DECL,
|
||||
/* In a VAR_DECL, FUNCTION_DECL, NAMESPACE_DECL or TYPE_DECL,
|
||||
nonzero means name is to be accessible from outside this module.
|
||||
In an IDENTIFIER_NODE, nonzero means an external declaration
|
||||
accessible from outside this module was previously seen
|
||||
|
@ -2264,9 +2264,9 @@ struct tree_binfo GTY (())
|
|||
enum symbol_visibility
|
||||
{
|
||||
VISIBILITY_DEFAULT,
|
||||
VISIBILITY_INTERNAL,
|
||||
VISIBILITY_PROTECTED,
|
||||
VISIBILITY_HIDDEN,
|
||||
VISIBILITY_PROTECTED
|
||||
VISIBILITY_INTERNAL
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -5033,7 +5033,7 @@ void
|
|||
default_assemble_visibility (tree decl, int vis)
|
||||
{
|
||||
static const char * const visibility_types[] = {
|
||||
NULL, "internal", "hidden", "protected"
|
||||
NULL, "protected", "hidden", "internal"
|
||||
};
|
||||
|
||||
const char *name, *type;
|
||||
|
|
Loading…
Add table
Reference in a new issue