diff mbox

[CilkPlus] Allow parenthesized initialization in for-loops

Message ID 20160321144552.GA1422@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Verbin March 21, 2016, 2:45 p.m. UTC
Hi!

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?


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




  -- Ilya

Comments

Jakub Jelinek March 21, 2016, 2:58 p.m. UTC | #1
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?  What about
(some_class i { 0 }; some_class < ...; some_class++)
and similar syntax?  The testsuite coverage is insufficient (nothing e.g.
tests templates or #pragma simd).

	Jakub
diff mbox

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d58b5aa..49b3791 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -33284,54 +33284,68 @@  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_open;
 
 	  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))
-	    {
-	      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);
+	  is_cilk = code == CILK_SIMD || code == CILK_FOR;
+	  next_is_semicol
+	    = cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON);
+	  next_is_eq = cp_lexer_next_token_is (parser->lexer, CPP_EQ);
+	  next_is_open = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN);
 
+	  if (!is_cilk && next_is_open)
+	    {
+	      error ("parenthesized initialization is not allowed in "
+		     "OpenMP %<for%> loop");
+	      init = error_mark_node;
+	      cp_parser_skip_to_end_of_statement (parser);
+	    }
+	  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 (CLASS_TYPE_P (TREE_TYPE (decl))
-		   || type_dependent_expression_p (decl)
-		   || auto_node)
+	  else if (is_cilk && !(next_is_eq || next_is_open || next_is_semicol))
+	    {
+	      cp_parser_error (parser, "expected %<=%>, %<(%> or %<;%>");
+	      init = error_mark_node;
+	      cp_parser_skip_to_end_of_statement (parser);
+	    }
+	  else if (is_cilk && !is_class && next_is_open)
+	    {
+	      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_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;
 		}
 		      
@@ -33339,7 +33353,7 @@  cp_parser_omp_for_loop_init (cp_parser *parser,
 			      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;
@@ -33350,8 +33364,7 @@  cp_parser_omp_for_loop_init (cp_parser *parser,
 	    }
 	  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..b9e4420
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/for2.cc
@@ -0,0 +1,46 @@ 
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+class control_var
+{
+private:
+  int x;
+public:
+  control_var () { x = 0; };
+  control_var (int a) { x = a; };
+  int get_x () const { return x; };
+  void operator ++ (int) { x++; };
+  void operator += (int y) { x += y; };
+  bool operator < (const control_var &a) const { return x < a.x; };
+  friend int operator - (control_var a, control_var b) { return a.x - b.x; };
+};
+
+int
+main ()
+{
+  int arr[100];
+
+  _Cilk_for (control_var i; i < control_var (100); i++)
+    arr[i.get_x ()] = i.get_x ();
+
+  for (int i = 0; i < 100; i++)
+    if (arr[i] != i)
+      __builtin_abort ();
+
+  _Cilk_for (control_var i (50); i < control_var (150); i++)
+    arr[i.get_x () - 50] = i.get_x ();
+
+  for (int i = 0; i < 100; i++)
+    if (arr[i] != i + 50)
+      __builtin_abort ();
+
+  _Cilk_for (int i (100); i < 200; i++)
+    arr[i - 100] = i;
+
+  for (int i = 0; i < 100; i++)
+    if (arr[i] != i + 100)
+      __builtin_abort ();
+
+  return 0;
+}