This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

C++ PATCH: PR 20142


This patch fixes a wrong-code regression; we were forgetting to look
through multiple array dimensions when determining whether or not an
array element defined "operator=".

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
3.4 and 4.0 branches.  The applications on the branch contain only the
init.c change, to minimize risk.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-03-08  Mark Mitchell  <mark@codesourcery.com>

	PR c++/20142
	* cp-tree.h (target_type): Remove.
	* decl.c (layout_var_decl): Remove #if 0'd code.
	(cp_finish_decl): Remove dead code.
	* init.c (build_vec_init): When determining whether or not the
	element type has an asignment operator, look through all array
	dimensions. 
	* typeck.c (target_type): Remove.

2005-03-08  Mark Mitchell  <mark@codesourcery.com>

	PR c++/20142
	* g++.dg/init/array18.C: New test.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1107
diff -c -5 -p -r1.1107 cp-tree.h
*** cp/cp-tree.h	1 Mar 2005 09:57:38 -0000	1.1107
--- cp/cp-tree.h	9 Mar 2005 07:23:41 -0000
*************** extern tree fold_if_not_in_template     
*** 4265,4275 ****
  
  /* in typeck.c */
  extern int string_conv_p			(tree, tree, int);
  extern tree cp_truthvalue_conversion		(tree);
  extern tree condition_conversion		(tree);
- extern tree target_type				(tree);
  extern tree require_complete_type		(tree);
  extern tree complete_type			(tree);
  extern tree complete_type_or_else		(tree, tree);
  extern int type_unknown_p			(tree);
  extern tree original_type			(tree);
