This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix PR6944
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 08 Jun 2002 21:34:26 +0700
- Subject: [C++ PATCH] Fix PR6944
- Reply-to: lerdsuwa at users dot sourceforge dot net
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();
+ }
+ }