Hi!

As written in the PR, location wrappers are stripped by
cxx_eval_constant_expression as the first thing it does after dealing with
jump_target.  The problem is that when this function is called on a
CONSTRUCTOR, is TREE_CONSTANT and reduced_constant_expression_p (which
allows location wrappers around constants), we don't recurse on the
CONSTRUCTOR elements and so nothing strips them away.  Then when
cxx_eval_component_reference or bit_field_ref we actually can run into those
location wrappers and the callers assume they don't appear anymore.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

I admit I'm not 100% sure about the second case which will call the function
to do the stripping for all the elts until the one found.  The alternative
would be:
       tree bitpos = bit_position (field);
       if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
-       return value;
+       {
+         STRIP_ANY_LOCATION_WRAPPER (value);
+         return value;
+       }
       if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
-         && TREE_CODE (value) == INTEGER_CST
          && tree_fits_shwi_p (bitpos)
          && tree_fits_shwi_p (DECL_SIZE (field)))
        {
          HOST_WIDE_INT bit = tree_to_shwi (bitpos);
          HOST_WIDE_INT sz = tree_to_shwi (DECL_SIZE (field));
          HOST_WIDE_INT shift;
          if (bit >= istart && bit + sz <= istart + isize)
            {
+             STRIP_ANY_LOCATION_WRAPPER (value);
+             if (TREE_CODE (value) != INTEGER_CST)
+               continue;
but then we'd do those tree_fits_shwi_p/tree_to_shwi.  Guess
a micro-optimization without a clear winner.

2019-10-17  Jakub Jelinek  <ja...@redhat.com>

        PR c++/92015
        * constexpr.c (cxx_eval_component_reference, cxx_eval_bit_field_ref):
        Use STRIP_ANY_LOCATION_WRAPPER on CONSTRUCTOR elts.

        * g++.dg/cpp0x/constexpr-92015.C: New test.

--- gcc/cp/constexpr.c.jj       2019-10-16 09:30:57.300112739 +0200
+++ gcc/cp/constexpr.c  2019-10-16 17:06:03.943539476 +0200
@@ -2887,7 +2887,10 @@ cxx_eval_component_reference (const cons
          : field == part)
        {
          if (value)
-           return value;
+           {
+             STRIP_ANY_LOCATION_WRAPPER (value);
+             return value;
+           }
          else
            /* We're in the middle of initializing it.  */
            break;
@@ -2977,6 +2980,7 @@ cxx_eval_bit_field_ref (const constexpr_
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
     {
       tree bitpos = bit_position (field);
+      STRIP_ANY_LOCATION_WRAPPER (value);
       if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
        return value;
       if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
--- gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C.jj     2019-10-16 
17:16:44.204871319 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C        2019-10-16 
17:14:14.773127884 +0200
@@ -0,0 +1,7 @@
+// PR c++/92015
+// { dg-do compile { target c++11 } }
+
+struct S1 { char c[6] {'h', 'e', 'l', 'l', 'o', 0}; };
+struct S2 { char c[6] = "hello"; };
+static_assert (S1{}.c[0] == 'h', "");
+static_assert (S2{}.c[0] == 'h', "");

        Jakub

Reply via email to