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] Fix PR6944


Hi

This patch fixes problems of synthesized constructor of class
containing multi-dimensional array of another class, for example,
the class 'Array' containing a 3-D array of 'std::string' in
the 'array4.C' testcase below.

There are actually two problems here: the 'array4.C' testcase is a
regression introduced in GCC 3.0.  Synthesized copy constructor
Array::Array(const Array&) fails with the error message:

        sorry, not implemented: cannot initialize multi-dimensional 
        array with initializer

This is due to bad argument to build_vec_init inside build_aggr_init.
The same_type_p returns false because 'init' has no qualifiers but
'exp' has a const qualifier.  This patch fixes the mentioned logic
now that the third argument of build_vec_init should be 0, 1 or 2.

The second problem, array5.C, is about destroying partially initialized
array when an exception is thrown.  This is not a regression.  Only
the constructed objects indexed by the innermost array index is properly
destroyed.  All outer object destructor is not called because 
build_vec_init calls build_vec_delete_1 but build_vec_delete_1 cannot
deal with multi-dimensional arrays.

Bootstrapped and tested with no regressions.  OK to commit
to the main trunk and 3.1 branch?

--Kriang


2002-06-08  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

        PR c++/6944
        * init.c (build_aggr_init): Remove qualifiers of init before calling
        build_vec_init.  Correct the third argument of build_vec_init
        function call.
        (build_vec_init): Flatten multi-dimensional array during cleanup.

2002-06-08  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

        * g++.dg/init/array4.C: New test.
        * g++.dg/init/array5.C: New test.


diff -cprN gcc-main-save/gcc/cp/init.c gcc-main-new/gcc/cp/init.c
*** gcc-main-save/gcc/cp/init.c Wed May 22 20:39:23 2002
--- gcc-main-new/gcc/cp/init.c  Sat Jun  8 18:34:45 2002
*************** build_aggr_init (exp, init, flags)
*** 1161,1174 ****
          return error_mark_node;
        }
        if (cp_type_quals (type) != TYPE_UNQUALIFIED)
!       {
!         TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
!         if (init)
!           TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
!       }
        stmt_expr = build_vec_init (exp, init,
!                                 init && same_type_p (TREE_TYPE (init),
!                                                      TREE_TYPE (exp)));
        TREE_READONLY (exp) = was_const;
        TREE_THIS_VOLATILE (exp) = was_volatile;
        TREE_TYPE (exp) = type;
--- 1161,1172 ----
          return error_mark_node;
        }
        if (cp_type_quals (type) != TYPE_UNQUALIFIED)
!       TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
!       if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
!       TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
        stmt_expr = build_vec_init (exp, init,
!                                 (init && same_type_p (TREE_TYPE (init),
!                                                       TREE_TYPE (exp))) ? 1 : 0);
        TREE_READONLY (exp) = was_const;
        TREE_THIS_VOLATILE (exp) = was_volatile;
        TREE_TYPE (exp) = type;
*************** build_vec_init (base, init, from_array)
*** 3002,3013 ****
        && from_array != 2)
      {
        tree e;
  
        finish_compound_stmt (/*has_no_scope=*/1, try_body);
        finish_cleanup_try_block (try_block);
!       e = build_vec_delete_1 (rval,
!                             cp_build_binary_op (MINUS_EXPR, maxindex, 
!                                                 iterator),
                              type,
                              sfk_base_destructor,
                              /*use_global_delete=*/0);
--- 3000,3019 ----
        && from_array != 2)
      {
        tree e;
+       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_compound_stmt (/*has_no_scope=*/1, try_body);
        finish_cleanup_try_block (try_block);
!       e = build_vec_delete_1 (rval, m,
                              type,
                              sfk_base_destructor,
                              /*use_global_delete=*/0);
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/init/array4.C gcc-main-new/gcc/testsuite/g++.dg/init/array4.C
*** gcc-main-save/gcc/testsuite/g++.dg/init/array4.C    Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/init/array4.C     Sat Jun  8 21:06:10 2002
***************
*** 0 ****
--- 1,27 ----
+ // { dg-do compile }
+ // Origin: Markus Breuer <markus.breuer@materna.de>
+ 
+ // PR c++/6944
+ // Fail to synthesize copy constructor of multi-dimensional
+ // array of class.
+ 
+ #include <string>
+ 
+ class Array
+ {
+ public:
+    std::string m_array[10][20][30];
+ };
+ 
+ Array func()
+ {
+    Array result;
+    return result; // sorry, not implemented: cannot initialize multi-dimensional array with initializer
+ }
+ 
+ 
+ int main()
+ {
+    Array arr = func();
+ }
+ 
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/init/array5.C gcc-main-new/gcc/testsuite/g++.dg/init/array5.C
*** gcc-main-save/gcc/testsuite/g++.dg/init/array5.C    Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/init/array5.C     Sat Jun  8 21:06:37 2002
***************
*** 0 ****
--- 1,52 ----
+ // { dg-do run }
+ // Copyright (C) 2002 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ 
+ // Incorrect construction and destruction of multi-dimensional
+ // array of class.
+ 
+ extern "C" void abort();
+ extern "C" int printf(const char *, ...);
+ 
+ int count;
+ int num;
+ 
+ struct A
+ {
+       A()
+       {
+               if (count == num)
+                       throw "";
+               count++;
+ #ifdef PRINT
+               printf("ctor %p\n", static_cast<void *>(this));
+ #endif
+       }
+ 
+       ~A()
+       {
+               count--;
+ #ifdef PRINT
+               printf("dtor %p\n", static_cast<void *>(this));
+ #endif
+       }
+ };
+ 
+ struct Array
+ {
+       A array[2][2][2];
+ };
+ 
+ int main()
+ {
+       for (num = 0; num <= 8; ++num) {
+               count = 0;
+               try {
+                       Array A;
+               }
+               catch (...) {
+               }
+               if (count != 0)
+                       abort();
+       }
+ }


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