From: Mark Mitchell Date: Wed, 4 Aug 2004 05:27:52 +0000 (+0000) Subject: class.c (build_vtable): Do not set DECL_VISIBILITY here. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=73a8adb62e1609c94e21903fe9c261b6d30a8415;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d87b4827aee..e82e5005d00 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2004-08-03 Mark Mitchell + + * 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 PR c++/16707 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 365febbb704..e0bae52179f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index cdb67063f3a..5b499256238 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c4755c0c7b0..8c85e71003d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 40322ab31cc..53060dd16fa 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d741d3d3cd1..7a2a7624fd8 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f19ab252e27..d6aadb37cd7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1e9bbb13122..14b0c837cf2 100644 --- a/gcc/cp/pt.c +++ b/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) { diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 83e24c4e21c..a59af79460b 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -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,20 +356,11 @@ get_tinfo_decl (tree type) define it later if we need to do so. */ DECL_EXTERNAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; + if (CLASS_TYPE_P (type)) + CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; 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; - /* Add decl to the global array of tinfo decls. */ my_friendly_assert (unemitted_tinfo_decls != 0, 20030312); VARRAY_PUSH_TREE (unemitted_tinfo_decls, d); @@ -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); diff --git a/gcc/testsuite/g++.dg/ext/visibility/assign1.C b/gcc/testsuite/g++.dg/ext/visibility/assign1.C new file mode 100644 index 00000000000..6d7392fd04b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/assign1.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/ext/visibility/new1.C b/gcc/testsuite/g++.dg/ext/visibility/new1.C new file mode 100644 index 00000000000..0f0be5148da --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/new1.C @@ -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(); +}