--- 4265,4274 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1374
diff -c -5 -p -r1.1374 decl.c
*** cp/decl.c	2 Mar 2005 19:55:48 -0000	1.1374
--- cp/decl.c	9 Mar 2005 07:23:42 -0000
*************** maybe_deduce_size_from_array_init (tree 
*** 3938,3950 ****
  
  static void
  layout_var_decl (tree decl)
  {
    tree type = TREE_TYPE (decl);
- #if 0
-   tree ttype = target_type (type);
- #endif
  
    /* If we haven't already layed out this declaration, do so now.
       Note that we must not call complete type for an external object
       because it's type might involve templates that we are not
       supposed to instantiate yet.  (And it's perfectly valid to say
--- 3938,3947 ----
*************** initialize_artificial_var (tree decl, tr
*** 4708,4718 ****
  
  void
  cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
  {
    tree type;
-   tree ttype = NULL_TREE;
    tree cleanup;
    const char *asmspec = NULL;
    int was_readonly = 0;
    bool var_definition_p = false;
  
--- 4705,4714 ----
*************** cp_finish_decl (tree decl, tree init, tr
*** 4793,4806 ****
        rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
  				at_eof);
        goto finish_end;
      }
  
-   if (TREE_CODE (decl) != FUNCTION_DECL)
-     ttype = target_type (type);
- 
- 
    /* A reference will be modified here, as it is initialized.  */
    if (! DECL_EXTERNAL (decl) 
        && TREE_READONLY (decl)
        && TREE_CODE (type) == REFERENCE_TYPE)
      {
--- 4789,4798 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.413
diff -c -5 -p -r1.413 init.c
*** cp/init.c	5 Mar 2005 15:44:19 -0000	1.413
--- cp/init.c	9 Mar 2005 07:23:42 -0000
*************** build_vec_init (tree base, tree maxindex
*** 2386,2395 ****
--- 2386,2398 ----
    tree iterator;
    /* The type of the array.  */
    tree atype = TREE_TYPE (base);
    /* The type of an element in the array.  */
    tree type = TREE_TYPE (atype);
+   /* The element type reached after removing all outer array 
+      types.  */
+   tree inner_elt_type;
    /* The type of a pointer to an element in the array.  */
    tree ptype;
    tree stmt_expr;
    tree compound_stmt;
    int destroy_temps;
*************** build_vec_init (tree base, tree maxindex
*** 2401,2419 ****
      maxindex = array_type_nelts (atype);
  
    if (maxindex == NULL_TREE || maxindex == error_mark_node)
      return error_mark_node;
  
    if (init
        && (from_array == 2
! 	  ? (!CLASS_TYPE_P (type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (type))
  	  : !TYPE_NEEDS_CONSTRUCTING (type))
        && ((TREE_CODE (init) == CONSTRUCTOR
  	   /* Don't do this if the CONSTRUCTOR might contain something
  	      that might throw and require us to clean up.  */
  	   && (CONSTRUCTOR_ELTS (init) == NULL_TREE
! 	       || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (target_type (type))))
  	  || from_array))
      {
        /* Do non-default initialization of POD arrays resulting from
  	 brace-enclosed initializers.  In this case, digest_init and
  	 store_constructor will handle the semantics for us.  */
--- 2404,2424 ----
      maxindex = array_type_nelts (atype);
  
    if (maxindex == NULL_TREE || maxindex == error_mark_node)
      return error_mark_node;
  
+   inner_elt_type = strip_array_types (atype);
    if (init
        && (from_array == 2
! 	  ? (!CLASS_TYPE_P (inner_elt_type) 
! 	     || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
  	  : !TYPE_NEEDS_CONSTRUCTING (type))
        && ((TREE_CODE (init) == CONSTRUCTOR
  	   /* Don't do this if the CONSTRUCTOR might contain something
  	      that might throw and require us to clean up.  */
  	   && (CONSTRUCTOR_ELTS (init) == NULL_TREE
! 	       || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
  	  || from_array))
      {
        /* Do non-default initialization of POD arrays resulting from
  	 brace-enclosed initializers.  In this case, digest_init and
  	 store_constructor will handle the semantics for us.  */
*************** build_vec_init (tree base, tree maxindex
*** 2600,2617 ****
        tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator);
  
        /* Flatten multi-dimensional array since build_vec_delete only
  	 expects one-dimensional array.  */
        if (TREE_CODE (type) == ARRAY_TYPE)
! 	{
! 	  m = cp_build_binary_op (MULT_EXPR, m,
! 				  array_type_nelts_total (type));
! 	  type = strip_array_types (type);
! 	}
  
        finish_cleanup_try_block (try_block);
!       e = build_vec_delete_1 (rval, m, type, sfk_base_destructor,
  			      /*use_global_delete=*/0);
        finish_cleanup (e, try_block);
      }
  
    /* The value of the array initialization is the array itself, RVAL
--- 2605,2620 ----
        tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator);
  
        /* Flatten multi-dimensional array since build_vec_delete only
  	 expects one-dimensional array.  */
        if (TREE_CODE (type) == ARRAY_TYPE)
! 	m = cp_build_binary_op (MULT_EXPR, m,
! 				array_type_nelts_total (type));
  
        finish_cleanup_try_block (try_block);
!       e = build_vec_delete_1 (rval, m, 
! 			      inner_elt_type, sfk_base_destructor,
  			      /*use_global_delete=*/0);
        finish_cleanup (e, try_block);
      }
  
    /* The value of the array initialization is the array itself, RVAL
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.617
diff -c -5 -p -r1.617 typeck.c
*** cp/typeck.c	5 Mar 2005 15:44:20 -0000	1.617
--- cp/typeck.c	9 Mar 2005 07:23:42 -0000
*************** static void casts_away_constness_r (tree
*** 57,82 ****
  static bool casts_away_constness (tree, tree);
  static void maybe_warn_about_returning_address_of_local (tree);
  static tree lookup_destructor (tree, tree, tree);
  static tree convert_arguments (tree, tree, tree, int);
  
- /* Return the target type of TYPE, which means return T for:
-    T*, T&, T[], T (...), and otherwise, just T.  */
- 
- tree
- target_type (tree type)
- {
-   type = non_reference (type);
-   while (TREE_CODE (type) == POINTER_TYPE
- 	 || TREE_CODE (type) == ARRAY_TYPE
- 	 || TREE_CODE (type) == FUNCTION_TYPE
- 	 || TREE_CODE (type) == METHOD_TYPE
- 	 || TYPE_PTRMEM_P (type))
-     type = TREE_TYPE (type);
-   return type;
- }
- 
  /* Do `exp = require_complete_type (exp);' to make sure exp
     does not have an incomplete type.  (That includes void types.)
     Returns the error_mark_node if the VALUE does not have
     complete type when this function returns.  */
  
--- 57,66 ----
Index: testsuite/g++.dg/init/array18.C
===================================================================
RCS file: testsuite/g++.dg/init/array18.C
diff -N testsuite/g++.dg/init/array18.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/array18.C	9 Mar 2005 07:23:42 -0000
***************
*** 0 ****
--- 1,21 ----
+ // PR c++/20142
+ 
+ int n=4;
+ 
+ struct A
+ {
+   A() {}
+   A& operator= (const A&) { --n; return *this; }
+ };
+ 
+ struct B
+ {
+   A x[2][2];
+ };
+ 
+ int main()
+ {
+   B b;
+   b = b;
+   return n;
+ }


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