]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: #pragma GCC unroll C++ fixes [PR112795]
authorJakub Jelinek <jakub@redhat.com>
Mon, 4 Dec 2023 07:59:15 +0000 (08:59 +0100)
committerJakub Jelinek <jakub@redhat.com>
Sun, 17 Dec 2023 13:54:43 +0000 (14:54 +0100)
foo in the unroll-5.C testcase ICEs because cp_parser_pragma_unroll
during parsing calls maybe_constant_value unconditionally, which is
fine if !processing_template_decl, but can ICE otherwise.

While just calling fold_non_dependent_expr there instead could be enough
to fix the ICE (and I guess the right thing to do for backports if any),
I don't see a reason why we couldn't handle a dependent #pragma GCC unroll
argument as well, the unrolling isn't done in the FE and all the middle-end
cares about is that ANNOTATE_EXPR has a 1..65534 last operand when it is
annot_expr_unroll_kind.

So, the following patch changes all the unsigned short unroll arguments
to tree unroll (and thus avoids the tree -> unsigned short -> tree
conversions), does the type and value checking during parsing only if
the argument isn't dependent and repeats it during instantiation.

2023-12-04  Jakub Jelinek  <jakub@redhat.com>

PR c++/112795
gcc/cp/
* parser.c (cp_parser_pragma_unroll): Use fold_non_dependent_expr
instead of maybe_constant_value.
gcc/testsuite/
* g++.dg/ext/unroll-5.C: New test.

(cherry picked from commit b6c78feea08c36e5754818c6a3d7536b3f8913dc)

gcc/cp/parser.c
gcc/testsuite/g++.dg/ext/unroll-5.C [new file with mode: 0644]

index 8df715596eba71e512e1f5137cb63ec547ed7e2a..0619b834cf46880a8bb9c426d0e934e5a392e0a4 100644 (file)
@@ -44968,7 +44968,7 @@ cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok)
   location_t location = cp_lexer_peek_token (parser->lexer)->location;
   tree expr = cp_parser_constant_expression (parser);
   unsigned short unroll;
-  expr = maybe_constant_value (expr);
+  expr = fold_non_dependent_expr (expr);
   HOST_WIDE_INT lunroll = 0;
   if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
       || TREE_CODE (expr) != INTEGER_CST
diff --git a/gcc/testsuite/g++.dg/ext/unroll-5.C b/gcc/testsuite/g++.dg/ext/unroll-5.C
new file mode 100644 (file)
index 0000000..f0bc51b
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/112795
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fdump-tree-cunrolli-details" }
+
+void baz (int);
+constexpr int n = 3;
+
+template <int N>
+void
+foo ()
+{
+#pragma GCC unroll(n)
+  for (int i = 0; i != n; ++i)
+    baz (i);
+}
+
+void
+qux ()
+{
+  foo <2> ();
+}
+
+// { dg-final { scan-tree-dump "loop with 3 iterations completely unrolled" "cunrolli" } }