Open tomilov opened 8 years ago
A similar case where neither a template version nor a non-template version gives an error:
struct A {
union {
int j;
};
constexpr A() {}
};
constexpr A a;
int fn1() {
return a.j;
}
class B {};
template <class> struct C {
union {
int j;
};
constexpr C() {}
};
constexpr C<B> c;
int fn2() {
return c.j;
}
Here the generated code for both fn1
and fn2
returns undef. We do get a warning though on the non-template version (unless using -std=c++20
):
tmp.cpp:5:13: warning: constexpr constructor that does not initialize all members is a C++20 extension [-Wc++20-extensions]
constexpr A() {}
^
tmp.cpp:2:3: note: member not initialized by constructor
union {
^
It's http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1331r2.pdf that defines that extension, but there (in the section "Avoiding undefined behaviour") it says that we should be emitting an error on the use of the uninitialized value.
With current trunk the above example gives the error
tmp.cpp:17:15: error: static_assert expression is not an integral constant expression
static_assert(test(), "!");
^~~~~~
tmp.cpp:14:11: note: read of uninitialized object is not allowed in a constant expression
return (v.d.a.i == 0);
^
tmp.cpp:17:15: note: in call to 'test()'
static_assert(test(), "!");
^
though there are still differences compared to a non-template version, in that in a non-template version the error is on the definition of the class, whereas for a template version we get an error only on some kinds of use. If we look at
struct A { int i; };
template< typename type >
struct C1 { constexpr C1() = default; type a; };
struct V1 { V1() = default; C1<A> d; };
int test1()
{
V1 v;
return v.d.a.i;
}
struct C2 { constexpr C2() = default; A a; };
struct V2 { V2() = default; C2 d; };
int test2()
{
V2 v;
return v.d.a.i;
}
the definition of the non-template C2
gets an error:
tmp.cpp:13:13: error: defaulted definition of default constructor is not constexpr
struct C2 { constexpr C2() = default; A a; };
^
but there's no such error for the templated C1
. If we compile just the first half of this example there are no errors and the result is a function that returns undef (at -O1
).
Extended Description
Given a code:
It compiles without errors by
clang
. Compilation byg++
failed with error:If I remove
template
s and substituteA
directly, thenclang
sees uninitialized during default construction variables. If I removeconstexpr
specifier ofC::C()
default constructor, thenclang
also sees wrong things.