Hi! This patch does a few things: 1) replaces ICEs with diagnostics + return false in potential_constant_expression_1 for OpenMP/OpenACC/Cilk+ constructs, I believe unless the upcoming versions of those standards say otherwise, we should treat the constructs as invalid in constexpr When writing a testcase for 1), I've noticed very odd locus for all the error messages, so I've changed 2) all but one error in potential_constant_expression_1 to error_at with location_of (t) and finally 3) #pragma omp target/teams in some cases had wrong locus too
While 1) and 3) I think I can commit with my OpenMP maintainer hat on, I'm seeking approval for 2). The only spot in potential_constant_expression_1 I've kept error is for division by zero, which breaks several g++.dg/warn/overflow-warn*.C tests and I have no idea what's going on in dejagnu there (both patched and unpatched compilers emit 4 different diagnostics on a single line there, the difference is just in one of those diagnostics (different column), but the testcases actually try to match only 3 diagnostics and the wording of some of them is very similar and one of the expected diagnostics is pruned somewhere during the dejagnu processing). After fighting with that for a while I gave up. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-02-22 Jakub Jelinek <ja...@redhat.com> PR c++/79664 * parser.c (cp_parser_omp_teams, cp_parser_omp_target): Use SET_EXPR_LOCATION on OMP_TARGET/OMP_TEAMS tree. * constexpr.c (potential_constant_expression_1): Handle OMP_*, OACC_* and CILK_* trees. Use error_at with location_of (t) instead of error, use location_of (t) instead of EXPR_LOC_OR_LOC (t, input_location). * g++.dg/gomp/teams-1.C: Adjust expected diagnostic location. * g++.dg/cpp1y/constexpr-throw.C: Likewise. * g++.dg/gomp/pr79664.C: New test. --- gcc/cp/parser.c.jj 2017-02-20 13:43:21.000000000 +0100 +++ gcc/cp/parser.c 2017-02-22 17:17:39.176918357 +0100 @@ -35519,6 +35519,7 @@ cp_parser_omp_teams (cp_parser *parser, OMP_TEAMS_CLAUSES (ret) = clauses; OMP_TEAMS_BODY (ret) = body; OMP_TEAMS_COMBINED (ret) = 1; + SET_EXPR_LOCATION (ret, loc); return add_stmt (ret); } } @@ -35540,6 +35541,7 @@ cp_parser_omp_teams (cp_parser *parser, TREE_TYPE (stmt) = void_type_node; OMP_TEAMS_CLAUSES (stmt) = clauses; OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p); + SET_EXPR_LOCATION (stmt, loc); return add_stmt (stmt); } @@ -35958,6 +35960,7 @@ cp_parser_omp_target (cp_parser *parser, OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; OMP_TARGET_BODY (stmt) = body; OMP_TARGET_COMBINED (stmt) = 1; + SET_EXPR_LOCATION (stmt, pragma_tok->location); add_stmt (stmt); pc = &OMP_TARGET_CLAUSES (stmt); goto check_clauses; --- gcc/cp/constexpr.c.jj 2017-02-21 18:56:43.000000000 +0100 +++ gcc/cp/constexpr.c 2017-02-22 17:16:53.413507546 +0100 @@ -5004,7 +5004,8 @@ potential_constant_expression_1 (tree t, if (TREE_THIS_VOLATILE (t) && !DECL_P (t)) { if (flags & tf_error) - error ("expression %qE has side-effects", t); + error_at (location_of (t), + "expression %qE has side-effects", t); return false; } if (CONSTANT_CLASS_P (t)) @@ -5086,7 +5087,7 @@ potential_constant_expression_1 (tree t, { /* fold_call_expr can't do anything with IFN calls. */ if (flags & tf_error) - error_at (EXPR_LOC_OR_LOC (t, input_location), + error_at (location_of (t), "call to internal function %qE", t); return false; } @@ -5105,7 +5106,7 @@ potential_constant_expression_1 (tree t, { if (flags & tf_error) { - error_at (EXPR_LOC_OR_LOC (t, input_location), + error_at (location_of (t), "call to non-constexpr function %qD", fun); explain_invalid_constexpr_fn (fun); } @@ -5199,7 +5200,7 @@ potential_constant_expression_1 (tree t, && !integer_zerop (from)) { if (flags & tf_error) - error_at (EXPR_LOC_OR_LOC (t, input_location), + error_at (location_of (t), "reinterpret_cast from integer to pointer"); return false; } @@ -5266,7 +5267,8 @@ potential_constant_expression_1 (tree t, && !DECL_DECLARED_CONSTEXPR_P (DECL_CONTEXT (x))) { if (flags & tf_error) - error ("use of %<this%> in a constant expression"); + error_at (location_of (t), + "use of %<this%> in a constant expression"); return false; } return true; @@ -5354,10 +5356,40 @@ potential_constant_expression_1 (tree t, case DELETE_EXPR: case VEC_DELETE_EXPR: case THROW_EXPR: + case OMP_PARALLEL: + case OMP_TASK: + case OMP_FOR: + case OMP_DISTRIBUTE: + case OMP_TASKLOOP: + case OMP_TEAMS: + case OMP_TARGET_DATA: + case OMP_TARGET: + case OMP_SECTIONS: + case OMP_ORDERED: + case OMP_CRITICAL: + case OMP_SINGLE: + case OMP_SECTION: + case OMP_MASTER: + case OMP_TASKGROUP: + case OMP_TARGET_UPDATE: + case OMP_TARGET_ENTER_DATA: + case OMP_TARGET_EXIT_DATA: case OMP_ATOMIC: case OMP_ATOMIC_READ: case OMP_ATOMIC_CAPTURE_OLD: case OMP_ATOMIC_CAPTURE_NEW: + case OACC_PARALLEL: + case OACC_KERNELS: + case OACC_DATA: + case OACC_HOST_DATA: + case OACC_LOOP: + case OACC_CACHE: + case OACC_DECLARE: + case OACC_ENTER_DATA: + case OACC_EXIT_DATA: + case OACC_UPDATE: + case CILK_SIMD: + case CILK_FOR: /* GCC internal stuff. */ case VA_ARG_EXPR: case OBJ_TYPE_REF: @@ -5366,7 +5398,8 @@ potential_constant_expression_1 (tree t, case AT_ENCODE_EXPR: fail: if (flags & tf_error) - error ("expression %qE is not a constant expression", t); + error_at (location_of (t), + "expression %qE is not a constant expression", t); return false; case TYPEID_EXPR: @@ -5378,8 +5411,9 @@ potential_constant_expression_1 (tree t, && TYPE_POLYMORPHIC_P (TREE_TYPE (e))) { if (flags & tf_error) - error ("typeid-expression is not a constant expression " - "because %qE is of polymorphic type", e); + error_at (location_of (t), + "typeid-expression is not a constant expression " + "because %qE is of polymorphic type", e); return false; } return true; @@ -5438,8 +5472,9 @@ potential_constant_expression_1 (tree t, constant expression. */ { if (flags & tf_error) - error ("cast to non-integral type %qT in a constant expression", - TREE_TYPE (t)); + error_at (location_of (t), + "cast to non-integral type %qT in a constant expression", + TREE_TYPE (t)); return false; } @@ -5504,8 +5539,9 @@ potential_constant_expression_1 (tree t, { if (flags & tf_error) { - error ("temporary of non-literal type %qT in a " - "constant expression", TREE_TYPE (t)); + error_at (location_of (t), + "temporary of non-literal type %qT in a " + "constant expression", TREE_TYPE (t)); explain_non_literal_class (TREE_TYPE (t)); } return false; @@ -5681,7 +5717,8 @@ potential_constant_expression_1 (tree t, want_rval, strict, tf_none)) return true; if (flags & tf_error) - error ("expression %qE is not a constant expression", t); + error_at (location_of (t), + "expression %qE is not a constant expression", t); return false; case VEC_INIT_EXPR: @@ -5689,7 +5726,8 @@ potential_constant_expression_1 (tree t, return true; if (flags & tf_error) { - error ("non-constant array initialization"); + error_at (location_of (t), + "non-constant array initialization"); diagnose_non_constexpr_vec_init (t); } return false; @@ -5710,7 +5748,8 @@ potential_constant_expression_1 (tree t, if (breaks (target) || continues (target)) return true; if (flags & tf_error) - error ("%<goto%> is not a constant expression"); + error_at (location_of (t), + "%<goto%> is not a constant expression"); return false; } --- gcc/testsuite/g++.dg/gomp/teams-1.C.jj 2016-05-24 10:56:00.000000000 +0200 +++ gcc/testsuite/g++.dg/gomp/teams-1.C 2017-02-22 17:20:18.310869557 +0100 @@ -26,7 +26,7 @@ foo (int x) { #pragma omp target teams { case 0:; } // { dg-error "jump" } - // { dg-warning "statement will never be executed" "" { target *-*-* } 28 } + // { dg-warning "statement will never be executed" "" { target *-*-* } 27 } // { dg-message "enters" "" { target *-*-* } 28 } } } --- gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C.jj 2016-08-06 12:11:32.000000000 +0200 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C 2017-02-22 16:42:55.605778417 +0100 @@ -7,19 +7,19 @@ constexpr void f1() { constexpr void f2() { if (true) - throw; -} // { dg-error "not a constant expression" } + throw; // { dg-error "not a constant expression" } +} constexpr void f3() { if (false) ; else - throw; -}// { dg-error "not a constant expression" } + throw; // { dg-error "not a constant expression" } +} constexpr void f4() { - throw; -}// { dg-error "not a constant expression" } + throw; // { dg-error "not a constant expression" } +} constexpr int fun(int n) { switch (n) { --- gcc/testsuite/g++.dg/gomp/pr79664.C.jj 2017-02-22 16:29:07.715586641 +0100 +++ gcc/testsuite/g++.dg/gomp/pr79664.C 2017-02-22 16:28:40.000000000 +0100 @@ -0,0 +1,168 @@ +// PR c++/79664 +// { dg-do compile } +// { dg-options "-std=c++14 -fopenmp" } + +constexpr int +f1 () +{ + int i = 0; +#pragma omp parallel for // { dg-error "is not a constant expression" } + for (i = 0; i < 10; ++i) + ; + return 0; +} + +constexpr int +f2 () +{ + int i = 0; +#pragma omp parallel // { dg-error "is not a constant expression" } + i = 5; + return 0; +} + +constexpr int +f3 () +{ + int i = 0; +#pragma omp task // { dg-error "is not a constant expression" } + i = 5; + return 0; +} + +constexpr int +f4 () +{ + int i = 0; +#pragma omp for // { dg-error "is not a constant expression" } + for (i = 0; i < 10; ++i) + ; + return 0; +} + +constexpr int +f5 () +{ + int i = 0; +#pragma omp taskloop // { dg-error "is not a constant expression" } + for (i = 0; i < 10; ++i) + ; + return 0; +} + +constexpr int +f6 () +{ + int i = 0; +#pragma omp target teams // { dg-error "is not a constant expression" } + i = 5; + return 0; +} + +constexpr int +f7 () +{ + int i = 0; +#pragma omp target data map(tofrom:i) // { dg-error "is not a constant expression" } + i = 5; + return 0; +} + +constexpr int +f8 () +{ + int i = 0; +#pragma omp target // { dg-error "is not a constant expression" } + i = 5; + return 0; +} + +constexpr int +f9 () +{ + int i = 0; +#pragma omp sections // { dg-error "is not a constant expression" } + { +#pragma omp section + i = 5; + } + return 0; +} + +constexpr int +f10 () +{ + int i = 0; +#pragma omp ordered // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f11 () +{ + int i = 0; +#pragma omp critical // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f12 () +{ + int i = 0; +#pragma omp single // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f13 () +{ + int i = 0; +#pragma omp master // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f14 () +{ + int i = 0; +#pragma omp taskgroup // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f15 () +{ + int i = 0; +#pragma omp target update to(i) // { dg-error "is not a constant expression" } + i = 1; + return 0; +} + +constexpr int +f16 () +{ + int i = 0; +#pragma omp target update to(i) // { dg-error "is not a constant expression" } + return 0; +} + +constexpr int +f17 () +{ + int i = 0; +#pragma omp target enter data map(to:i) // { dg-error "is not a constant expression" } + return 0; +} + +constexpr int +f18 () +{ + int i = 0; +#pragma omp target exit data map(from:i) // { dg-error "is not a constant expression" } + return 0; +} Jakub