https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91529

            Bug ID: 91529
           Summary: -fmerge-all-constants leads to corrupt output without
                    inlining
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: fiesh at zefix dot tv
  Target Milestone: ---

(Filed this as C++ but don't think that's the right component.)

The following code compiles to a program that behaves as follows:

* Compiled with "g++ -std=c++17 -fmerge-all-constants": segfault
* Compiled with "g++ -std=c++17 -fmerge-all-constants -O1 -fno-inline":
segfault
* Compiled with "g++ -std=c++17 -fmerge-all-constants -O1": success
* Compiled with "g++ -std=c++17": success

It seems that for gcc-7, the program always succeeds, but for gcc-8, gcc-9, and
trunk, this behavior shows up.  It was reduced from what I believe is valid
code using std::variant.

template <unsigned long>
struct e
{
};
template <long f>
e<f> h;
template <typename...>
class ad;
long bi;
struct i
{
        static constexpr bool bm = 0;
};
template <typename...>
union ap {
};
template <typename ag, typename... ah>
union ap<ag, ah...> {
        constexpr ap(e<0>) : aq() {}
        template <unsigned long af>
        constexpr ap(e<af>) : bt(h<af - 1>)
        {
        }
        ag aq;
        ap<ah...> bt;
};
template <bool, typename...>
struct as;
template <typename... bv>
struct as<false, bv...>
{
        template <unsigned long af>
        constexpr as(e<af>) : av(h<af>), aw(af)
        {
        }
        void j() { aw = bi; }
        ~as() { j(); }
        ap<bv...> av;
        int aw;
};
template <typename... bv>
using az = as<i::bm, bv...>;
template <int, typename... bv>
struct k : az<bv...>
{
        using bb = az<bv...>;
        bb::bb;
};
template <typename... bv>
using ce = k<0, bv...>;
template <int, typename... bv>
struct m : ce<bv...>
{
        using bb = ce<bv...>;
        bb::bb;
};
template <typename... bv>
using be = m<0, bv...>;
template <int, typename... bv>
struct p : be<bv...>
{
        using bb = be<bv...>;
        bb::bb;
};
template <typename... bv>
using bg = p<0, bv...>;
template <int, typename... bv>
struct q : bg<bv...>
{
        using bb = bg<bv...>;
        bb::bb;
};
template <typename... bv>
using ck = q<0, bv...>;
template <typename... bv>
struct r : ck<bv...>
{
        using bb = ck<bv...>;
        template <unsigned long af>
        constexpr r(e<af> s) : bb(s)
        {
        }
};
template <typename, typename>
struct l;
template <typename g, typename... bv>
struct l<g, ad<bv...>>
{
        static constexpr long c = 1;
};
template <typename... bv>
class ad : r<bv...>
{
        using bb = r<bv...>;
        template <typename g>
        static constexpr long l = l<g, ad>::c;

public:
        template <typename g>
        constexpr ad(g) : ad(h<l<g>>)
        {
        }
        template <unsigned long af>
        constexpr ad(e<af>) : bb(h<af>)
        {
        }
};
template <int>
struct n
{
        double d = 1.;
};
using ch = ad<int, n<1>>;
main()
{
        ch const o{n<0>()};
}

Reply via email to