@@ -223,6 +223,7 @@ static void write_method_parms (tree, const int, const tree);
static void write_class_enum_type (const tree);
static void write_template_args (tree, tree = NULL_TREE);
static void write_expression (tree);
+static bool literal_p (const tree);
static void write_template_arg_literal (const tree);
static void write_template_arg (tree);
static void write_template_template_arg (const tree);
@@ -3397,8 +3398,7 @@ write_expression (tree expr)
|| code == TEMPLATE_PARM_INDEX)
write_template_param (expr);
/* Handle literals. */
- else if (TREE_CODE_CLASS (code) == tcc_constant
- || code == CONST_DECL)
+ else if (literal_p (expr))
write_template_arg_literal (expr);
else if (code == EXCESS_PRECISION_EXPR
&& TREE_CODE (TREE_OPERAND (expr, 0)) == REAL_CST)
@@ -3946,6 +3946,29 @@ write_expression (tree expr)
}
}
+/* 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)))
+ || null_member_pointer_value_p (t))
+ return true;
+ else
+ switch (TREE_CODE (t))
+ {
+ case CONST_DECL:
+ return literal_p (DECL_INITIAL (t));
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case COMPLEX_CST:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Literal subcase of non-terminal <template-arg>.
"Literal arguments, e.g. "A<42L>", are encoded with their type
@@ -3956,6 +3979,8 @@ write_expression (tree expr)
static void
write_template_arg_literal (const tree value)
{
+ gcc_assert (literal_p (value));
+
if (TREE_CODE (value) == STRING_CST)
/* Temporarily mangle strings as braced initializer lists. */
write_string ("tl");
@@ -4113,9 +4138,7 @@ write_template_arg (tree node)
else if (code == TEMPLATE_DECL)
/* A template appearing as a template arg is a template template arg. */
write_template_template_arg (node);
- else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
- || code == CONST_DECL
- || null_member_pointer_value_p (node))
+ else if (literal_p (node))
write_template_arg_literal (node);
else if (code == EXCESS_PRECISION_EXPR
&& TREE_CODE (TREE_OPERAND (node, 0)) == REAL_CST)
@@ -89,7 +89,7 @@ void k00 (F<D{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z3k001FIXtl1DEEE" } }
void k0x (F<D{{ 0, &AF::f }}>) { }
-// { dg-final { scan-assembler "_Z3k0x1FIXtl1DtlA2_M2AFFvvEtlS3_EtlS3_adL_ZNS1_1fEvEEEEEE" } }
+// { dg-final { scan-assembler "_Z3k0x1FIXtl1DtlA2_M2AFFvvELS3_0EtlS3_adL_ZNS1_1fEvEEEEEE" } }
void kx_ (F<D{{ &AF::f }}>) { }
// { dg-final { scan-assembler "_Z3kx_1FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEEEEE" } }
new file mode 100644
@@ -0,0 +1,13 @@
+// PR c++/116511
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fabi-compat-version=0 }
+template <int> struct s1 {
+ enum { e1 = 1 };
+};
+template <int t2> struct s2 {
+ enum { e1 = s1<t2>::e1 };
+ s2() requires(0 != e1) {}
+};
+
+// { dg-final { scan-assembler "_ZN2s2ILi8EEC1EvQneLi0EL_ZNS_IXT_EEUt_2e1EE" } }
+s2<8> a;