re PR c++/15507 (hang laying out union)
authorMark Mitchell <mark@codesourcery.com>
Sat, 22 May 2004 19:28:31 +0000 (19:28 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 22 May 2004 19:28:31 +0000 (19:28 +0000)
PR c++/15507
* class.c (layout_nonempty_base_or_field): Do not try to avoid
layout conflicts for unions.

PR c++/15542
* typeck.c (build_x_unary_op): Instantiate template class
specializations before looking for "operator &".

PR c++/15427
* typeck.c (complete_type): Layout non-dependent array types, even
in templates.

PR c++/15287
* typeck.c (build_unary_op): Do not optimize "&x[y]" when in a
template.

PR c++/15507
* g++.dg/inherit/union1.C: New test.

PR c++/15542
* g++.dg/template/addr1.C: New test.

PR c++/15427
* g++.dg/template/array5.C: New test.

PR c++/15287
* g++.dg/template/array6.C: New test.

From-SVN: r82144

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/union1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/addr1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/array5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/array6.C [new file with mode: 0644]

index 03cc5a8..063ea63 100644 (file)
@@ -1,3 +1,21 @@
+2004-05-22  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/15507
+       * class.c (layout_nonempty_base_or_field): Do not try to avoid
+       layout conflicts for unions.
+
+       PR c++/15542
+       * typeck.c (build_x_unary_op): Instantiate template class
+       specializations before looking for "operator &".
+
+       PR c++/15427
+       * typeck.c (complete_type): Layout non-dependent array types, even
+       in templates.
+
+       PR c++/15287
+       * typeck.c (build_unary_op): Do not optimize "&x[y]" when in a
+       template.
+
 2004-05-22  Roger Sayle  <roger@eyesopen.com>
 
        * name-lookup.c (check_for_out_of_scope_variable): Avoid ICE by
index 33cbdb6..73828a8 100644 (file)
@@ -3502,14 +3502,14 @@ layout_nonempty_base_or_field (record_layout_info rli,
       /* Place this field.  */
       place_field (rli, decl);
       offset = byte_position (decl);
+
       /* We have to check to see whether or not there is already
         something of the same type at the offset we're about to use.
-        For example:
+        For example, consider:
         
-        struct S {};
-        struct T : public S { int i; };
-        struct U : public S, public T {};
+          struct S {};
+          struct T : public S { int i; };
+          struct U : public S, public T {};
         
         Here, we put S at offset zero in U.  Then, we can't put T at
         offset zero -- its S component would be at the same address
@@ -3518,6 +3518,10 @@ layout_nonempty_base_or_field (record_layout_info rli,
         empty class, have nonzero size, any overlap can happen only
         with a direct or indirect base-class -- it can't happen with
         a data member.  */
+      /* In a union, overlap is permitted; all members are placed at
+        offset zero.  */
+      if (TREE_CODE (rli->t) == UNION_TYPE)
+       break;
       /* G++ 3.2 did not check for overlaps when placing a non-empty
         virtual base.  */
       if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
index 3e9c2cf..603f655 100644 (file)
@@ -127,7 +127,7 @@ complete_type (tree type)
   else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
     {
       tree t = complete_type (TREE_TYPE (type));
-      if (COMPLETE_TYPE_P (t) && ! processing_template_decl)
+      if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))
        layout_type (type);
       TYPE_NEEDS_CONSTRUCTING (type)
        = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
@@ -3527,12 +3527,18 @@ build_x_unary_op (enum tree_code code, tree xarg)
 
   exp = NULL_TREE;
 
-  /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
-     error message.  */
+  /* [expr.unary.op] says:
+
+       The address of an object of incomplete type can be taken.
+
+     (And is just the ordinary address operator, not an overloaded
+     "operator &".)  However, if the type is a template
+     specialization, we must complete the type at this point so that
+     an overloaded "operator &" will be available if required.  */
   if (code == ADDR_EXPR
       && TREE_CODE (xarg) != TEMPLATE_ID_EXPR
-      && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
-          && !COMPLETE_TYPE_P (TREE_TYPE (xarg)))
+      && ((CLASS_TYPE_P (TREE_TYPE (xarg))
+          && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (xarg))))
          || (TREE_CODE (xarg) == OFFSET_REF)))
     /* Don't look for a function.  */;
   else
@@ -3927,8 +3933,12 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          return arg;
        }
 
-      /* For &x[y], return x+y.  */
-      if (TREE_CODE (arg) == ARRAY_REF)
+      /* For &x[y], return x+y.  But, in a template, ARG may be an
+        ARRAY_REF representing a non-dependent expression.  In that
+        case, there may be an overloaded "operator []" that will be
+        chosen at instantiation time; we must not try to optimize
+        here.  */
+      if (TREE_CODE (arg) == ARRAY_REF && !processing_template_decl)
        {
          if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
            return error_mark_node;
index 13b309c..2d7c928 100644 (file)
@@ -1,3 +1,17 @@
+2004-05-22  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/15507
+       * g++.dg/inherit/union1.C: New test.
+
+       PR c++/15542
+       * g++.dg/template/addr1.C: New test.
+
+       PR c++/15427
+       * g++.dg/template/array5.C: New test.
+
+       PR c++/15287
+       * g++.dg/template/array6.C: New test.
+
 2004-05-22  Wolfgang Bangerth  <bangerth@dealii.org>
            Roger Sayle  <roger@eyesopen.com>
 
diff --git a/gcc/testsuite/g++.dg/inherit/union1.C b/gcc/testsuite/g++.dg/inherit/union1.C
new file mode 100644 (file)
index 0000000..da46096
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/15507
+
+struct A {
+  // empty
+};
+
+struct B : A {
+  int b;
+};
+
+union U {
+  A a;
+  B b;
+};
diff --git a/gcc/testsuite/g++.dg/template/addr1.C b/gcc/testsuite/g++.dg/template/addr1.C
new file mode 100644 (file)
index 0000000..dd5e387
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/15542
+
+template <typename> struct S_T { 
+  const char** operator & (); 
+}; 
+template <class T> void foo(T **) {} 
+template <typename> void templateTest() { 
+  S_T<const char> s_t; 
+  foo(&s_t); 
+} 
diff --git a/gcc/testsuite/g++.dg/template/array5.C b/gcc/testsuite/g++.dg/template/array5.C
new file mode 100644 (file)
index 0000000..a543580
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/15427
+
+template<class T>
+struct A
+{
+  T foo;
+};
+
+template<class T>
+struct B
+{
+  A<int> _squares[2];
+};
+
diff --git a/gcc/testsuite/g++.dg/template/array6.C b/gcc/testsuite/g++.dg/template/array6.C
new file mode 100644 (file)
index 0000000..0dc5161
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/15287
+
+struct S {}; 
+struct Array { 
+  S operator[](int); 
+} array; 
+void (S::*mem_fun_ptr)(); 
+template <int> void foo() { 
+  (array[0].*mem_fun_ptr)(); 
+}