On Mon, Mar 21, 2016 at 15:58:18 +0100, Jakub Jelinek wrote:
> On Mon, Mar 21, 2016 at 05:45:52PM +0300, Ilya Verbin wrote:
> > www.cilkplus.org/sites/default/files/open_specifications/Intel_Cilk_plus_lang_spec_1.2.htm
> > says:
> >   In C++, the control variable shall be declared and initialized within the
> >   initialization clause of the _Cilk_for loop. The variable shall have 
> > automatic
> >   storage duration. The variable shall be initialized. Initialization may be
> >   explicit, using assignment or constructor syntax, or implicit via a 
> > nontrivial
> >   default constructor.
> > 
> > This patch enables constructor-syntax initialization.
> > Bootstraped and regtested on x86_64-linux.  OK for stage1?
> 
> Does this affect just _Cilk_for or also #pragma simd?

It affects both.

> What about (some_class i { 0 }; some_class < ...; some_class++)
> and similar syntax?

It's allowed, thanks, I missed this in the initial patch.

> The testsuite coverage is insufficient (nothing e.g.
> tests templates or #pragma simd).

Patch is updated.  Is it sufficient now?


gcc/cp/
        * parser.c (cp_parser_omp_for_loop_init): Allow constructor syntax in
        Cilk Plus for-loop initialization.
gcc/testsuite/
        * g++.dg/cilk-plus/CK/for2.cc: New test.
        * g++.dg/cilk-plus/for5.C: New test.


diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cd09de6..e481c0c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -33284,62 +33284,74 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
 
       if (declarator == cp_error_declarator) 
        cp_parser_skip_to_end_of_statement (parser);
-
       else 
        {
          tree pushed_scope, auto_node;
+         bool is_cilk, is_class, next_is_semicol, next_is_eq, next_is_op_paren,
+              next_is_op_brace;
 
          decl = start_decl (declarator, &type_specifiers,
                             SD_INITIALIZED, attributes,
                             /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
 
+         is_class = CLASS_TYPE_P (TREE_TYPE (decl));
          auto_node = type_uses_auto (TREE_TYPE (decl));
-         if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+         is_cilk = code == CILK_SIMD || code == CILK_FOR;
+         next_is_semicol
+           = cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON);
+         next_is_op_paren
+           = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN);
+         next_is_op_brace
+           = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE);
+         next_is_eq = cp_lexer_next_token_is (parser->lexer, CPP_EQ);
+
+         if (!is_cilk && next_is_op_paren)
            {
-             if (cp_lexer_next_token_is (parser->lexer, 
-                                         CPP_OPEN_PAREN))
-               {
-                 if (code != CILK_SIMD && code != CILK_FOR)
-                   error ("parenthesized initialization is not allowed in "
-                          "OpenMP %<for%> loop");
-                 else
-                   error ("parenthesized initialization is "
-                          "not allowed in for-loop");
-               }
-             else
-               /* Trigger an error.  */
-               cp_parser_require (parser, CPP_EQ, RT_EQ);
-
+             error ("parenthesized initialization is not allowed in "
+                    "OpenMP %<for%> loop");
              init = error_mark_node;
              cp_parser_skip_to_end_of_statement (parser);
            }
