This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: C++ Bug w/new-abi: Same function emitted twice
- To: chip at valinux dot com
- Subject: Re: C++ Bug w/new-abi: Same function emitted twice
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 11 Jun 2000 23:44:01 -0700
- Cc: gcc-bugs at gcc dot gnu dot org
- Organization: CodeSourcery, LLC
- References: <20000611200236.H1288@perlsupport.com>
Fixed with this patch, which nails a few other new ABI problems as
well.
Tested on i686-pc-linux-gnu.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-06-11 Mark Mitchell <mark@codesourcery.com>
* mangle.c (NESTED_TEMPLATE_MATCH): Fix typo in comment.
(is_std_substitution): Don't check CLASSTYPE_USE_TEMPLATE here.
(find_substitution): Only use the `Sa' substitution for
std::allocator, not instantiations of it.
(write_template_prefix): Move comment. Only use a TREE_LIST to
represent substitutions for a member template.
(write_array_type): Mangle array dimensions correctly.
* optimize.c (maybe_clone_body): Copy more information from the
cloned function.
* pt.c (regenerate_decl_from_template): Preserve DECL_USE_TEMPLATE
on the regenerated declaration.
Index: mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.7
diff -c -p -r1.7 mangle.c
*** mangle.c 2000/06/11 03:57:18 1.7
--- mangle.c 2000/06/12 06:39:54
*************** static tree mangle_special_for_type PARA
*** 208,215 ****
#define mangled_position() \
obstack_object_size (&G.name_obstack)
! /* Non-zero if NODE1__ and NODE2__ are both TREE_LIST nodes and have
! the same purpose (context, which may be a type) and value (template
decl). See write_template_prefix for more information on what this
is used for. */
#define NESTED_TEMPLATE_MATCH(NODE1, NODE2) \
--- 208,215 ----
#define mangled_position() \
obstack_object_size (&G.name_obstack)
! /* Non-zero if NODE1 and NODE2 are both TREE_LIST nodes and have the
! same purpose (context, which may be a type) and value (template
decl). See write_template_prefix for more information on what this
is used for. */
#define NESTED_TEMPLATE_MATCH(NODE1, NODE2) \
*************** is_std_substitution (node, index)
*** 348,359 ****
/* These are not the droids you're looking for. */
return 0;
! return
! DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
! && TYPE_LANG_SPECIFIC (type)
! && CLASSTYPE_USE_TEMPLATE (type)
! && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
! == subst_identifiers[index]);
}
/* Helper function for find_substitution. Returns non-zero if NODE,
--- 348,358 ----
/* These are not the droids you're looking for. */
return 0;
! return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
! && TYPE_LANG_SPECIFIC (type)
! && CLASSTYPE_TEMPLATE_INFO (type)
! && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
! == subst_identifiers[index]));
}
/* Helper function for find_substitution. Returns non-zero if NODE,
*************** find_substitution (node)
*** 441,447 ****
type = TYPE_P (node) ? node : TREE_TYPE (node);
/* Check for std::allocator. */
! if (decl && is_std_substitution (decl, SUBID_ALLOCATOR))
{
write_string ("Sa");
return 1;
--- 440,448 ----
type = TYPE_P (node) ? node : TREE_TYPE (node);
/* Check for std::allocator. */
! if (decl
! && is_std_substitution (decl, SUBID_ALLOCATOR)
! && !CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)))
{
write_string ("Sa");
return 1;
*************** write_prefix (node)
*** 782,813 ****
}
/* <template-prefix> ::= <prefix> <template component>
! ::= <substitution>
!
! Names of templates are substitution candidates. For a nested
! template, though, the template name for the innermost name must
! have all the outer template levels instantiated. For instance,
! consider
!
! template<typename T> struct Outer
! {
! template<typename U> struct Inner {};
! };
!
! The template name for `Inner' in `Outer<int>::Inner<float>' is
! `Outer<int>::Inner<U>'. In g++, we don't instantiate the template
! levels separately, so there's no TEMPLATE_DECL available for this
! (there's only `Outer<T>::Inner<U>').
!
! In order to get the substitutions right, we create a special
! TREE_LIST to represent the substitution candidate for a nested
! template. The TREE_PURPOSE is the tempate's context, fully
! instantiated, and the TREE_VALUE is the TEMPLATE_DECL for the inner
! template.
!
! So, for the example above, `Inner' is represented as a substitution
! candidate by a TREE_LIST whose purpose is `Outer<int>' and whose
! value is `Outer<T>::Inner<U>'. */
static void
write_template_prefix (node)
--- 783,789 ----
}
/* <template-prefix> ::= <prefix> <template component>
! ::= <substitution> */
static void
write_template_prefix (node)
*************** write_template_prefix (node)
*** 830,837 ****
/* Oops, not a template. */
my_friendly_abort (20000524);
! /* Build the substitution candidate TREE_LIST. */
! substitution = build_tree_list (context, template);
if (find_substitution (substitution))
return;
--- 806,837 ----
/* Oops, not a template. */
my_friendly_abort (20000524);
! /* For a member template, though, the template name for the
! innermost name must have all the outer template levels
! instantiated. For instance, consider
!
! template<typename T> struct Outer {
! template<typename U> struct Inner {};
! };
!
! The template name for `Inner' in `Outer<int>::Inner<float>' is
! `Outer<int>::Inner<U>'. In g++, we don't instantiate the template
! levels separately, so there's no TEMPLATE_DECL available for this
! (there's only `Outer<T>::Inner<U>').
!
! In order to get the substitutions right, we create a special
! TREE_LIST to represent the substitution candidate for a nested
! template. The TREE_PURPOSE is the template's context, fully
! instantiated, and the TREE_VALUE is the TEMPLATE_DECL for the inner
! template.
!
! So, for the example above, `Outer<int>::Inner' is represented as a
! substitution candidate by a TREE_LIST whose purpose is `Outer<int>'
! and whose value is `Outer<T>::Inner<U>'. */
! if (TYPE_P (context))
! substitution = build_tree_list (context, template);
! else
! substitution = template;
if (find_substitution (substitution))
return;
*************** write_array_type (type)
*** 1768,1774 ****
array. */
max = TYPE_MAX_VALUE (index_type);
if (TREE_CODE (max) == INTEGER_CST)
! write_unsigned_number (tree_low_cst (max, 1));
else
write_expression (TREE_OPERAND (max, 0));
}
--- 1768,1779 ----
array. */
max = TYPE_MAX_VALUE (index_type);
if (TREE_CODE (max) == INTEGER_CST)
! {
! /* The ABI specifies that we should mangle the number of
! elements in the array, not the largest allowed index. */
! max = size_binop (PLUS_EXPR, max, size_one_node);
! write_unsigned_number (tree_low_cst (max, 1));
! }
else
write_expression (TREE_OPERAND (max, 0));
}
Index: optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.35
diff -c -p -r1.35 optimize.c
*** optimize.c 2000/06/09 16:23:46 1.35
--- optimize.c 2000/06/12 06:39:55
*************** maybe_clone_body (fn)
*** 911,916 ****
--- 911,920 ----
DECL_WEAK (clone) = DECL_WEAK (fn);
DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn);
DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
+ DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
+ DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
+ DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
+ DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
/* Start processing the function. */
push_to_top_level ();
Index: pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.437
diff -c -p -r1.437 pt.c
*** pt.c 2000/06/09 16:26:24 1.437
--- pt.c 2000/06/12 06:40:00
*************** regenerate_decl_from_template (decl, tmp
*** 9469,9474 ****
--- 9469,9475 ----
DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
DECL_RTL (new_decl) = DECL_RTL (decl);
+ DECL_USE_TEMPLATE (new_decl) = DECL_USE_TEMPLATE (decl);
/* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);