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. 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; +} -- Ilya