-         else if (CLASS_TYPE_P (TREE_TYPE (decl))
-                  || type_dependent_expression_p (decl)
-                  || auto_node)
+         else if (!is_cilk && !next_is_eq)
+           {
+             /* Trigger an error.  */
+             cp_parser_require (parser, CPP_EQ, RT_EQ);
+             init = error_mark_node;
+             cp_parser_skip_to_end_of_statement (parser);
+           }
+         else if (is_cilk && !(next_is_eq || next_is_op_paren
+                               || next_is_op_brace || next_is_semicol))
+           {
+             cp_parser_error (parser, "expected %<=%>, %<(%>, %<{%> or %<;%>");
+             init = error_mark_node;
+             cp_parser_skip_to_end_of_statement (parser);
+           }
+         else if (is_class || type_dependent_expression_p (decl) || auto_node)
            {
              bool is_direct_init, is_non_constant_init;
 
-             init = cp_parser_initializer (parser,
-                                           &is_direct_init,
-                                           &is_non_constant_init);
-
+             if (is_cilk && next_is_semicol)
+               init = NULL_TREE;
+             else
+               init = cp_parser_initializer (parser,
+                                             &is_direct_init,
+                                             &is_non_constant_init);
              if (auto_node)
                {
                  TREE_TYPE (decl)
                    = do_auto_deduction (TREE_TYPE (decl), init,
                                         auto_node);
 
-                 if (!CLASS_TYPE_P (TREE_TYPE (decl))
-                     && !type_dependent_expression_p (decl))
+                 if (!is_class && !type_dependent_expression_p (decl))
                    goto non_class;
                }
-                     
+
              cp_finish_decl (decl, init, !is_non_constant_init,
                              asm_specification,
                              LOOKUP_ONLYCONVERTING);
              orig_init = init;
-             if (CLASS_TYPE_P (TREE_TYPE (decl)))
+             if (is_class)
                {
                  vec_safe_push (for_block, this_pre_body);
                  init = NULL_TREE;
@@ -33348,10 +33360,39 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
                init = pop_stmt_list (this_pre_body);
              this_pre_body = NULL_TREE;
            }
+         else if (is_cilk && next_is_op_paren)
+           {
+             cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+             init = cp_parser_assignment_expression (parser);
+             cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+             goto non_class;
+           }
+         else if (is_cilk && next_is_eq)
+           {
+             bool braced = false;
+             cp_parser_require (parser, CPP_EQ, RT_EQ);
+             if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+               {
+                 braced = true;
+                 cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+               }
+             init = cp_parser_assignment_expression (parser);
+             if (braced)
+               cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+             goto non_class;
+           }
+         else if (is_cilk && next_is_op_brace)
+           {
+             cp_lexer_set_source_position (parser->lexer);
+             maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+             cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+             init = cp_parser_assignment_expression (parser);
+             cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+             goto non_class;
+           }
          else
            {
-             /* Consume '='.  */
-             cp_lexer_consume_token (parser->lexer);
+             cp_parser_require (parser, CPP_EQ, RT_EQ);
              init = cp_parser_assignment_expression (parser);
 
            non_class:
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/for2.cc 
b/gcc/testsuite/g++.dg/cilk-plus/CK/for2.cc
new file mode 100644
index 0000000..495afa2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/for2.cc
@@ -0,0 +1,85 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -std=c++11" } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+template <typename T>
+class control_var
+{
+private:
+  T x;
+public:
+  control_var () { x = 0; };
+  control_var (T a) { x = a; };
+  T get_x () const { return x; };
+  void operator ++ (int) { x++; };
+  void operator += (T y) { x += y; };
+  bool operator < (T a) const { return x < a; };
+  bool operator <= (T a) const { return x <= a; };
+  friend T operator - (control_var a, control_var b) { return a.x - b.x; };
+};
+
+int arr[100];
+
+template <typename T>
+void
+f1 (T start)
+{
+  for (T i { start }; i < start + 100; i++)
+    arr[i - start] = i;
+}
+
+template <typename T>
+void
+f2 (int start)
+{
+  for (T i (start); i < start + 100; i++)
+    arr[i.get_x () - start] = i.get_x ();
+}
+
+void
+check (int start)
+{
+  for (int i = 0; i < 100; i++)
+    if (arr[i] != start + i)
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  _Cilk_for (control_var<int> i; i < 100; i++)
+    arr[i.get_x ()] = i.get_x ();
+  check (0);
+
+  _Cilk_for (control_var<int> i (10); i < 110; i++)
+    arr[i.get_x () - 10] = i.get_x ();
+  check (10);
+
+  _Cilk_for (control_var<int> i { 20 }; i < 120; i++)
+    arr[i.get_x () - 20] = i.get_x ();
+  check (20);
+
+  _Cilk_for (control_var<int> i = { 30 }; i < 130; i++)
+    arr[i.get_x () - 30] = i.get_x ();
+  check (30);
+
+  _Cilk_for (int i (40); i < 140; i++)
+    arr[i - 40] = i;
+  check (40);
+
+  _Cilk_for (int i { 50 }; i < 150; i++)
+    arr[i - 50] = i;
+  check (50);
+
+  _Cilk_for (int i = { 60 }; i < 160; i++)
+    arr[i - 60] = i;
+  check (60);
+
+  f1<int> (70);
+  check (70);
+
+  f2<control_var<int>> (80);
+  check (80);
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/for5.C 
b/gcc/testsuite/g++.dg/cilk-plus/for5.C
new file mode 100644
index 0000000..803b315
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/for5.C
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -std=c++11" } */
+
+template <typename T>
+class control_var
+{
+private:
+  T x;
+public:
+  control_var () { x = 0; };
+  control_var (T a) { x = a; };
+  T get_x () const { return x; };
+  void operator ++ (int) { x++; };
+  void operator += (T y) { x += y; };
+  bool operator < (T a) const { return x < a; };
+  bool operator <= (T a) const { return x <= a; };
+  friend T operator - (control_var a, control_var b) { return a.x - b.x; };
+};
+
+int arr[100];
+
+template <typename T>
+void
+f1 (T start)
+{
+  for (T i { start }; i < start + 100; i++)
+    arr[i - start] = i;
+}
+
+template <typename T>
+void
+f2 (int start)
+{
+  for (T i (start); i < start + 100; i++)
+    arr[i.get_x () - start] = i.get_x ();
+}
+
+void
+foo ()
+{
+  #pragma simd
+  for (control_var<int> i; i < 100; i++)
+    arr[i.get_x ()] = i.get_x ();
+
+  #pragma simd
+  for (control_var<int> i (10); i < 110; i++)
+    arr[i.get_x () - 10] = i.get_x ();
+
+  #pragma simd
+  for (control_var<int> i { 20 }; i < 120; i++)
+    arr[i.get_x () - 20] = i.get_x ();
+
+  #pragma simd
+  for (control_var<int> i = { 30 }; i < 130; i++)
+    arr[i.get_x () - 30] = i.get_x ();
+
+  #pragma simd
+  for (int i (40); i < 140; i++)
+    arr[i - 40] = i;
+
+  #pragma simd
+  for (int i { 50 }; i < 150; i++)
+    arr[i - 50] = i;
+
+  #pragma simd
+  for (int i = { 60 }; i < 160; i++)
+    arr[i - 60] = i;
+
+  f1<int> (70);
+
+  f2<control_var<int>> (80);
+}


Thanks,
  -- Ilya

Reply via email to