This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: C++ Bug w/new-abi: Same function emitted twice



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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]