]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/70393 (Miscompilation: missing constructor call for static object)
authorNathan Sidwell <nathan@acm.org>
Thu, 31 Mar 2016 15:30:33 +0000 (15:30 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 31 Mar 2016 15:30:33 +0000 (15:30 +0000)
PR c++/70393
* varasm.c (output_constructor_regular_field): Flush bitfield
earlier.  Assert we don't want to move backwards.

cp/
* constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR
elements in field order.

testsuite/
* g++.dg/cpp0x/constexpr-virtual6.C: New.

From-SVN: r234636

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C [new file with mode: 0644]
gcc/varasm.c

index 5a9b321582232ccffbebcc8ed0c55a3d31b870e7..c58b659b190ba89059e9ab4234bbde59aed2da2f 100644 (file)
@@ -1,3 +1,9 @@
+2016-03-31  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/70393
+       * varasm.c (output_constructor_regular_field): Flush bitfield
+       earlier.  Assert we don't want to move backwards.
+
 2016-03-31  Kirill Yukhin  <kirill.yukhin@intel.com>
 
        PR target/70453
index 8aad906fc127ac4c9d0f0326462dbefdaf0ec7d6..4a6dc51253301649785c22fa2d37404c7de93241 100644 (file)
@@ -1,3 +1,9 @@
+2016-03-31  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/70393
+       * constexpr.c (cxx_eval_store_expression): Keep CONSTRUCTOR
+       elements in field order.
+
 2016-03-31  Marek Polacek  <polacek@redhat.com>
 
        PR c/70297
index 8ea71113d9991ec10e41187749dcf5c2561ee350..ea605dc641b43192bf731216cd37598b41a0869a 100644 (file)
@@ -2959,16 +2959,39 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       else
        {
          gcc_assert (TREE_CODE (index) == FIELD_DECL);
-         for (unsigned HOST_WIDE_INT idx = 0;
+
+         /* We must keep the CONSTRUCTOR's ELTS in FIELD order.
+            Usually we meet initializers in that order, but it is
+            possible for base types to be placed not in program
+            order.  */
+         tree fields = TYPE_FIELDS (DECL_CONTEXT (index));
+         unsigned HOST_WIDE_INT idx;
+
+         for (idx = 0;
               vec_safe_iterate (CONSTRUCTOR_ELTS (*valp), idx, &cep);
-              idx++)
-           if (index == cep->index)
-             break;
-         if (!cep)
+              idx++, fields = DECL_CHAIN (fields))
            {
-             constructor_elt ce = { index, NULL_TREE };
-             cep = vec_safe_push (CONSTRUCTOR_ELTS (*valp), ce);
+             if (index == cep->index)
+               goto found;
+
+             /* The field we're initializing must be on the field
+                list.  Look to see if it is present before the
+                field the current ELT initializes.  */
+             for (; fields != cep->index; fields = DECL_CHAIN (fields))
+               if (index == fields)
+                 goto insert;
            }
+
+         /* We fell off the end of the CONSTRUCTOR, so insert a new
+            entry at the end.  */
+       insert:
+         {
+           constructor_elt ce = { index, NULL_TREE };
+
+           vec_safe_insert (CONSTRUCTOR_ELTS (*valp), idx, ce);
+           cep = CONSTRUCTOR_ELT (*valp, idx);
+         }
+       found:;
        }
       valp = &cep->value;
     }
index 4cab39478b7ad5b0454462c0da647e44efb3da89..f977fc82992d6a855c5395a75cfd3b890f95963f 100644 (file)
@@ -1,3 +1,8 @@
+2016-03-31  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/70393
+       * g++.dg/cpp0x/constexpr-virtual6.C: New.
+
 2016-03-31  Kirill Yukhin  <kirill.yukhin@intel.com>
 
        PR target/70453
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual6.C
new file mode 100644 (file)
index 0000000..f5abf2c
--- /dev/null
@@ -0,0 +1,49 @@
+// PR c++/70393
+// { dg-do run { target c++11 } }
+
+/* 'ab' has a static initializer, but we flubbed the initializer,
+   because of B being the primary base.  */
+
+struct A
+{
+  int a = 1;
+};
+
+struct B
+{
+  B *element = (B*)2;
+
+    virtual int vfunc() = 0;
+
+    int call_element()
+    {
+      return element->vfunc();
+    }
+
+    void set_element()
+    {
+      element = this;
+    }
+};
+
+struct AB : public A, public B
+{
+    int vfunc()
+    {
+      return 0;
+    }
+};
+
+static AB ab;
+
+int main()
+{
+  if (ab.a != 1)
+    return 1;
+  if (ab.element != (void*)2)
+    return 2;
+  
+  ab.set_element();
+  return ab.call_element();
+}
+
index 3a3573e53951d5aacad7a93abb1b435fb534a7dc..b0f2af03de492b1499ab52a73a49d2ec33920045 100644 (file)
@@ -4929,6 +4929,14 @@ output_constructor_regular_field (oc_local_state *local)
 
   unsigned int align2;
 
+  /* Output any buffered-up bit-fields preceding this element.  */
+  if (local->byte_buffer_in_use)
+    {
+      assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+      local->total_bytes++;
+      local->byte_buffer_in_use = false;
+    }
+
   if (local->index != NULL_TREE)
     {
       /* Perform the index calculation in modulo arithmetic but
@@ -4945,22 +4953,19 @@ output_constructor_regular_field (oc_local_state *local)
   else
     fieldpos = 0;
 
-  /* Output any buffered-up bit-fields preceding this element.  */
-  if (local->byte_buffer_in_use)
-    {
-      assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
-      local->total_bytes++;
-      local->byte_buffer_in_use = false;
-    }
-
   /* Advance to offset of this element.
      Note no alignment needed in an array, since that is guaranteed
      if each element has the proper size.  */
-  if ((local->field != NULL_TREE || local->index != NULL_TREE)
-      && fieldpos > local->total_bytes)
+  if (local->field != NULL_TREE || local->index != NULL_TREE)
     {
-      assemble_zeros (fieldpos - local->total_bytes);
-      local->total_bytes = fieldpos;
+      if (fieldpos > local->total_bytes)
+       {
+         assemble_zeros (fieldpos - local->total_bytes);
+         local->total_bytes = fieldpos;
+       }
+      else
+       /* Must not go backwards.  */
+       gcc_assert (fieldpos == local->total_bytes);
     }
 
   /* Find the alignment of this element.  */