The following patch fixes the remaining problems in the C++ front-end to
bring the pragma simd implementation on equal footing with the C FE.
Herein lie some small changes to the code parsing the initialization
statement in the for loop, as well as the condition. I also separated
out the "for2.c" test, since both frontends were sufficiently different
to warrant different tests.
The remaining Cilk Plus failure (for both C and C++) is
c-c++-common/cilk-plus/PS/for5.c, which I'm still investigating how to fix.
Pushed to branch.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c93ea9e..d68bdf7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30236,6 +30236,17 @@ cp_parser_simd_for_init_statement (cp_parser *parser,
tree *init,
error_at (loc, "expected iteration declaration");
return error_mark_node;
}
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_REGISTER)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_EXTERN)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_THREAD))
+ {
+ error_at (loc, "storage class is not allowed");
+ cp_lexer_consume_token (parser->lexer);
+ }
+
cp_parser_parse_tentatively (parser);
cp_parser_type_specifier_seq (parser, true, false, &type_specifiers);
if (cp_parser_parse_definitely (parser))
@@ -30332,7 +30343,8 @@ cp_parser_simd_for_init_statement (cp_parser *parser,
tree *init,
}
else
{
- decl = NULL_TREE;
+ if (decl != error_mark_node)
+ decl = NULL;
cp_parser_abort_tentative_parse (parser);
*init = cp_parser_expression (parser, false, NULL);
}
@@ -30379,6 +30391,7 @@ cp_parser_cilk_for (cp_parser *parser, enum rid
for_keyword, tree clauses)
return error_mark_node;
}
+ /* Parse initialization. */
if (for_keyword == RID_FOR)
decl = cp_parser_simd_for_init_statement (parser, &init, &pre_body);
@@ -30410,6 +30423,13 @@ cp_parser_cilk_for (cp_parser *parser, enum rid
for_keyword, tree clauses)
valid = false;
}
+ if (!valid)
+ {
+ /* Skip to the semicolon ending the init. */
+ cp_parser_skip_to_end_of_statement (parser);
+ }
+
+ /* Parse condition. */
if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
return error_mark_node;
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -30426,7 +30446,8 @@ cp_parser_cilk_for (cp_parser *parser, enum rid
for_keyword, tree clauses)
if (cond == error_mark_node)
valid = false;
cp_parser_consume_semicolon_at_end_of_statement (parser);
-
+
+ /* Parse increment. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
{
error_at (loc, "missing increment");
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 16e2472..f8c5d82 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6058,7 +6058,7 @@ finish_omp_cancellation_point (tree clauses)
tree
finish_cilk_for_cond (tree cond)
{
- return maybe_convert_cond (cond);
+ return cp_truthvalue_conversion (cond);
}
/* Begin a __transaction_atomic or __transaction_relaxed statement.
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
index 5ecefd5..fe8b630 100644
--- a/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/body.c
@@ -12,7 +12,7 @@ void foo()
for (int i=0; i < 1000; ++i)
{
if (c == 5)
- return; /* { dg-error "return statments are not allowed" } */
+ return; /* { dg-error "\(return statments are not allowed\|invalid
exit\)" } */
if (c == 6)
__builtin_setjmp (jmpbuf); /* { dg-error "calls to setjmp are not
allowed" } */
a[i] = b[i];
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
b/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
deleted file mode 100644
index dc0a41e..0000000
--- a/gcc/testsuite/c-c++-common/cilk-plus/PS/for2.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O3 -fcilkplus" } */
-
-// Test storage classes in the initialization of a <#pragma simd> for
-// loop.
-
-int *a, *b;
-
-void foo()
-{
-#pragma simd
- for (static int foo=5; foo < 10; ++foo)
- a[foo] = b[foo];
- /* { dg-error "declaration of static variable" "storage class1" { target
*-*-* } 12 } */
- /* { dg-error "induction variable cannot be static" "storage class2" {
target *-*-* } 12 } */
-
- static int bar;
-#pragma simd
- for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be
static" } */
- a[bar] = bar;
-
-#pragma simd
- for (extern int var=0; var < 1000; ++var)
- a[var] = var;
- /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* }
23 } */
- /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */
- /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 }
*/
-
- extern int extvar;
-#pragma simd
- for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable
cannot be extern" } */
- b[extvar] = a[extvar];
-
- // This seems like it should be ok.
- // Must check with standards people.
-#pragma simd
- for (auto int autoi = 0; autoi < 1000; ++autoi)
- b[autoi] = a[autoi] * 2;
- // Similarly here.
- auto int autoj;
-#pragma simd
- for (auto int autoj = 0; autoj < 1000; ++autoj)
- b[autoj] = a[autoj] * 2;
-
- register int regi;
-#pragma simd
- for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot
be declared register" } */
- b[regi] = a[regi] * 2;
-
-#pragma simd
- for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction
variable cannot be declared register" } */
- b[regj] = a[regj] * 2;
-
- volatile int vi;
-#pragma simd
- for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be
volatile" } */
- a[vi] = b[vi];
-
-#pragma simd
- for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable
cannot be volatile" } */
- a[vj] = b[vj];
-
-#pragma simd
- for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only
var" } */
- a[ci] = b[ci];
-}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for2.C
b/gcc/testsuite/g++.dg/cilk-plus/for2.C
new file mode 100644
index 0000000..d30e057
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/for2.C
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+// Test storage classes in the initialization of a <#pragma simd> for
+// loop.
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+ for (static int tt=5; tt < 10; ++tt) /* { dg-error "storage class is not
allowed" } */
+ a[tt] = b[tt];
+
+#pragma simd
+ for (extern int var=0; var < 1000; ++var) /* { dg-error "storage class is
not allowed" } */
+ a[var] = var;
+
+#pragma simd
+ for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "storage
class is not allowed" } */
+ b[regj] = a[regj] * 2;
+
+#pragma simd
+ for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable
cannot be volatile" } */
+ a[vj] = b[vj];
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/for2.c
b/gcc/testsuite/gcc.dg/cilk-plus/for2.c
new file mode 100644
index 0000000..dc0a41e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/for2.c
@@ -0,0 +1,66 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+// Test storage classes in the initialization of a <#pragma simd> for
+// loop.
+
+int *a, *b;
+
+void foo()
+{
+#pragma simd
+ for (static int foo=5; foo < 10; ++foo)
+ a[foo] = b[foo];
+ /* { dg-error "declaration of static variable" "storage class1" { target
*-*-* } 12 } */
+ /* { dg-error "induction variable cannot be static" "storage class2" {
target *-*-* } 12 } */
+
+ static int bar;
+#pragma simd
+ for (bar=0; bar < 1000; ++bar) /* { dg-error "induction variable cannot be
static" } */
+ a[bar] = bar;
+
+#pragma simd
+ for (extern int var=0; var < 1000; ++var)
+ a[var] = var;
+ /* { dg-error "has both 'extern' and initializer" "extern" { target *-*-* }
23 } */
+ /* { dg-error "declaration of static variable" "" { target *-*-* } 23 } */
+ /* { dg-error "induction variable cannot be static" "" { target *-*-* } 23 }
*/
+
+ extern int extvar;
+#pragma simd
+ for (extvar = 0; extvar < 1000; ++extvar) /* { dg-error "induction variable
cannot be extern" } */
+ b[extvar] = a[extvar];
+
+ // This seems like it should be ok.
+ // Must check with standards people.
+#pragma simd
+ for (auto int autoi = 0; autoi < 1000; ++autoi)
+ b[autoi] = a[autoi] * 2;
+ // Similarly here.
+ auto int autoj;
+#pragma simd
+ for (auto int autoj = 0; autoj < 1000; ++autoj)
+ b[autoj] = a[autoj] * 2;
+
+ register int regi;
+#pragma simd
+ for (regi = 0; regi < 1000; ++regi) /* { dg-error "induction variable cannot
be declared register" } */
+ b[regi] = a[regi] * 2;
+
+#pragma simd
+ for (register int regj = 0; regj < 1000; ++regj) /* { dg-error "induction
variable cannot be declared register" } */
+ b[regj] = a[regj] * 2;
+
+ volatile int vi;
+#pragma simd
+ for (vi=0; vi<1000; ++vi) /* { dg-error "induction variable cannot be
volatile" } */
+ a[vi] = b[vi];
+
+#pragma simd
+ for (volatile int vj=0; vj<1000; ++vj) /* { dg-error "induction variable
cannot be volatile" } */
+ a[vj] = b[vj];
+
+#pragma simd
+ for (const int ci=0; ci<1000; ++ci) /* { dg-error "increment of read-only
var" } */
+ a[ci] = b[ci];
+}