This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Improve DECL_VISIBILIITY machinery
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 3 Aug 2004 22:33:44 -0700
- Subject: C++ PATCH: Improve DECL_VISIBILIITY machinery
- Reply-to: mark at codesourcery dot com
This patch fixes a couple of bugs with the new DECL_VISIBILITY stuff:
neither implicit methods nor library functions were getting their
libraries set correctly. The original patch also had a variety of
formatting problems, which I corrected. Finally, I moved the
machinery for setting DECL_VISIBILITY into a single function, which
makes it much easier to change the way this stuff works if necessary.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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-03 Mark Mitchell <mark@codesourcery.com>
* g++.dg/ext/visibility/assign1.C: New test.
* g++.dg/ext/visibility/new1.C: Likewise.
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.647
diff -c -5 -p -r1.647 class.c
*** cp/class.c 29 Jul 2004 17:59:25 -0000 1.647
--- cp/class.c 4 Aug 2004 03:26:15 -0000
*************** build_vtable (tree class_type, tree name
*** 657,671 ****
attached to the member list for `S' before the debug info for
`S' get written (which would solve the problem) but that would
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;
}
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
or even complete. If this does not exist, create it. If COMPLETE is
--- 657,666 ----
*************** check_field_decls (tree t, tree *access_
*** 2969,2997 ****
if (type == error_mark_node)
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;
! }
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
--- 2964,2974 ----
if (type == error_mark_node)
continue;
if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
! continue;
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
*************** check_methods (tree t)
*** 3742,3768 ****
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
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))
{
TYPE_POLYMORPHIC_P (t) = 1;
--- 3719,3728 ----
*************** initialize_vtable (tree binfo, tree init
*** 6738,6754 ****
the 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.
A class requires a VTT if it has virtual bases.
--- 6698,6709 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1027
diff -c -5 -p -r1.1027 cp-tree.h
*** cp/cp-tree.h 2 Aug 2004 01:58:50 -0000 1.1027
--- cp/cp-tree.h 4 Aug 2004 03:26:15 -0000
*************** extern tree push_void_library_fn (tree,
*** 3738,3748 ****
extern tree push_throw_library_fn (tree, tree);
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 void start_decl_1 (tree);
extern void cp_finish_decl (tree, tree, tree, int);
extern void finish_decl (tree, tree, tree);
extern int complete_array_type (tree, tree, int);
extern tree build_ptrmemfunc_type (tree);
--- 3738,3748 ----
extern tree push_throw_library_fn (tree, tree);
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, bool *);
extern void start_decl_1 (tree);
extern void cp_finish_decl (tree, tree, tree, int);
extern void finish_decl (tree, tree, tree);
extern int complete_array_type (tree, tree, int);
extern tree build_ptrmemfunc_type (tree);
*************** extern void cplus_decl_attributes (tree
*** 3823,3832 ****
--- 3823,3833 ----
extern void finish_anon_union (tree);
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);
extern void check_default_args (tree);
extern void mark_used (tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1266
diff -c -5 -p -r1.1266 decl.c
*** cp/decl.c 2 Aug 2004 01:58:50 -0000 1.1266
--- cp/decl.c 4 Aug 2004 03:26:16 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1879,1916 ****
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
/* Warn about conflicting visibility specifications. */
! if (DECL_VISIBILITY_SPECIFIED (olddecl) && DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%J'%D': visibility attribute ignored because it",
! newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
/* Choose the declaration which specified visibility. */
if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
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)
{
int function_size;
--- 1879,1902 ----
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
/* Warn about conflicting visibility specifications. */
! if (DECL_VISIBILITY_SPECIFIED (olddecl)
! && DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%J'%D': visibility attribute ignored because it",
! newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
/* Choose the declaration which specified visibility. */
if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
*************** build_library_fn_1 (tree name, enum tree
*** 3274,3283 ****
--- 3260,3273 ----
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
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;
}
/* Returns the _DECL for a library function with C linkage.
We assume that such functions never throw; if this is incorrect,
*************** groktypename (cp_decl_specifier_seq *typ
*** 3605,3615 ****
tree
start_decl (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
int initialized,
tree attributes,
! tree prefix_attributes)
{
tree decl;
tree type, tem;
tree context;
--- 3595,3606 ----
tree
start_decl (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
int initialized,
tree attributes,
! tree prefix_attributes,
! bool *pop_scope_p)
{
tree decl;
tree type, tem;
tree context;
*************** start_decl (const cp_declarator *declara
*** 3640,3657 ****
if (type == error_mark_node)
return NULL_TREE;
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);
! }
!
/* We are only interested in class contexts, later. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
if (initialized)
--- 3631,3645 ----
if (type == error_mark_node)
return NULL_TREE;
context = DECL_CONTEXT (decl);
! 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;
if (initialized)
*************** start_decl (const cp_declarator *declara
*** 3703,3714 ****
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning ("%Jinline function '%D' given attribute noinline", decl, decl);
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);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
error ("`%#D' is not a static member of `%#T'", decl, context);
--- 3691,3700 ----
*************** cp_finish_decl (tree decl, tree init, tr
*** 4713,4736 ****
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (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;
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
--- 4699,4712 ----
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
type = TREE_TYPE (decl);
if (type == error_mark_node)
! goto finish_end;
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
*************** cp_finish_decl (tree decl, tree init, tr
*** 4743,4753 ****
DECL_INITIAL (decl) = init;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
maybe_deduce_size_from_array_init (decl, init);
! goto finish_end0;
}
/* Parameters are handled by store_parm_decls, not cp_finish_decl. */
my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
--- 4719,4729 ----
DECL_INITIAL (decl) = init;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
maybe_deduce_size_from_array_init (decl, init);
! goto finish_end;
}
/* Parameters are handled by store_parm_decls, not cp_finish_decl. */
my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
*************** cp_finish_decl (tree decl, tree init, tr
*** 4831,4840 ****
--- 4807,4819 ----
/*nelts=*/NULL_TREE,
/*static_storage_p=*/true);
/* 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
array, and we must get TYPE_ALIGN set correctly on the array
type. */
*************** cp_finish_decl (tree decl, tree init, tr
*** 4897,4926 ****
}
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
reference, insert it in the statement-tree now. */
if (cleanup)
--- 4876,4885 ----
*************** start_preparsed_function (tree decl1, tr
*** 9661,9670 ****
--- 9620,9632 ----
if (DECL_DECLARED_INLINE_P (decl1)
&& 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
now. The clones are used directly in overload resolution. */
adjust_clone_args (decl1);
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.730
diff -c -5 -p -r1.730 decl2.c
*** cp/decl2.c 29 Jul 2004 17:59:27 -0000 1.730
--- cp/decl2.c 4 Aug 2004 03:26:16 -0000
*************** maybe_emit_vtables (tree ctype)
*** 1614,1623 ****
--- 1614,1676 ----
note_debug_info_needed (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
function is called entities with vague linkage whose definitions
are available must have TREE_PUBLIC set.
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.305
diff -c -5 -p -r1.305 method.c
*** cp/method.c 29 Jul 2004 17:59:28 -0000 1.305
--- cp/method.c 4 Aug 2004 03:26:16 -0000
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 366,376 ****
DECL_EXTERNAL (thunk_fndecl) = 0;
/* The linkage of the function may have changed. FIXME in linkage
rewrite. */
TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
! DECL_VISIBILITY_SPECIFIED (thunk_fndecl) = DECL_VISIBILITY_SPECIFIED (function);
if (flag_weak && TREE_PUBLIC (thunk_fndecl))
comdat_linkage (thunk_fndecl);
if (flag_syntax_only)
{
--- 366,377 ----
DECL_EXTERNAL (thunk_fndecl) = 0;
/* The linkage of the function may have changed. FIXME in linkage
rewrite. */
TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
! DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
! = DECL_VISIBILITY_SPECIFIED (function);
if (flag_weak && TREE_PUBLIC (thunk_fndecl))
comdat_linkage (thunk_fndecl);
if (flag_syntax_only)
{
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.231
diff -c -5 -p -r1.231 parser.c
*** cp/parser.c 25 Jul 2004 17:19:39 -0000 1.231
--- cp/parser.c 4 Aug 2004 03:26:16 -0000
*************** cp_parser_condition (cp_parser* parser)
*** 6310,6331 ****
cp_parser_require (parser, CPP_EQ, "`='");
/* If we did see an `=', then we are looking at a declaration
for sure. */
if (cp_parser_parse_definitely (parser))
{
/* Create the declaration. */
decl = start_decl (declarator, &type_specifiers,
/*initialized_p=*/true,
! attributes, /*prefix_attributes=*/NULL_TREE);
/* Parse the assignment-expression. */
initializer = cp_parser_assignment_expression (parser);
/* Process the initializer. */
cp_finish_decl (decl,
initializer,
asm_specification,
LOOKUP_ONLYCONVERTING);
return convert_from_reference (decl);
}
}
/* If we didn't even get past the declarator successfully, we are
--- 6310,6336 ----
cp_parser_require (parser, CPP_EQ, "`='");
/* If we did see an `=', then we are looking at a declaration
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,
! &pop_p);
/* Parse the assignment-expression. */
initializer = cp_parser_assignment_expression (parser);
/* Process the initializer. */
cp_finish_decl (decl,
initializer,
asm_specification,
LOOKUP_ONLYCONVERTING);
+ if (pop_p)
+ pop_scope (DECL_CONTEXT (decl));
return convert_from_reference (decl);
}
}
/* If we didn't even get past the declarator successfully, we are
*************** cp_parser_init_declarator (cp_parser* pa
*** 10628,10643 ****
{
decl_specifiers->storage_class = sc_extern;
have_extern_spec = false;
}
decl = start_decl (declarator, decl_specifiers,
! is_initialized, attributes, prefix_attributes);
}
!
! /* Enter the SCOPE. That way unqualified names appearing in the
! initializer will be looked up in SCOPE. */
! if (scope)
pop_p = push_scope (scope);
/* Perform deferred access control checks, now that we know in which
SCOPE the declared entity resides. */
if (!member_p && decl)
--- 10633,10648 ----
{
decl_specifiers->storage_class = sc_extern;
have_extern_spec = false;
}
decl = start_decl (declarator, decl_specifiers,
! is_initialized, attributes, prefix_attributes,
! &pop_p);
}
! 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
SCOPE the declared entity resides. */
if (!member_p && decl)
*************** cp_parser_init_declarator (cp_parser* pa
*** 10680,10719 ****
attributes -- but ignores them. */
if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
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)
{
decl = grokfield (declarator, decl_specifiers,
initializer, /*asmspec=*/NULL_TREE,
/*attributes=*/NULL_TREE);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
}
/* 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)
? 0 : LOOKUP_ONLYCONVERTING));
/* Remember whether or not variables were initialized by
constant-expressions. */
if (decl && TREE_CODE (decl) == VAR_DECL
&& is_initialized && !is_non_constant_init)
--- 10685,10723 ----
attributes -- but ignores them. */
if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
if (cp_parser_attributes_opt (parser))
warning ("attributes after parenthesized initializer ignored");
/* 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);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
}
/* 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)
? 0 : LOOKUP_ONLYCONVERTING));
+ if (pop_p)
+ pop_scope (DECL_CONTEXT (decl));
+ }
/* Remember whether or not variables were initialized by
constant-expressions. */
if (decl && TREE_CODE (decl) == VAR_DECL
&& is_initialized && !is_non_constant_init)
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.900
diff -c -5 -p -r1.900 pt.c
*** cp/pt.c 2 Aug 2004 06:25:32 -0000 1.900
--- cp/pt.c 4 Aug 2004 03:26:16 -0000
*************** instantiate_decl (tree d, int defer_ok,
*** 11160,11183 ****
/* Clear DECL_EXTERNAL so that cp_finish_decl will process the
initializer. That function will defer actual emission until
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. */
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 ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
tree subst_decl;
--- 11160,11176 ----
/* Clear DECL_EXTERNAL so that cp_finish_decl will process the
initializer. That function will defer actual emission until
we have a chance to determine linkage. */
DECL_EXTERNAL (d) = 0;
! /* 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);
! pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
tree subst_decl;
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.193
diff -c -5 -p -r1.193 rtti.c
*** cp/rtti.c 29 Jul 2004 17:59:28 -0000 1.193
--- cp/rtti.c 4 Aug 2004 03:26:16 -0000
*************** get_tinfo_decl (tree type)
*** 344,375 ****
{
tree var_desc = get_pseudo_ti_desc (type);
d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
SET_DECL_ASSEMBLER_NAME (d, name);
DECL_TINFO_P (d) = 1;
DECL_ARTIFICIAL (d) = 1;
TREE_READONLY (d) = 1;
TREE_STATIC (d) = 1;
/* Mark the variable as undefined -- but remember that we can
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;
-
/* Add decl to the global array of tinfo decls. */
my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);
}
--- 344,368 ----
{
tree var_desc = get_pseudo_ti_desc (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;
TREE_STATIC (d) = 1;
/* Mark the variable as undefined -- but remember that we can
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);
/* Add decl to the global array of tinfo decls. */
my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);
VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);
}
*************** tinfo_base_init (tree desc, tree target)
*** 789,822 ****
type it is associated. */
name_name = mangle_typeinfo_string_for_type (target);
TREE_TYPE (name_name) = target;
name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
!
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;
DECL_INTERFACE_KNOWN (name_decl) = 1;
}
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);
}
--- 782,805 ----
type it is associated. */
name_name = mangle_typeinfo_string_for_type (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 (involves_incomplete_p (target))
{
TREE_PUBLIC (name_decl) = 0;
DECL_INTERFACE_KNOWN (name_decl) = 1;
}
else
set_linkage_according_to_type (target, name_decl);
import_export_decl (name_decl);
DECL_INITIAL (name_decl) = name_string;
mark_used (name_decl);
pushdecl_top_level_and_finish (name_decl, name_string);
}
Index: testsuite/g++.dg/ext/visibility/assign1.C
===================================================================
RCS file: testsuite/g++.dg/ext/visibility/assign1.C
diff -N testsuite/g++.dg/ext/visibility/assign1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/visibility/assign1.C 4 Aug 2004 03:26:16 -0000
***************
*** 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;
+ }
Index: testsuite/g++.dg/ext/visibility/new1.C
===================================================================
RCS file: testsuite/g++.dg/ext/visibility/new1.C
diff -N testsuite/g++.dg/ext/visibility/new1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/visibility/new1.C 4 Aug 2004 03:26:16 -0000
***************
*** 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();
+ }