On 9/6/24 7:15 AM, Simon Martin wrote:
We ICE upon the following *valid* code when mangling the requires
clause
=== cut here ===
template <int> struct s1 {
enum { e1 = 1 };
};
template <int t2> struct s2 {
enum { e1 = s1<t2>::e1 };
s2() requires(0 != e1) {}
};
s2<8> a;
=== cut here ===
The problem is that the mangler wrongly assumes that the DECL_INITIAL of
a CONST_DECL is always an INTEGER_CST, and blindly passes it to
write_integer_cst.
I assume we should be able to actually compute the value of e1 and use
it when mangling, however from my investigation, it seems to be a pretty
involved change.
What's clear however is that we should not try to write a non-literal as
a literal. This patch adds a utility function to determine whether a
tree is a literal as per the definition in the ABI, and uses it to only
call write_template_arg_literal when we actually have a literal in hand.
Note that I had to change the expectation of an existing test, that was
expecting "[...]void (AF::*)(){}[...]" and now gets an equivalent
"[...](void (AF::*)())0[...]" (and FWIW is what clang and icx give; see
https://godbolt.org/z/hnjdeKEhW).
Unfortunately we need to provide backward bug compatibility for
-fabi-version=14, so this change needs to check abi_version_at_least (15).
+/* Determine whether T is a literal per section 5.1.6.1 of the CXX ABI. */
+
+static bool
+literal_p (const tree t)
+{
+ if ((TREE_TYPE (t) && NULLPTR_TYPE_P (TREE_TYPE (t)))
This looks wrong; a random expression with type nullptr_t is not a
literal, and can be instantiation-dependent. And I don't see any test
of mangling such a thing.
Jason