On 9/30/21 12:52, Patrick Palka wrote:
When parsing a variadic trait expression, we build up the list of
trailing arguments in reverse, but we're neglecting to reverse the list
to its true order afterwards.  This causes us to confuse the meaning of
e.g. __is_xible(x, y, z) and __is_xible(x, z, y).

Note that bug isn't exposed in the standard type traits within libstdc++
because there we pass a pack expansion as the single trailing argument
to __is_xible, which indeed gets expanded correctly by tsubst_tree_list.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  What about backports?  This isn't a regression AFAICT.

OK for trunk. I wouldn't bother backporting, since it doesn't affect the library traits.

gcc/cp/ChangeLog:

        * parser.c (cp_parser_trait_expr): Call nreverse on the list of
        trailing arguments.

gcc/testsuite/ChangeLog:

        * g++.dg/ext/is_constructible6.C: New test.
---
  gcc/cp/parser.c                              |  1 +
  gcc/testsuite/g++.dg/ext/is_constructible6.C | 10 ++++++++++
  2 files changed, 11 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_constructible6.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8430445ef8c..04f5a24cc03 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10832,6 +10832,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid 
keyword)
            return error_mark_node;
          type2 = tree_cons (NULL_TREE, elt, type2);
        }
+      type2 = nreverse (type2);
      }
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible6.C 
b/gcc/testsuite/g++.dg/ext/is_constructible6.C
new file mode 100644
index 00000000000..7fce153fa75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible6.C
@@ -0,0 +1,10 @@
+// Verify we respect the order of trailing arguments passed to
+// __is_constructible.
+
+struct A { };
+struct B { };
+struct C { C(A, B); };
+
+extern int n[true];
+extern int n[ __is_constructible(C, A, B)];
+extern int n[!__is_constructible(C, B, A)];


Reply via email to