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