On 1/17/25 3:08 PM, Jakub Jelinek wrote:
Hi!

This is the first bug discovered today with the
https://gcc.gnu.org/pipermail/gcc-patches/2025-January/673945.html
hack but then turned into proper testcases where embed-21.C FAILed
since introduction of optimized #embed support and the other when
optimizing large C++ initializers using RAW_DATA_CST.

The problem is that the C++ FE calls make_tree_vector_from_ctor
and uses that as arguments vector for deduction guide handling.
The call.cc code isn't prepared to handle RAW_DATA_CST just about
everywhere, so I think it is safer to make sure RAW_DATA_CST only
appears in CONSTRUCTOR_ELTS and nowhere else.
Thus, the following patch expands the RAW_DATA_CSTs from initializers
into multiple INTEGER_CSTs in the returned vector.

Bootstrapped on x86_64-linux and i686-linux, regtests pending, ok
for trunk if it passes?

2025-01-17  Jakub Jelinek  <ja...@redhat.com>

        PR c++/118528
        * c-common.cc (make_tree_vector_from_ctor): Expand RAW_DATA_CST
        elements from the CONSTRUCTOR to individual INTEGER_CSTs.

        * g++.dg/cpp/embed-21.C: New test.
        * g++.dg/cpp2a/class-deduction-aggr16.C: New test.

--- gcc/c-family/c-common.cc.jj 2025-01-02 11:47:29.803228077 +0100
+++ gcc/c-family/c-common.cc    2025-01-17 13:32:53.512294482 +0100
@@ -9016,9 +9016,26 @@ vec<tree, va_gc> *
  make_tree_vector_from_ctor (tree ctor)
  {
    vec<tree,va_gc> *ret = make_tree_vector ();
+  unsigned nelts = CONSTRUCTOR_NELTS (ctor);
    vec_safe_reserve (ret, CONSTRUCTOR_NELTS (ctor));
    for (unsigned i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
-    ret->quick_push (CONSTRUCTOR_ELT (ctor, i)->value);
+    if (TREE_CODE (CONSTRUCTOR_ELT (ctor, i)->value) == RAW_DATA_CST)
+      {
+       tree raw_data = CONSTRUCTOR_ELT (ctor, i)->value;
+       nelts += RAW_DATA_LENGTH (raw_data);
+       vec_safe_reserve (ret, nelts);

I notice that the second argument to vec_safe_reserve is the number of empty spaces to provide, rather than the new desired capacity. So this will allocate space for an additional copy of the whole constructor.

I guess you want to say reserve (ret, nelts - vec_safe_length (res))? It's weird that there isn't a more convenient way to express that.

Note that this behavior differs from the C++ standard library, where reserve indeed specifies the new capacity. This seems likely to cause a lot of confusion (and over-allocation) going forward. And indeed looking through exising uses turns up at least two that seem to assume the standard library semantics (as well as others that assume the actual semantics).

I wonder about renaming the existing reserve to reserve_space and adding a reserve_capacity?

Jason

Reply via email to