mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-13 18:30:59 +08:00
class.c (build_vtable): Do not set DECL_VISIBILITY here.
* class.c (build_vtable): Do not set DECL_VISIBILITY here. (check_field_decls): Or here. (check_methods): Or here. (initialize_array): Don't mess with DECL_CONTEXT. * cp-tree.h (start_decl): Adjust prototype. (determine_visibility): New function. * decl.c (duplicate_decls): Remove checks for hidden "operator new". (build_library_fn_1): Give all library functions default visibility. (start_decl): Add pop_scope_p parameter. Tidy. (cp_finish_decl): Do not pop scopes here. Call determine_visibility for variable definitions. (start_preparsed_function): Call determine_visibility. * decl2.c (determine_visibility): New function. * method.c (use_thunk): Fix formatting. * parser.c (cp_parser_condition): Adjust calls to start_decl. (cp_parser_init_declarator): Likewise. * pt.c (instantiate_decl): Always call pop_nested_class. * rtti.c (get_tinfo_decl): Do not set DECL_VISIBILITY. (tinfo_base_init): Likewise. * g++.dg/ext/visibility/assign1.C: New test. * g++.dg/ext/visibility/new1.C: Likewise. From-SVN: r85543
This commit is contained in:
parent
aed6152d8c
commit
73a8adb62e
@ -1,3 +1,27 @@
|
||||
2004-08-03 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* class.c (build_vtable): Do not set DECL_VISIBILITY here.
|
||||
(check_field_decls): Or here.
|
||||
(check_methods): Or here.
|
||||
(initialize_array): Don't mess with DECL_CONTEXT.
|
||||
* cp-tree.h (start_decl): Adjust prototype.
|
||||
(determine_visibility): New function.
|
||||
* decl.c (duplicate_decls): Remove checks for hidden "operator
|
||||
new".
|
||||
(build_library_fn_1): Give all library functions default
|
||||
visibility.
|
||||
(start_decl): Add pop_scope_p parameter. Tidy.
|
||||
(cp_finish_decl): Do not pop scopes here. Call
|
||||
determine_visibility for variable definitions.
|
||||
(start_preparsed_function): Call determine_visibility.
|
||||
* decl2.c (determine_visibility): New function.
|
||||
* method.c (use_thunk): Fix formatting.
|
||||
* parser.c (cp_parser_condition): Adjust calls to start_decl.
|
||||
(cp_parser_init_declarator): Likewise.
|
||||
* pt.c (instantiate_decl): Always call pop_nested_class.
|
||||
* rtti.c (get_tinfo_decl): Do not set DECL_VISIBILITY.
|
||||
(tinfo_base_init): Likewise.
|
||||
|
||||
2004-08-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/16707
|
||||
|
@ -659,11 +659,6 @@ build_vtable (tree class_type, tree name, tree vtable_type)
|
||||
require more intrusive changes to the g++ front end. */
|
||||
DECL_IGNORED_P (decl) = 1;
|
||||
|
||||
/* 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);
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
@ -2971,25 +2966,7 @@ check_field_decls (tree t, tree *access_decls,
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
continue;
|
||||
|
||||
/* Now it can only be a FIELD_DECL. */
|
||||
|
||||
@ -3744,23 +3721,6 @@ 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. */
|
||||
if (DECL_VINDEX (x))
|
||||
@ -6740,13 +6700,8 @@ initialize_vtable (tree binfo, tree inits)
|
||||
static void
|
||||
initialize_array (tree decl, tree inits)
|
||||
{
|
||||
tree context;
|
||||
|
||||
context = DECL_CONTEXT (decl);
|
||||
DECL_CONTEXT (decl) = NULL_TREE;
|
||||
DECL_INITIAL (decl) = build_constructor (NULL_TREE, inits);
|
||||
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
|
||||
DECL_CONTEXT (decl) = context;
|
||||
}
|
||||
|
||||
/* Build the VTT (virtual table table) for T.
|
||||
|
@ -3740,7 +3740,7 @@ extern int init_type_desc (void);
|
||||
extern tree check_tag_decl (cp_decl_specifier_seq *);
|
||||
extern tree shadow_tag (cp_decl_specifier_seq *);
|
||||
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *);
|
||||
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree);
|
||||
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, bool *);
|
||||
extern void start_decl_1 (tree);
|
||||
extern void cp_finish_decl (tree, tree, tree, int);
|
||||
extern void finish_decl (tree, tree, tree);
|
||||
@ -3825,6 +3825,7 @@ extern tree finish_table (tree, tree, tree, int);
|
||||
extern tree coerce_new_type (tree);
|
||||
extern tree coerce_delete_type (tree);
|
||||
extern void comdat_linkage (tree);
|
||||
extern void determine_visibility (tree);
|
||||
extern void import_export_decl (tree);
|
||||
extern tree build_cleanup (tree);
|
||||
extern tree build_offset_ref_call_from_tree (tree, tree);
|
||||
|
@ -1881,11 +1881,12 @@ duplicate_decls (tree newdecl, tree olddecl)
|
||||
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
|
||||
|
||||
/* Warn about conflicting visibility specifications. */
|
||||
if (DECL_VISIBILITY_SPECIFIED (olddecl) && DECL_VISIBILITY_SPECIFIED (newdecl)
|
||||
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);
|
||||
newdecl, newdecl);
|
||||
warning ("%Jconflicts with previous declaration here", olddecl);
|
||||
}
|
||||
/* Choose the declaration which specified visibility. */
|
||||
@ -1894,21 +1895,6 @@ duplicate_decls (tree newdecl, tree 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)
|
||||
{
|
||||
@ -3276,6 +3262,10 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
|
||||
TREE_NOTHROW (fn) = 1;
|
||||
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
|
||||
SET_DECL_LANGUAGE (fn, lang_c);
|
||||
/* Runtime library routines are, by definition, available in an
|
||||
external shared object. */
|
||||
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
|
||||
DECL_VISIBILITY_SPECIFIED (fn) = 1;
|
||||
return fn;
|
||||
}
|
||||
|
||||
@ -3607,7 +3597,8 @@ start_decl (const cp_declarator *declarator,
|
||||
cp_decl_specifier_seq *declspecs,
|
||||
int initialized,
|
||||
tree attributes,
|
||||
tree prefix_attributes)
|
||||
tree prefix_attributes,
|
||||
bool *pop_scope_p)
|
||||
{
|
||||
tree decl;
|
||||
tree type, tem;
|
||||
@ -3642,14 +3633,11 @@ start_decl (const cp_declarator *declarator,
|
||||
|
||||
context = DECL_CONTEXT (decl);
|
||||
|
||||
if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
|
||||
&& context != current_namespace && TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
/* When parsing the initializer, lookup should use the object's
|
||||
namespace. */
|
||||
push_decl_namespace (context);
|
||||
}
|
||||
|
||||
if (context)
|
||||
*pop_scope_p = push_scope (context);
|
||||
else
|
||||
*pop_scope_p = false;
|
||||
|
||||
/* We are only interested in class contexts, later. */
|
||||
if (context && TREE_CODE (context) == NAMESPACE_DECL)
|
||||
context = NULL_TREE;
|
||||
@ -3705,8 +3693,6 @@ start_decl (const cp_declarator *declarator,
|
||||
|
||||
if (context && COMPLETE_TYPE_P (complete_type (context)))
|
||||
{
|
||||
push_nested_class (context);
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
|
||||
@ -4715,20 +4701,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
||||
&& (DECL_INITIAL (decl) || init))
|
||||
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_CONTEXT (decl)
|
||||
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
|
||||
&& DECL_CONTEXT (decl) != current_namespace
|
||||
&& init)
|
||||
{
|
||||
/* Leave the namespace of the object. */
|
||||
pop_decl_namespace ();
|
||||
}
|
||||
|
||||
type = TREE_TYPE (decl);
|
||||
|
||||
if (type == error_mark_node)
|
||||
goto finish_end0;
|
||||
goto finish_end;
|
||||
|
||||
if (TYPE_HAS_MUTABLE_P (type))
|
||||
TREE_READONLY (decl) = 0;
|
||||
@ -4745,7 +4721,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
||||
&& !DECL_PRETTY_FUNCTION_P (decl)
|
||||
&& !dependent_type_p (TREE_TYPE (decl)))
|
||||
maybe_deduce_size_from_array_init (decl, init);
|
||||
goto finish_end0;
|
||||
goto finish_end;
|
||||
}
|
||||
|
||||
/* Parameters are handled by store_parm_decls, not cp_finish_decl. */
|
||||
@ -4833,6 +4809,9 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
||||
/* Remember that the initialization for this variable has
|
||||
taken place. */
|
||||
DECL_INITIALIZED_P (decl) = 1;
|
||||
/* The variable is being defined, so determine its
|
||||
visibility. */
|
||||
determine_visibility (decl);
|
||||
}
|
||||
/* If the variable has an array type, lay out the type, even if
|
||||
there is no initializer. It is valid to index through the
|
||||
@ -4899,26 +4878,6 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
||||
if (TREE_STATIC (decl))
|
||||
expand_static_init (decl, init);
|
||||
}
|
||||
finish_end0:
|
||||
|
||||
/* Undo call to `pushclass' that was done in `start_decl'
|
||||
due to initialization of qualified member variable.
|
||||
I.e., Foo::x = 10; */
|
||||
{
|
||||
tree context = CP_DECL_CONTEXT (decl);
|
||||
if (context
|
||||
&& TYPE_P (context)
|
||||
&& (TREE_CODE (decl) == VAR_DECL
|
||||
/* We also have a pushclass done that we need to undo here
|
||||
if we're at top level and declare a method. */
|
||||
|| TREE_CODE (decl) == FUNCTION_DECL)
|
||||
/* If size hasn't been set, we're still defining it,
|
||||
and therefore inside the class body; don't pop
|
||||
the binding level.. */
|
||||
&& COMPLETE_TYPE_P (context)
|
||||
&& context == current_class_type)
|
||||
pop_nested_class ();
|
||||
}
|
||||
}
|
||||
|
||||
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
|
||||
@ -9663,6 +9622,9 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
&& lookup_attribute ("noinline", attrs))
|
||||
warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
|
||||
|
||||
/* Determine the ELF visibility attribute for the function. */
|
||||
determine_visibility (decl1);
|
||||
|
||||
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
|
||||
/* This is a constructor, we must ensure that any default args
|
||||
introduced by this definition are propagated to the clones
|
||||
|
@ -1616,6 +1616,59 @@ maybe_emit_vtables (tree ctype)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Determine the ELF symbol visibility for DECL. */
|
||||
|
||||
void
|
||||
determine_visibility (tree decl)
|
||||
{
|
||||
tree class_type;
|
||||
|
||||
/* Cloned constructors and destructors get the same visibility as
|
||||
the underlying function. That should be set up in
|
||||
maybe_clone_body. */
|
||||
if (DECL_CLONED_FUNCTION_P (decl))
|
||||
return;
|
||||
|
||||
if (DECL_CLASS_SCOPE_P (decl))
|
||||
class_type = DECL_CONTEXT (decl);
|
||||
else if (TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_TINFO_P (decl)
|
||||
&& CLASS_TYPE_P (TREE_TYPE (DECL_NAME (decl))))
|
||||
class_type = TREE_TYPE (DECL_NAME (decl));
|
||||
else
|
||||
{
|
||||
/* Virtual tables have DECL_CONTEXT set to their associated class,
|
||||
so they are automatically handled above. */
|
||||
my_friendly_assert (!(TREE_CODE (decl) == VAR_DECL
|
||||
&& DECL_VTABLE_OR_VTT_P (decl)), 20040803);
|
||||
/* Entities not associated with any class just get the
|
||||
visibility specified by their attributes. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* By default, static data members and function members receive
|
||||
the visibility of their containing class. */
|
||||
if (class_type
|
||||
&& (TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == FUNCTION_DECL)
|
||||
&& !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
|
||||
{
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_INLINE_P (decl)
|
||||
&& visibility_options.inlines_hidden)
|
||||
{
|
||||
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (decl) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
|
||||
DECL_VISIBILITY_SPECIFIED (decl)
|
||||
= CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage
|
||||
for DECL has not already been determined, do so now by setting
|
||||
DECL_EXTERNAL, DECL_COMDAT and other related flags. Until this
|
||||
|
@ -368,7 +368,8 @@ 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);
|
||||
DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
|
||||
= DECL_VISIBILITY_SPECIFIED (function);
|
||||
if (flag_weak && TREE_PUBLIC (thunk_fndecl))
|
||||
comdat_linkage (thunk_fndecl);
|
||||
|
||||
|
@ -6312,10 +6312,13 @@ cp_parser_condition (cp_parser* parser)
|
||||
for sure. */
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
{
|
||||
bool pop_p;
|
||||
|
||||
/* Create the declaration. */
|
||||
decl = start_decl (declarator, &type_specifiers,
|
||||
/*initialized_p=*/true,
|
||||
attributes, /*prefix_attributes=*/NULL_TREE);
|
||||
attributes, /*prefix_attributes=*/NULL_TREE,
|
||||
&pop_p);
|
||||
/* Parse the assignment-expression. */
|
||||
initializer = cp_parser_assignment_expression (parser);
|
||||
|
||||
@ -6324,6 +6327,8 @@ cp_parser_condition (cp_parser* parser)
|
||||
initializer,
|
||||
asm_specification,
|
||||
LOOKUP_ONLYCONVERTING);
|
||||
if (pop_p)
|
||||
pop_scope (DECL_CONTEXT (decl));
|
||||
|
||||
return convert_from_reference (decl);
|
||||
}
|
||||
@ -10630,12 +10635,12 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
have_extern_spec = false;
|
||||
}
|
||||
decl = start_decl (declarator, decl_specifiers,
|
||||
is_initialized, attributes, prefix_attributes);
|
||||
is_initialized, attributes, prefix_attributes,
|
||||
&pop_p);
|
||||
}
|
||||
|
||||
/* Enter the SCOPE. That way unqualified names appearing in the
|
||||
initializer will be looked up in SCOPE. */
|
||||
if (scope)
|
||||
else if (scope)
|
||||
/* Enter the SCOPE. That way unqualified names appearing in the
|
||||
initializer will be looked up in SCOPE. */
|
||||
pop_p = push_scope (scope);
|
||||
|
||||
/* Perform deferred access control checks, now that we know in which
|
||||
@ -10682,17 +10687,12 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
if (cp_parser_attributes_opt (parser))
|
||||
warning ("attributes after parenthesized initializer ignored");
|
||||
|
||||
/* Leave the SCOPE, now that we have processed the initializer. It
|
||||
is important to do this before calling cp_finish_decl because it
|
||||
makes decisions about whether to create DECL_EXPRs or not based
|
||||
on the current scope. */
|
||||
if (pop_p)
|
||||
pop_scope (scope);
|
||||
|
||||
/* For an in-class declaration, use `grokfield' to create the
|
||||
declaration. */
|
||||
if (member_p)
|
||||
{
|
||||
if (pop_p)
|
||||
pop_scope (scope);
|
||||
decl = grokfield (declarator, decl_specifiers,
|
||||
initializer, /*asmspec=*/NULL_TREE,
|
||||
/*attributes=*/NULL_TREE);
|
||||
@ -10703,15 +10703,19 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||
/* Finish processing the declaration. But, skip friend
|
||||
declarations. */
|
||||
if (!friend_p && decl)
|
||||
cp_finish_decl (decl,
|
||||
initializer,
|
||||
asm_specification,
|
||||
/* If the initializer is in parentheses, then this is
|
||||
a direct-initialization, which means that an
|
||||
`explicit' constructor is OK. Otherwise, an
|
||||
`explicit' constructor cannot be used. */
|
||||
((is_parenthesized_init || !is_initialized)
|
||||
{
|
||||
cp_finish_decl (decl,
|
||||
initializer,
|
||||
asm_specification,
|
||||
/* If the initializer is in parentheses, then this is
|
||||
a direct-initialization, which means that an
|
||||
`explicit' constructor is OK. Otherwise, an
|
||||
`explicit' constructor cannot be used. */
|
||||
((is_parenthesized_init || !is_initialized)
|
||||
? 0 : LOOKUP_ONLYCONVERTING));
|
||||
if (pop_p)
|
||||
pop_scope (DECL_CONTEXT (decl));
|
||||
}
|
||||
|
||||
/* Remember whether or not variables were initialized by
|
||||
constant-expressions. */
|
||||
|
11
gcc/cp/pt.c
11
gcc/cp/pt.c
@ -11162,20 +11162,13 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
|
||||
we have a chance to determine linkage. */
|
||||
DECL_EXTERNAL (d) = 0;
|
||||
|
||||
/* This is done in analogous to `start_decl'. It is required
|
||||
for correct access checking. */
|
||||
/* Enter the scope of D so that access-checking works correctly. */
|
||||
push_nested_class (DECL_CONTEXT (d));
|
||||
cp_finish_decl (d,
|
||||
(!DECL_INITIALIZED_IN_CLASS_P (d)
|
||||
? DECL_INITIAL (d) : NULL_TREE),
|
||||
NULL_TREE, 0);
|
||||
/* Normally, pop_nested_class is called by cp_finish_decl above.
|
||||
But when instantiate_decl is triggered during
|
||||
instantiate_class_template processing, its DECL_CONTEXT is
|
||||
still not completed yet, and pop_nested_class isn't
|
||||
called. */
|
||||
if (!COMPLETE_TYPE_P (DECL_CONTEXT (d)))
|
||||
pop_nested_class ();
|
||||
pop_nested_class ();
|
||||
}
|
||||
else if (TREE_CODE (d) == FUNCTION_DECL)
|
||||
{
|
||||
|
@ -346,6 +346,8 @@ get_tinfo_decl (tree type)
|
||||
|
||||
d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
|
||||
SET_DECL_ASSEMBLER_NAME (d, name);
|
||||
/* Remember the type it is for. */
|
||||
TREE_TYPE (name) = type;
|
||||
DECL_TINFO_P (d) = 1;
|
||||
DECL_ARTIFICIAL (d) = 1;
|
||||
TREE_READONLY (d) = 1;
|
||||
@ -354,19 +356,10 @@ get_tinfo_decl (tree type)
|
||||
define it later if we need to do so. */
|
||||
DECL_EXTERNAL (d) = 1;
|
||||
DECL_NOT_REALLY_EXTERN (d) = 1;
|
||||
set_linkage_according_to_type (type, d);
|
||||
|
||||
pushdecl_top_level_and_finish (d, NULL_TREE);
|
||||
|
||||
if (CLASS_TYPE_P (type))
|
||||
{
|
||||
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;
|
||||
CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
|
||||
set_linkage_according_to_type (type, d);
|
||||
pushdecl_top_level_and_finish (d, NULL_TREE);
|
||||
|
||||
/* Add decl to the global array of tinfo decls. */
|
||||
my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
|
||||
@ -791,18 +784,12 @@ tinfo_base_init (tree desc, tree target)
|
||||
TREE_TYPE (name_name) = target;
|
||||
|
||||
name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
|
||||
|
||||
SET_DECL_ASSEMBLER_NAME (name_decl, name_name);
|
||||
DECL_ARTIFICIAL (name_decl) = 1;
|
||||
TREE_READONLY (name_decl) = 1;
|
||||
TREE_STATIC (name_decl) = 1;
|
||||
DECL_EXTERNAL (name_decl) = 0;
|
||||
DECL_TINFO_P (name_decl) = 1;
|
||||
if (CLASS_TYPE_P (target))
|
||||
{
|
||||
DECL_VISIBILITY (name_decl) = CLASSTYPE_VISIBILITY (target);
|
||||
DECL_VISIBILITY_SPECIFIED (name_decl)
|
||||
= CLASSTYPE_VISIBILITY_SPECIFIED (target);
|
||||
}
|
||||
if (involves_incomplete_p (target))
|
||||
{
|
||||
TREE_PUBLIC (name_decl) = 0;
|
||||
@ -811,10 +798,6 @@ tinfo_base_init (tree desc, tree target)
|
||||
else
|
||||
set_linkage_according_to_type (target, name_decl);
|
||||
import_export_decl (name_decl);
|
||||
/* External name of the string containing the type's name has a
|
||||
special name. */
|
||||
SET_DECL_ASSEMBLER_NAME (name_decl,
|
||||
mangle_typeinfo_string_for_type (target));
|
||||
DECL_INITIAL (name_decl) = name_string;
|
||||
mark_used (name_decl);
|
||||
pushdecl_top_level_and_finish (name_decl, name_string);
|
||||
|
17
gcc/testsuite/g++.dg/ext/visibility/assign1.C
Normal file
17
gcc/testsuite/g++.dg/ext/visibility/assign1.C
Normal file
@ -0,0 +1,17 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-visibility "" } */
|
||||
/* { dg-final { scan-assembler "\\.hidden.*_ZN1DaSERKS_" } } */
|
||||
|
||||
struct B {
|
||||
B& operator=(const B&);
|
||||
};
|
||||
|
||||
struct D : public B {
|
||||
// The implicit assignment operator should be hidden.
|
||||
} __attribute__((visibility("hidden")));
|
||||
|
||||
D d1, d2;
|
||||
|
||||
void f() {
|
||||
d1 = d2;
|
||||
}
|
14
gcc/testsuite/g++.dg/ext/visibility/new1.C
Normal file
14
gcc/testsuite/g++.dg/ext/visibility/new1.C
Normal file
@ -0,0 +1,14 @@
|
||||
// { dg-require-visibility }
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fvisibility=hidden" }
|
||||
// { dg-final { scan-assembler-not "\\.hidden\[^\n\]*_Znwj" } }
|
||||
|
||||
void f() {
|
||||
new int;
|
||||
}
|
||||
|
||||
void *g();
|
||||
|
||||
void *operator new(__SIZE_TYPE__) {
|
||||
return g();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user