From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1534) id EE1683858D39; Tue, 27 Sep 2022 09:42:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EE1683858D39 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1664271755; bh=vzNNoz+BSCLutNoueswDRLulMRhAZN2wM81xIrDZcB4=; h=From:To:Subject:Date:From; b=PO1454U+JsdPxZTrzBfyUKnluZNjix5bEMhg+Q1OcJ5234wdmlvNEmTd06/p3XFF0 rYYjQvBz3KaNCCoVPXYJLJCxpy/9mm8pUqMaXn8Wx0eYmMVUHkd3fM+GBSDL6zBjzD soYfWfw9lg6LKuLFUBQnHYnJJH63Xjmc2bbPbzrQ= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Tobias Burnus To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/omp/gcc-12] openmp: Add OpenMP assume, assumes and begin/end assumes support X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/devel/omp/gcc-12 X-Git-Oldrev: 8cf4c2316cb6a4082bf24fcc3003124e4b0a05c3 X-Git-Newrev: aacfbe588d563fe0987cc4758d6c749bf70a8086 Message-Id: <20220927094235.EE1683858D39@sourceware.org> Date: Tue, 27 Sep 2022 09:42:35 +0000 (GMT) List-Id: https://gcc.gnu.org/g:aacfbe588d563fe0987cc4758d6c749bf70a8086 commit aacfbe588d563fe0987cc4758d6c749bf70a8086 Author: Jakub Jelinek Date: Tue Sep 27 10:38:49 2022 +0200 openmp: Add OpenMP assume, assumes and begin/end assumes support The following patch implements OpenMP 5.1 #pragma omp assume #pragma omp assumes and #pragma omp begin assumes #pragma omp end assumes directive support for C and C++. Currently it doesn't remember anything from the assumption clauses for later, so is mainly to support the directives and diagnose errors in their use. If the recently posted C++23 [[assume (cond)]]; support makes it in, the intent is that this can be easily adjusted at least for the #pragma omp assume directive with holds clause(s) to use the same infrastructure. Now, C++23 portable assumptions are slightly different from OpenMP 5.1 assumptions' holds clause in that C++23 assumption holds just where it appears, while OpenMP 5.1 assumptions hold everywhere in the scope of the directive. For assumes directive which can appear at file or namespace scope it is the whole TU and everything that functions from there call at runtime, for begin assumes/end assumes pair all the functions in between those directives and everything they call and for assume directive the associated (currently structured) block. I have no idea how to represents such holds to be usable for optimizers, except to make #pragma omp assume holds (cond) block; expand essentially to [[assume (cond)]]; block; or [[assume (cond)]]; block; [[assume (cond)]]; for now. Except for holds clause, the other assumptions are OpenMP related, I'd say we should brainstorm where it would be useful to optimize based on such information (I guess e.g. in target regions it easily could) and only when we come up with something like that think about how to propagate the assumptions to the optimizers. 2022-09-27 Jakub Jelinek gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ASSUME, PRAGMA_OMP_ASSUMES and PRAGMA_OMP_BEGIN. Rename PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END. * c-pragma.cc (omp_pragmas): Add assumes and begin. For end rename PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END. (omp_pragmas_simd): Add assume. * c-common.h (c_omp_directives): Declare. * c-omp.cc (omp_directives): Rename to ... (c_omp_directives): ... this. No longer static. Uncomment assume, assumes, begin assumes and end assumes entries. In end declare target entry rename PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END. (c_omp_categorize_directive): Adjust for omp_directives to c_omp_directives renaming. gcc/c/ * c-lang.h (current_omp_begin_assumes): Declare. * c-parser.cc: Include bitmap.h. (c_parser_omp_end_declare_target): Rename to ... (c_parser_omp_end): ... this. Handle also end assumes. (c_parser_omp_begin, c_parser_omp_assumption_clauses, c_parser_omp_assumes, c_parser_omp_assume): New functions. (c_parser_translation_unit): Also diagnose #pragma omp begin assumes without corresponding #pragma omp end assumes. (c_parser_pragma): Use %s in may only be used at file scope diagnostics to decrease number of translatable messages. Handle PRAGMA_OMP_BEGIN and PRAGMA_OMP_ASSUMES. Handle PRAGMA_OMP_END rather than PRAGMA_OMP_END_DECLARE_TARGET and call c_parser_omp_end for it rather than c_parser_omp_end_declare_target. (c_parser_omp_construct): Handle PRAGMA_OMP_ASSUME. * c-decl.cc (current_omp_begin_assumes): Define. gcc/cp/ * cp-tree.h (struct omp_begin_assumes_data): New type. (struct saved_scope): Add omp_begin_assumes member. * parser.cc: Include bitmap.h. (cp_parser_omp_assumption_clauses, cp_parser_omp_assume, cp_parser_omp_assumes, cp_parser_omp_begin): New functions. (cp_parser_omp_end_declare_target): Rename to ... (cp_parser_omp_end): ... this. Handle also end assumes. (cp_parser_omp_construct): Handle PRAGMA_OMP_ASSUME. (cp_parser_pragma): Handle PRAGMA_OMP_ASSUME, PRAGMA_OMP_ASSUMES and PRAGMA_OMP_BEGIN. Handle PRAGMA_OMP_END rather than PRAGMA_OMP_END_DECLARE_TARGET and call cp_parser_omp_end for it rather than cp_parser_omp_end_declare_target. * pt.cc (apply_late_template_attributes): Also temporarily clear omp_begin_assumes. * semantics.cc (finish_translation_unit): Also diagnose #pragma omp begin assumes without corresponding #pragma omp end assumes. gcc/testsuite/ * c-c++-common/gomp/assume-1.c: New test. * c-c++-common/gomp/assume-2.c: New test. * c-c++-common/gomp/assume-3.c: New test. * c-c++-common/gomp/assumes-1.c: New test. * c-c++-common/gomp/assumes-2.c: New test. * c-c++-common/gomp/assumes-3.c: New test. * c-c++-common/gomp/assumes-4.c: New test. * c-c++-common/gomp/begin-assumes-1.c: New test. * c-c++-common/gomp/begin-assumes-2.c: New test. * c-c++-common/gomp/begin-assumes-3.c: New test. * c-c++-common/gomp/begin-assumes-4.c: New test. * c-c++-common/gomp/declare-target-6.c: New test. * g++.dg/gomp/attrs-1.C (bar): Add n1 and n2 arguments, add tests for assume directive. * g++.dg/gomp/attrs-2.C (bar): Likewise. * g++.dg/gomp/attrs-9.C: Add n1 and n2 variables, add tests for begin assumes directive. * g++.dg/gomp/attrs-15.C: New test. * g++.dg/gomp/attrs-16.C: New test. * g++.dg/gomp/attrs-17.C: New test. (cherry picked from commit 4790fe99f236c7f1b617722403e682ba2f82485f) Diff: --- gcc/c-family/ChangeLog.omp | 20 ++ gcc/c-family/c-common.h | 1 + gcc/c-family/c-omp.cc | 42 +-- gcc/c-family/c-pragma.cc | 5 +- gcc/c-family/c-pragma.h | 5 +- gcc/c/ChangeLog.omp | 21 ++ gcc/c/c-decl.cc | 4 + gcc/c/c-lang.h | 3 + gcc/c/c-parser.cc | 308 +++++++++++++++++-- gcc/cp/ChangeLog.omp | 23 ++ gcc/cp/cp-tree.h | 5 + gcc/cp/parser.cc | 340 +++++++++++++++++++-- gcc/cp/pt.cc | 1 + gcc/cp/semantics.cc | 7 + gcc/testsuite/ChangeLog.omp | 26 ++ gcc/testsuite/c-c++-common/gomp/assume-1.c | 29 ++ gcc/testsuite/c-c++-common/gomp/assume-2.c | 46 +++ gcc/testsuite/c-c++-common/gomp/assume-3.c | 27 ++ gcc/testsuite/c-c++-common/gomp/assumes-1.c | 26 ++ gcc/testsuite/c-c++-common/gomp/assumes-2.c | 23 ++ gcc/testsuite/c-c++-common/gomp/assumes-3.c | 15 + gcc/testsuite/c-c++-common/gomp/assumes-4.c | 6 + gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c | 46 +++ gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c | 63 ++++ gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c | 2 + gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c | 2 + gcc/testsuite/c-c++-common/gomp/declare-target-6.c | 2 + gcc/testsuite/g++.dg/gomp/attrs-1.C | 15 +- gcc/testsuite/g++.dg/gomp/attrs-15.C | 41 +++ gcc/testsuite/g++.dg/gomp/attrs-16.C | 26 ++ gcc/testsuite/g++.dg/gomp/attrs-17.C | 17 ++ gcc/testsuite/g++.dg/gomp/attrs-2.C | 15 +- gcc/testsuite/g++.dg/gomp/attrs-9.C | 20 ++ 33 files changed, 1165 insertions(+), 67 deletions(-) diff --git a/gcc/c-family/ChangeLog.omp b/gcc/c-family/ChangeLog.omp index 548c302225d..72c2e506844 100644 --- a/gcc/c-family/ChangeLog.omp +++ b/gcc/c-family/ChangeLog.omp @@ -1,3 +1,23 @@ +2022-09-27 Tobias Burnus + + Backport from mainline: + 2022-09-27 Jakub Jelinek + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ASSUME, + PRAGMA_OMP_ASSUMES and PRAGMA_OMP_BEGIN. Rename + PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END. + * c-pragma.cc (omp_pragmas): Add assumes and begin. + For end rename PRAGMA_OMP_END_DECLARE_TARGET to PRAGMA_OMP_END. + (omp_pragmas_simd): Add assume. + * c-common.h (c_omp_directives): Declare. + * c-omp.cc (omp_directives): Rename to ... + (c_omp_directives): ... this. No longer static. Uncomment + assume, assumes, begin assumes and end assumes entries. + In end declare target entry rename PRAGMA_OMP_END_DECLARE_TARGET + to PRAGMA_OMP_END. + (c_omp_categorize_directive): Adjust for omp_directives to + c_omp_directives renaming. + 2022-07-06 Tobias Burnus Backport from mainline: diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 9109a76cd75..51911fac103 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1272,6 +1272,7 @@ struct c_omp_directive { bool simd; }; +extern const struct c_omp_directive c_omp_directives[]; extern const struct c_omp_directive *c_omp_categorize_directive (const char *, const char *, const char *); diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index ab92d60e91a..c8573953e41 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -3896,21 +3896,21 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } -static const struct c_omp_directive omp_directives[] = { +const struct c_omp_directive c_omp_directives[] = { /* Keep this alphabetically sorted by the first word. Non-null second/third if any should precede null ones. */ { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE, C_OMP_DIR_DECLARATIVE, false }, - /* { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME, - C_OMP_DIR_INFORMATIONAL, false }, */ - /* { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES, - C_OMP_DIR_INFORMATIONAL, false }, */ + { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME, + C_OMP_DIR_INFORMATIONAL, false }, + { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES, + C_OMP_DIR_INFORMATIONAL, false }, { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC, C_OMP_DIR_CONSTRUCT, false }, { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER, C_OMP_DIR_STANDALONE, false }, - /* { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN, - C_OMP_DIR_INFORMATIONAL, false }, */ + { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_INFORMATIONAL, false }, /* { "begin", "declare", "target", PRAGMA_OMP_BEGIN, C_OMP_DIR_DECLARATIVE, false }, */ /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN, @@ -3939,9 +3939,9 @@ static const struct c_omp_directive omp_directives[] = { C_OMP_DIR_CONSTRUCT, false }, */ { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE, C_OMP_DIR_CONSTRUCT, true }, - /* { "end", "assumes", nullptr, PRAGMA_OMP_END, - C_OMP_DIR_INFORMATIONAL, false }, */ - { "end", "declare", "target", PRAGMA_OMP_END_DECLARE_TARGET, + { "end", "assumes", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_INFORMATIONAL, false }, + { "end", "declare", "target", PRAGMA_OMP_END, C_OMP_DIR_DECLARATIVE, false }, /* { "end", "declare", "variant", PRAGMA_OMP_END, C_OMP_DIR_DECLARATIVE, false }, */ @@ -4023,26 +4023,26 @@ const struct c_omp_directive * c_omp_categorize_directive (const char *first, const char *second, const char *third) { - const size_t n_omp_directives = ARRAY_SIZE (omp_directives); + const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives); for (size_t i = 0; i < n_omp_directives; i++) { - if ((unsigned char) omp_directives[i].first[0] + if ((unsigned char) c_omp_directives[i].first[0] < (unsigned char) first[0]) continue; - if ((unsigned char) omp_directives[i].first[0] + if ((unsigned char) c_omp_directives[i].first[0] > (unsigned char) first[0]) break; - if (strcmp (omp_directives[i].first, first)) + if (strcmp (c_omp_directives[i].first, first)) continue; - if (!omp_directives[i].second) - return &omp_directives[i]; - if (!second || strcmp (omp_directives[i].second, second)) + if (!c_omp_directives[i].second) + return &c_omp_directives[i]; + if (!second || strcmp (c_omp_directives[i].second, second)) continue; - if (!omp_directives[i].third) - return &omp_directives[i]; - if (!third || strcmp (omp_directives[i].third, third)) + if (!c_omp_directives[i].third) + return &c_omp_directives[i]; + if (!third || strcmp (c_omp_directives[i].third, third)) continue; - return &omp_directives[i]; + return &c_omp_directives[i]; } return NULL; } diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 8e4dfe5a83e..b0c0f9bb896 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -1360,14 +1360,16 @@ static const struct omp_pragma_def oacc_pragmas[] = { }; static const struct omp_pragma_def omp_pragmas[] = { { "allocate", PRAGMA_OMP_ALLOCATE }, + { "assumes", PRAGMA_OMP_ASSUMES }, { "atomic", PRAGMA_OMP_ATOMIC }, { "barrier", PRAGMA_OMP_BARRIER }, + { "begin", PRAGMA_OMP_BEGIN }, { "cancel", PRAGMA_OMP_CANCEL }, { "cancellation", PRAGMA_OMP_CANCELLATION_POINT }, { "critical", PRAGMA_OMP_CRITICAL }, { "depobj", PRAGMA_OMP_DEPOBJ }, { "error", PRAGMA_OMP_ERROR }, - { "end", PRAGMA_OMP_END_DECLARE_TARGET }, + { "end", PRAGMA_OMP_END }, { "flush", PRAGMA_OMP_FLUSH }, { "metadirective", PRAGMA_OMP_METADIRECTIVE }, { "nothing", PRAGMA_OMP_NOTHING }, @@ -1383,6 +1385,7 @@ static const struct omp_pragma_def omp_pragmas[] = { { "threadprivate", PRAGMA_OMP_THREADPRIVATE } }; static const struct omp_pragma_def omp_pragmas_simd[] = { + { "assume", PRAGMA_OMP_ASSUME }, { "declare", PRAGMA_OMP_DECLARE }, { "distribute", PRAGMA_OMP_DISTRIBUTE }, { "for", PRAGMA_OMP_FOR }, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 2fb459a9872..f56acf48574 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -45,8 +45,11 @@ enum pragma_kind { /* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code. */ PRAGMA_OMP_ALLOCATE, PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE, + PRAGMA_OMP_ASSUME, + PRAGMA_OMP_ASSUMES, PRAGMA_OMP_ATOMIC, PRAGMA_OMP_BARRIER, + PRAGMA_OMP_BEGIN, PRAGMA_OMP_CANCEL, PRAGMA_OMP_CANCELLATION_POINT, PRAGMA_OMP_CRITICAL, @@ -54,7 +57,7 @@ enum pragma_kind { PRAGMA_OMP_DEPOBJ, PRAGMA_OMP_DISTRIBUTE, PRAGMA_OMP_ERROR, - PRAGMA_OMP_END_DECLARE_TARGET, + PRAGMA_OMP_END, PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, PRAGMA_OMP_LOOP, diff --git a/gcc/c/ChangeLog.omp b/gcc/c/ChangeLog.omp index e86fbc83a31..1601b22cf63 100644 --- a/gcc/c/ChangeLog.omp +++ b/gcc/c/ChangeLog.omp @@ -1,3 +1,24 @@ +2022-09-27 Tobias Burnus + + Backport from mainline: + 2022-09-27 Jakub Jelinek + + * c-lang.h (current_omp_begin_assumes): Declare. + * c-parser.cc: Include bitmap.h. + (c_parser_omp_end_declare_target): Rename to ... + (c_parser_omp_end): ... this. Handle also end assumes. + (c_parser_omp_begin, c_parser_omp_assumption_clauses, + c_parser_omp_assumes, c_parser_omp_assume): New functions. + (c_parser_translation_unit): Also diagnose #pragma omp begin assumes + without corresponding #pragma omp end assumes. + (c_parser_pragma): Use %s in may only be used at file scope + diagnostics to decrease number of translatable messages. Handle + PRAGMA_OMP_BEGIN and PRAGMA_OMP_ASSUMES. Handle PRAGMA_OMP_END + rather than PRAGMA_OMP_END_DECLARE_TARGET and call c_parser_omp_end + for it rather than c_parser_omp_end_declare_target. + (c_parser_omp_construct): Handle PRAGMA_OMP_ASSUME. + * c-decl.cc (current_omp_begin_assumes): Define. + 2022-09-24 Tobias Burnus Backport from mainline: diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 0260fcb8c4f..4de04f25b67 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -156,6 +156,10 @@ static bool undef_nested_function; /* If non-zero, implicit "omp declare target" attribute is added into the attribute lists. */ int current_omp_declare_target_attribute; + +/* If non-zero, we are inside of + #pragma omp begin assumes ... #pragma omp end assumes region. */ +int current_omp_begin_assumes; /* Each c_binding structure describes one binding of an identifier to a decl. All the decls in a scope - irrespective of namespace - are diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h index 7bdab47bd9b..861abe8377a 100644 --- a/gcc/c/c-lang.h +++ b/gcc/c/c-lang.h @@ -63,5 +63,8 @@ struct GTY(()) language_function { /* If non-zero, implicit "omp declare target" attribute is added into the attribute lists. */ extern GTY(()) int current_omp_declare_target_attribute; +/* Similarly whether we are in between #pragma omp begin assumes and + #pragma omp end assumes (and how many times when nested). */ +extern GTY(()) int current_omp_begin_assumes; #endif /* ! GCC_C_LANG_H */ diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 36450a43beb..0c520a44fff 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -71,6 +71,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "memmodel.h" #include "c-family/known-headers.h" +#include "bitmap.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -1607,10 +1608,13 @@ enum pragma_context { pragma_external, pragma_struct, pragma_param, static bool c_parser_pragma (c_parser *, enum pragma_context, bool *); static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context); static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *); -static void c_parser_omp_end_declare_target (c_parser *); +static void c_parser_omp_begin (c_parser *); +static void c_parser_omp_end (c_parser *); static bool c_parser_omp_declare (c_parser *, enum pragma_context); static void c_parser_omp_requires (c_parser *); static bool c_parser_omp_error (c_parser *, enum pragma_context); +static void c_parser_omp_assumption_clauses (c_parser *, bool); +static void c_parser_omp_assumes (c_parser *); static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *); static void c_parser_oacc_routine (c_parser *, enum pragma_context); @@ -1691,6 +1695,13 @@ c_parser_translation_unit (c_parser *parser) "%<#pragma omp end declare target%>"); current_omp_declare_target_attribute = 0; } + if (current_omp_begin_assumes) + { + if (!errorcount) + error ("%<#pragma omp begin assumes%> without corresponding " + "%<#pragma omp end assumes%>"); + current_omp_begin_assumes = 0; + } } /* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9). @@ -12529,8 +12540,12 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_TARGET: return c_parser_omp_target (parser, context, if_p); - case PRAGMA_OMP_END_DECLARE_TARGET: - c_parser_omp_end_declare_target (parser); + case PRAGMA_OMP_BEGIN: + c_parser_omp_begin (parser); + return false; + + case PRAGMA_OMP_END: + c_parser_omp_end (parser); return false; case PRAGMA_OMP_SCAN: @@ -12554,13 +12569,26 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) if (context != pragma_external) { error_at (c_parser_peek_token (parser)->location, - "%<#pragma omp requires%> may only be used at file scope"); + "%<#pragma %s%> may only be used at file scope", + "omp requires"); c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; } c_parser_omp_requires (parser); return false; + case PRAGMA_OMP_ASSUMES: + if (context != pragma_external) + { + error_at (c_parser_peek_token (parser)->location, + "%<#pragma %s%> may only be used at file scope", + "omp assumes"); + c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); + return false; + } + c_parser_omp_assumes (parser); + return false; + case PRAGMA_OMP_NOTHING: c_parser_omp_nothing (parser); return false; @@ -22602,14 +22630,44 @@ c_parser_omp_declare_target (c_parser *parser) "directive with only % clauses ignored"); } +/* OpenMP 5.1 + #pragma omp begin assumes clauses[optseq] new-line */ + +static void +c_parser_omp_begin (c_parser *parser) +{ + const char *p = ""; + c_parser_consume_pragma (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "assumes") == 0) + { + c_parser_consume_token (parser); + c_parser_omp_assumption_clauses (parser, false); + current_omp_begin_assumes++; + } + else + { + c_parser_error (parser, "expected %"); + c_parser_skip_to_pragma_eol (parser); + } +} + +/* OpenMP 4.0 + #pragma omp end declare target + + OpenMP 5.1 + #pragma omp end assumes */ + static void -c_parser_omp_end_declare_target (c_parser *parser) +c_parser_omp_end (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; + const char *p = ""; c_parser_consume_pragma (parser); - if (c_parser_next_token_is (parser, CPP_NAME) - && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), - "declare") == 0) + if (c_parser_next_token_is (parser, CPP_NAME)) + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "declare") == 0) { c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME) @@ -22622,22 +22680,30 @@ c_parser_omp_end_declare_target (c_parser *parser) c_parser_skip_to_pragma_eol (parser); return; } + c_parser_skip_to_pragma_eol (parser); + if (!current_omp_declare_target_attribute) + error_at (loc, "%<#pragma omp end declare target%> without " + "corresponding %<#pragma omp declare target%>"); + else + current_omp_declare_target_attribute--; } - else + else if (strcmp (p, "assumes") == 0) { - c_parser_error (parser, "expected %"); + c_parser_consume_token (parser); c_parser_skip_to_pragma_eol (parser); - return; + if (!current_omp_begin_assumes) + error_at (loc, "%<#pragma omp end assumes%> without " + "corresponding %<#pragma omp begin assumes%>"); + else + current_omp_begin_assumes--; } - c_parser_skip_to_pragma_eol (parser); - if (!current_omp_declare_target_attribute) - error_at (loc, "%<#pragma omp end declare target%> without corresponding " - "%<#pragma omp declare target%>"); else - current_omp_declare_target_attribute--; + { + c_parser_error (parser, "expected % or %"); + c_parser_skip_to_pragma_eol (parser); + } } - /* OpenMP 4.0 #pragma omp declare reduction (reduction-id : typename-list : expression) \ initializer-clause[opt] new-line @@ -23877,6 +23943,211 @@ error: c_parser_skip_to_end_of_block_or_statement (parser); } +/* Assumption clauses: + OpenMP 5.1 + absent (directive-name-list) + contains (directive-name-list) + holds (expression) + no_openmp + no_openmp_routines + no_parallelism */ + +static void +c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) +{ + bool first = true; + bool no_openmp = false; + bool no_openmp_routines = false; + bool no_parallelism = false; + bitmap_head absent_head, contains_head; + + bitmap_obstack_initialize (NULL); + bitmap_initialize (&absent_head, &bitmap_default_obstack); + bitmap_initialize (&contains_head, &bitmap_default_obstack); + + if (c_parser_next_token_is (parser, CPP_PRAGMA_EOL)) + error_at (c_parser_peek_token (parser)->location, + "expected at least one assumption clause"); + + while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) + { + if (!first + && c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + + first = false; + + if (!c_parser_next_token_is (parser, CPP_NAME)) + break; + + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + location_t cloc = c_parser_peek_token (parser)->location; + + if (!strcmp (p, "no_openmp")) + { + c_parser_consume_token (parser); + if (no_openmp) + error_at (cloc, "too many %qs clauses", "no_openmp"); + no_openmp = true; + } + else if (!strcmp (p, "no_openmp_routines")) + { + c_parser_consume_token (parser); + if (no_openmp_routines) + error_at (cloc, "too many %qs clauses", "no_openmp_routines"); + no_openmp_routines = true; + } + else if (!strcmp (p, "no_parallelism")) + { + c_parser_consume_token (parser); + if (no_parallelism) + error_at (cloc, "too many %qs clauses", "no_parallelism"); + no_parallelism = true; + } + else if (!strcmp (p, "holds")) + { + c_parser_consume_token (parser); + matching_parens parens; + if (parens.require_open (parser)) + { + location_t eloc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value; + t = c_objc_common_truthvalue_conversion (eloc, t); + t = c_fully_fold (t, false, NULL); + if (is_assume) + { + /* FIXME: Emit .ASSUME (t) call here. */ + (void) t; + } + parens.skip_until_found_close (parser); + } + } + else if (!strcmp (p, "absent") || !strcmp (p, "contains")) + { + c_parser_consume_token (parser); + matching_parens parens; + if (parens.require_open (parser)) + { + do + { + const char *directive[3] = {}; + int i; + location_t dloc = c_parser_peek_token (parser)->location; + for (i = 0; i < 3; i++) + { + tree id; + if (c_parser_peek_nth_token (parser, i + 1)->type + == CPP_NAME) + id = c_parser_peek_nth_token (parser, i + 1)->value; + else if (c_parser_peek_nth_token (parser, i + 1)->keyword + != RID_MAX) + { + enum rid rid + = c_parser_peek_nth_token (parser, i + 1)->keyword; + id = ridpointers[rid]; + } + else + break; + directive[i] = IDENTIFIER_POINTER (id); + } + if (i == 0) + error_at (dloc, "expected directive name"); + else + { + const struct c_omp_directive *dir + = c_omp_categorize_directive (directive[0], + directive[1], + directive[2]); + if (dir == NULL + || dir->kind == C_OMP_DIR_DECLARATIVE + || dir->kind == C_OMP_DIR_INFORMATIONAL + || dir->id == PRAGMA_OMP_END + || (!dir->second && directive[1]) + || (!dir->third && directive[2])) + error_at (dloc, "unknown OpenMP directive name in " + "%qs clause argument", p); + else + { + int id = dir - c_omp_directives; + if (bitmap_bit_p (p[0] == 'a' ? &contains_head + : &absent_head, id)) + error_at (dloc, "%<%s%s%s%s%s%> directive " + "mentioned in both % and " + "% clauses", + directive[0], + directive[1] ? " " : "", + directive[1] ? directive[1] : "", + directive[2] ? " " : "", + directive[2] ? directive[2] : ""); + else if (!bitmap_set_bit (p[0] == 'a' + ? &absent_head + : &contains_head, id)) + error_at (dloc, "%<%s%s%s%s%s%> directive " + "mentioned multiple times in %qs " + "clauses", + directive[0], + directive[1] ? " " : "", + directive[1] ? directive[1] : "", + directive[2] ? " " : "", + directive[2] ? directive[2] : "", p); + } + for (; i; --i) + c_parser_consume_token (parser); + } + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; + } + while (1); + parens.skip_until_found_close (parser); + } + } + else if (startswith (p, "ext_")) + { + warning_at (cloc, 0, "unknown assumption clause %qs", p); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + matching_parens parens; + parens.consume_open (parser); + c_parser_balanced_token_sequence (parser); + parens.require_close (parser); + } + } + else + { + c_parser_consume_token (parser); + error_at (cloc, "expected assumption clause"); + break; + } + } + c_parser_skip_to_pragma_eol (parser); +} + +/* OpenMP 5.1 + #pragma omp assume clauses[optseq] new-line */ + +static void +c_parser_omp_assume (c_parser *parser, bool *if_p) +{ + c_parser_omp_assumption_clauses (parser, true); + add_stmt (c_parser_omp_structured_block (parser, if_p)); +} + +/* OpenMP 5.1 + #pragma omp assumes clauses[optseq] new-line */ + +static void +c_parser_omp_assumes (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_omp_assumption_clauses (parser, false); +} + /* Main entry point to parsing most OpenMP pragmas. */ static void @@ -23982,6 +24253,9 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) strcpy (p_name, "#pragma omp"); stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_ASSUME: + c_parser_omp_assume (parser, if_p); + return; default: gcc_unreachable (); } diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp index c3214f31252..ff9f62d6cd1 100644 --- a/gcc/cp/ChangeLog.omp +++ b/gcc/cp/ChangeLog.omp @@ -1,3 +1,26 @@ +2022-09-27 Tobias Burnus + + Backport from mainline: + 2022-09-27 Jakub Jelinek + + * cp-tree.h (struct omp_begin_assumes_data): New type. + (struct saved_scope): Add omp_begin_assumes member. + * parser.cc: Include bitmap.h. + (cp_parser_omp_assumption_clauses, cp_parser_omp_assume, + cp_parser_omp_assumes, cp_parser_omp_begin): New functions. + (cp_parser_omp_end_declare_target): Rename to ... + (cp_parser_omp_end): ... this. Handle also end assumes. + (cp_parser_omp_construct): Handle PRAGMA_OMP_ASSUME. + (cp_parser_pragma): Handle PRAGMA_OMP_ASSUME, PRAGMA_OMP_ASSUMES + and PRAGMA_OMP_BEGIN. Handle PRAGMA_OMP_END rather than + PRAGMA_OMP_END_DECLARE_TARGET and call cp_parser_omp_end + for it rather than cp_parser_omp_end_declare_target. + * pt.cc (apply_late_template_attributes): Also temporarily clear + omp_begin_assumes. + * semantics.cc (finish_translation_unit): Also diagnose + #pragma omp begin assumes without corresponding + #pragma omp end assumes. + 2022-09-09 Paul-Antoine Arras Backport from mainline: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 73d22aac7d6..774a7e68311 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1816,6 +1816,10 @@ struct GTY(()) omp_declare_target_attr { bool attr_syntax; }; +struct GTY(()) omp_begin_assumes_data { + bool attr_syntax; +}; + /* Global state. */ struct GTY(()) saved_scope { @@ -1863,6 +1867,7 @@ struct GTY(()) saved_scope { hash_map *GTY((skip)) x_local_specializations; vec *omp_declare_target_attribute; + vec *omp_begin_assumes; struct saved_scope *prev; }; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 93283f7a509..dda809e7d4f 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "cp-name-hint.h" #include "memmodel.h" #include "c-family/known-headers.h" +#include "bitmap.h" /* The lexer. */ @@ -46046,6 +46047,218 @@ cp_parser_omp_context_selector_specification (cp_parser *parser, return nreverse (ret); } +/* Assumption clauses: + OpenMP 5.1 + absent (directive-name-list) + contains (directive-name-list) + holds (expression) + no_openmp + no_openmp_routines + no_parallelism */ + +static void +cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, + bool is_assume) +{ + bool first = true; + bool no_openmp = false; + bool no_openmp_routines = false; + bool no_parallelism = false; + bitmap_head absent_head, contains_head; + + bitmap_obstack_initialize (NULL); + bitmap_initialize (&absent_head, &bitmap_default_obstack); + bitmap_initialize (&contains_head, &bitmap_default_obstack); + + if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)) + error_at (cp_lexer_peek_token (parser->lexer)->location, + "expected at least one assumption clause"); + + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) + { + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + + first = false; + + if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + break; + + const char *p + = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); + location_t cloc = cp_lexer_peek_token (parser->lexer)->location; + + if (!strcmp (p, "no_openmp")) + { + cp_lexer_consume_token (parser->lexer); + if (no_openmp) + error_at (cloc, "too many %qs clauses", "no_openmp"); + no_openmp = true; + } + else if (!strcmp (p, "no_openmp_routines")) + { + cp_lexer_consume_token (parser->lexer); + if (no_openmp_routines) + error_at (cloc, "too many %qs clauses", "no_openmp_routines"); + no_openmp_routines = true; + } + else if (!strcmp (p, "no_parallelism")) + { + cp_lexer_consume_token (parser->lexer); + if (no_parallelism) + error_at (cloc, "too many %qs clauses", "no_parallelism"); + no_parallelism = true; + } + else if (!strcmp (p, "holds")) + { + cp_lexer_consume_token (parser->lexer); + matching_parens parens; + if (parens.require_open (parser)) + { + tree t = cp_parser_assignment_expression (parser); + if (!type_dependent_expression_p (t)) + t = contextual_conv_bool (t, tf_warning_or_error); + if (is_assume) + { + /* FIXME: Emit .ASSUME (t) call here. */ + (void) t; + } + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } + } + else if (!strcmp (p, "absent") || !strcmp (p, "contains")) + { + cp_lexer_consume_token (parser->lexer); + matching_parens parens; + if (parens.require_open (parser)) + { + do + { + const char *directive[3] = {}; + int i; + location_t dloc + = cp_lexer_peek_token (parser->lexer)->location; + for (i = 0; i < 3; i++) + { + tree id; + if (cp_lexer_nth_token_is (parser->lexer, i + 1, CPP_NAME)) + id = cp_lexer_peek_nth_token (parser->lexer, + i + 1)->u.value; + else if (cp_lexer_nth_token_is (parser->lexer, i + 1, + CPP_KEYWORD)) + { + enum rid rid + = cp_lexer_peek_nth_token (parser->lexer, + i + 1)->keyword; + id = ridpointers[rid]; + } + else + break; + directive[i] = IDENTIFIER_POINTER (id); + } + if (i == 0) + error_at (dloc, "expected directive name"); + else + { + const struct c_omp_directive *dir + = c_omp_categorize_directive (directive[0], + directive[1], + directive[2]); + if (dir == NULL + || dir->kind == C_OMP_DIR_DECLARATIVE + || dir->kind == C_OMP_DIR_INFORMATIONAL + || dir->id == PRAGMA_OMP_END + || (!dir->second && directive[1]) + || (!dir->third && directive[2])) + error_at (dloc, "unknown OpenMP directive name in " + "%qs clause argument", p); + else + { + int id = dir - c_omp_directives; + if (bitmap_bit_p (p[0] == 'a' ? &contains_head + : &absent_head, id)) + error_at (dloc, "%<%s%s%s%s%s%> directive " + "mentioned in both % and " + "% clauses", + directive[0], + directive[1] ? " " : "", + directive[1] ? directive[1] : "", + directive[2] ? " " : "", + directive[2] ? directive[2] : ""); + else if (!bitmap_set_bit (p[0] == 'a' + ? &absent_head + : &contains_head, id)) + error_at (dloc, "%<%s%s%s%s%s%> directive " + "mentioned multiple times in %qs " + "clauses", + directive[0], + directive[1] ? " " : "", + directive[1] ? directive[1] : "", + directive[2] ? " " : "", + directive[2] ? directive[2] : "", p); + } + for (; i; --i) + cp_lexer_consume_token (parser->lexer); + } + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else + break; + } + while (1); + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } + } + else if (startswith (p, "ext_")) + { + warning_at (cloc, 0, "unknown assumption clause %qs", p); + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; + n; --n) + cp_lexer_consume_token (parser->lexer); + } + else + { + cp_lexer_consume_token (parser->lexer); + error_at (cloc, "expected assumption clause"); + break; + } + } + cp_parser_skip_to_pragma_eol (parser, pragma_tok); +} + +/* OpenMP 5.1 + # pragma omp assume clauses[optseq] new-line */ + +static void +cp_parser_omp_assume (cp_parser *parser, cp_token *pragma_tok, bool *if_p) +{ + cp_parser_omp_assumption_clauses (parser, pragma_tok, true); + add_stmt (cp_parser_omp_structured_block (parser, if_p)); +} + +/* OpenMP 5.1 + # pragma omp assumes clauses[optseq] new-line */ + +static bool +cp_parser_omp_assumes (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_omp_assumption_clauses (parser, pragma_tok, false); + return false; +} + /* Finalize #pragma omp declare variant after a fndecl has been parsed, and put that into "omp declare variant base" attribute. */ @@ -46495,8 +46708,41 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) "directive with only % clauses ignored"); } +/* OpenMP 5.1 + #pragma omp begin assumes clauses[optseq] new-line */ + static void -cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) +{ + const char *p = ""; + bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + p = IDENTIFIER_POINTER (id); + } + if (strcmp (p, "assumes") == 0) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_omp_assumption_clauses (parser, pragma_tok, false); + struct omp_begin_assumes_data a = { in_omp_attribute_pragma }; + vec_safe_push (scope_chain->omp_begin_assumes, a); + } + else + { + cp_parser_error (parser, "expected %"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + } +} + +/* OpenMP 4.0: + # pragma omp end declare target new-line + + OpenMP 5.1: + # pragma omp end assumes new-line */ + +static void +cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok) { const char *p = ""; bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; @@ -46522,33 +46768,58 @@ cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) cp_parser_skip_to_pragma_eol (parser, pragma_tok); return; } + cp_parser_require_pragma_eol (parser, pragma_tok); + if (!vec_safe_length (scope_chain->omp_declare_target_attribute)) + error_at (pragma_tok->location, + "%<#pragma omp end declare target%> without corresponding " + "%<#pragma omp declare target%>"); + else + { + omp_declare_target_attr + a = scope_chain->omp_declare_target_attribute->pop (); + if (a.attr_syntax != in_omp_attribute_pragma) + { + if (a.attr_syntax) + error_at (pragma_tok->location, + "% in attribute syntax terminated " + "with % in pragma syntax"); + else + error_at (pragma_tok->location, + "% in pragma syntax terminated " + "with % in attribute syntax"); + } + } } - else + else if (strcmp (p, "assumes") == 0) { - cp_parser_error (parser, "expected %"); - cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return; + cp_lexer_consume_token (parser->lexer); + cp_parser_require_pragma_eol (parser, pragma_tok); + if (!vec_safe_length (scope_chain->omp_begin_assumes)) + error_at (pragma_tok->location, + "%<#pragma omp end assumes%> without corresponding " + "%<#pragma omp begin assumes%>"); + else + { + omp_begin_assumes_data + a = scope_chain->omp_begin_assumes->pop (); + if (a.attr_syntax != in_omp_attribute_pragma) + { + if (a.attr_syntax) + error_at (pragma_tok->location, + "% in attribute syntax terminated " + "with % in pragma syntax"); + else + error_at (pragma_tok->location, + "% in pragma syntax terminated " + "with % in attribute syntax"); + } + } } - cp_parser_require_pragma_eol (parser, pragma_tok); - if (!vec_safe_length (scope_chain->omp_declare_target_attribute)) - error_at (pragma_tok->location, - "%<#pragma omp end declare target%> without corresponding " - "%<#pragma omp declare target%>"); else { - omp_declare_target_attr - a = scope_chain->omp_declare_target_attribute->pop (); - if (a.attr_syntax != in_omp_attribute_pragma) - { - if (a.attr_syntax) - error_at (pragma_tok->location, - "% in attribute syntax terminated " - "with % in pragma syntax"); - else - error_at (pragma_tok->location, - "% in pragma syntax terminated " - "with % in attribute syntax"); - } + cp_parser_error (parser, "expected % or %"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return; } } @@ -48220,6 +48491,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_ASSUME: + cp_parser_omp_assume (parser, pragma_tok, if_p); + return; default: gcc_unreachable (); } @@ -48827,6 +49101,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OACC_LOOP: case PRAGMA_OACC_PARALLEL: case PRAGMA_OACC_SERIAL: + case PRAGMA_OMP_ASSUME: case PRAGMA_OMP_ATOMIC: case PRAGMA_OMP_CRITICAL: case PRAGMA_OMP_DISTRIBUTE: @@ -48861,6 +49136,17 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) } return cp_parser_omp_requires (parser, pragma_tok); + case PRAGMA_OMP_ASSUMES: + if (context != pragma_external) + { + error_at (pragma_tok->location, + "%<#pragma omp assumes%> may only be used at file or " + "namespace scope"); + ret = true; + break; + } + return cp_parser_omp_assumes (parser, pragma_tok); + case PRAGMA_OMP_NOTHING: cp_parser_omp_nothing (parser, pragma_tok); return false; @@ -48888,8 +49174,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) pop_omp_privatization_clauses (stmt); return ret; - case PRAGMA_OMP_END_DECLARE_TARGET: - cp_parser_omp_end_declare_target (parser, pragma_tok); + case PRAGMA_OMP_BEGIN: + cp_parser_omp_begin (parser, pragma_tok); + return false; + + case PRAGMA_OMP_END: + cp_parser_omp_end (parser, pragma_tok); return false; case PRAGMA_OMP_SCAN: diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 410e8df504b..98f444bc95b 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -11891,6 +11891,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, auto o3 = make_temp_override (current_target_pragma, NULL_TREE); auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute, NULL); + auto o5 = make_temp_override (scope_chain->omp_begin_assumes, NULL); cplus_decl_attributes (decl_p, late_attrs, attr_flags); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index dad04dc4757..ac2f5d79e59 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3345,6 +3345,13 @@ finish_translation_unit (void) "%<#pragma omp end declare target%>"); vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0); } + if (vec_safe_length (scope_chain->omp_begin_assumes)) + { + if (!errorcount) + error ("%<#pragma omp begin assumes%> without corresponding " + "%<#pragma omp end assumes%>"); + vec_safe_truncate (scope_chain->omp_begin_assumes, 0); + } } /* Finish a template type parameter, specified as AGGR IDENTIFIER. diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index 0d452cbd690..15e95baa089 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,29 @@ +2022-09-27 Tobias Burnus + + Backport from mainline: + 2022-09-27 Jakub Jelinek + + * c-c++-common/gomp/assume-1.c: New test. + * c-c++-common/gomp/assume-2.c: New test. + * c-c++-common/gomp/assume-3.c: New test. + * c-c++-common/gomp/assumes-1.c: New test. + * c-c++-common/gomp/assumes-2.c: New test. + * c-c++-common/gomp/assumes-3.c: New test. + * c-c++-common/gomp/assumes-4.c: New test. + * c-c++-common/gomp/begin-assumes-1.c: New test. + * c-c++-common/gomp/begin-assumes-2.c: New test. + * c-c++-common/gomp/begin-assumes-3.c: New test. + * c-c++-common/gomp/begin-assumes-4.c: New test. + * c-c++-common/gomp/declare-target-6.c: New test. + * g++.dg/gomp/attrs-1.C (bar): Add n1 and n2 arguments, add + tests for assume directive. + * g++.dg/gomp/attrs-2.C (bar): Likewise. + * g++.dg/gomp/attrs-9.C: Add n1 and n2 variables, add tests for + begin assumes directive. + * g++.dg/gomp/attrs-15.C: New test. + * g++.dg/gomp/attrs-16.C: New test. + * g++.dg/gomp/attrs-17.C: New test. + 2022-09-24 Tobias Burnus Backport from mainline: diff --git a/gcc/testsuite/c-c++-common/gomp/assume-1.c b/gcc/testsuite/c-c++-common/gomp/assume-1.c new file mode 100644 index 00000000000..05c64a803da --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assume-1.c @@ -0,0 +1,29 @@ +void +foo (int i, int *a) +{ + #pragma omp assume no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U) + ; + #pragma omp assume no_openmp_routines, contains (simd) + { + #pragma omp simd + for (int j = 0; j < i; j++) + a[j] = j; + } + #pragma omp assume no_parallelism, contains (error) + { + if (i >= 32) + { + #pragma omp error at (execution) message ("Should not happen") + } + } + #pragma omp assume absent (for) + ; + #pragma omp assume absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) + ; + #pragma omp assume absent (distribute, flush, loop, masked, master, nothing, ordered) + ; + #pragma omp assume absent (parallel, scan, scope, section, sections, simd, single, task) + ; + #pragma omp assume absent (taskgroup, taskloop, taskwait, taskyield) + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/assume-2.c b/gcc/testsuite/c-c++-common/gomp/assume-2.c new file mode 100644 index 00000000000..47396055aef --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assume-2.c @@ -0,0 +1,46 @@ +void +foo (int i, int *a) +{ + #pragma omp assume no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */ + ; + #pragma omp assume no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */ + ; + #pragma omp assume no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */ + ; + #pragma omp assume absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */ + ; + #pragma omp assume absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */ + ; + #pragma omp assume contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */ + ; + #pragma omp assume contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */ + ; + #pragma omp assume absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */ + ; + #pragma omp assume contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */ + ; + #pragma omp assume contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ + ; + #pragma omp assume absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ + ; + #pragma omp assume contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ + ; + #pragma omp assume absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ + ; + #pragma omp assume absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ + ; + #pragma omp assume contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ + ; + #pragma omp assume contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ + ; + #pragma omp assume contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ + ; + #pragma omp assume absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ + ; + #pragma omp assume foobar /* { dg-error "expected assumption clause" } */ + ; + #pragma omp assume ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */ + ; /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */ + #pragma omp assume /* { dg-error "expected at least one assumption clause" } */ + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/assume-3.c b/gcc/testsuite/c-c++-common/gomp/assume-3.c new file mode 100644 index 00000000000..ce38359552d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assume-3.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-fno-openmp -fopenmp-simd" } */ + +int i, j; + +int +foo (void) +{ + j = 1; + return 1; +} + +int +main () +{ + #pragma omp assume holds (i < 42) + ; + #pragma omp assume holds (++i == 1) + ; + if (i != 0) + __builtin_abort (); + #pragma omp assume holds (foo () == 1) + ; + if (j != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-1.c b/gcc/testsuite/c-c++-common/gomp/assumes-1.c new file mode 100644 index 00000000000..8b3fb378bfb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assumes-1.c @@ -0,0 +1,26 @@ +int i; + +#pragma omp assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U) +void +bar (void) +{ +} + +#pragma omp assumes no_openmp_routines + +#pragma omp assumes no_parallelism + +#pragma omp assumes absent (for) +void +fred (void) +{ +} + +#pragma omp assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) \ + absent (distribute, flush, loop, masked, master, nothing, ordered) \ + absent (parallel, scan, scope, section, sections, simd, single, task) \ + absent (taskgroup, taskloop, taskwait, taskyield) +void +foo (void) +{ +} diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-2.c b/gcc/testsuite/c-c++-common/gomp/assumes-2.c new file mode 100644 index 00000000000..924f323d68f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assumes-2.c @@ -0,0 +1,23 @@ +#pragma omp assumes no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */ +#pragma omp assumes no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */ +#pragma omp assumes no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */ +#pragma omp assumes absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */ +#pragma omp assumes absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */ +#pragma omp assumes contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */ +#pragma omp assumes contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */ +#pragma omp assumes absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */ +#pragma omp assumes contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */ +#pragma omp assumes contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +#pragma omp assumes absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +#pragma omp assumes contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +#pragma omp assumes absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +#pragma omp assumes absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +#pragma omp assumes contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +#pragma omp assumes contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +#pragma omp assumes contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +#pragma omp assumes absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +#pragma omp assumes foobar /* { dg-error "expected assumption clause" } */ +#pragma omp assumes ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */ + /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */ +#pragma omp assumes /* { dg-error "expected at least one assumption clause" } */ +int i; diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-3.c b/gcc/testsuite/c-c++-common/gomp/assumes-3.c new file mode 100644 index 00000000000..0bfadace4b3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assumes-3.c @@ -0,0 +1,15 @@ +#pragma omp assumes contains (simd) +#pragma omp assumes contains (error) +#pragma omp assumes contains (simd) + +void +foo (int i, int *a) +{ + #pragma omp simd + for (int j = 0; j < i; j++) + a[j] = j; + if (i >= 32) + { + #pragma omp error at (execution) message ("Should not happen") + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/assumes-4.c b/gcc/testsuite/c-c++-common/gomp/assumes-4.c new file mode 100644 index 00000000000..6e77adb2fe8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assumes-4.c @@ -0,0 +1,6 @@ +void +foo (void) +{ + #pragma omp assumes no_openmp /* { dg-error "'#pragma omp assumes' may only be used at file scope" "" { target c } } */ + ; /* { dg-error "'#pragma omp assumes' may only be used at file or namespace scope" "" { target c++ } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c new file mode 100644 index 00000000000..c3332b12755 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-1.c @@ -0,0 +1,46 @@ +int i; + +#pragma omp begin assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U) +void +bar (void) +{ +} +#pragma omp end assumes + +#pragma omp begin assumes no_openmp_routines, contains (simd) +void +baz (int *a) +{ + #pragma omp simd + for (int j = 0; j < i; j++) + a[j] = j; +} +#pragma omp end assumes + +#pragma omp begin assumes no_parallelism, contains (error) +void +qux (void) +{ + if (i >= 32) + { + #pragma omp error at (execution) message ("Should not happen") + } +} +#pragma omp end assumes + +#pragma omp begin assumes absent (for) +void +fred (void) +{ +} +#pragma omp end assumes + +#pragma omp begin assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) \ + absent (distribute, flush, loop, masked, master, nothing, ordered) \ + absent (parallel, scan, scope, section, sections, simd, single, task) \ + absent (taskgroup, taskloop, taskwait, taskyield) +void +foo (void) +{ +} +#pragma omp end assumes diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c new file mode 100644 index 00000000000..15dae641933 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-2.c @@ -0,0 +1,63 @@ +#pragma omp begin assumes no_openmp no_openmp /* { dg-error "too many 'no_openmp' clauses" } */ +void f1 (void) {} +#pragma omp end assumes +#pragma omp begin assumes no_openmp_routines, no_openmp_routines /* { dg-error "too many 'no_openmp_routines' clauses" } */ +void f2 (void) {} +#pragma omp end assumes +#pragma omp begin assumes no_parallelism, no_parallelism /* { dg-error "too many 'no_parallelism' clauses" } */ +void f3 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (target, target) /* { dg-error "'target' directive mentioned multiple times in 'absent' clauses" } */ +void f4 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (target, teams) absent (teams, parallel) /* { dg-error "'teams' directive mentioned multiple times in 'absent' clauses" } */ +void f5 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (cancellation point, cancellation point) /* { dg-error "'cancellation point' directive mentioned multiple times in 'contains' clauses" } */ +void f6 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "target exit data' directive mentioned multiple times in 'contains' clauses" } */ +void f7 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (target enter data, target exit data) contains (target exit data, parallel) /* { dg-error "'target exit data' directive mentioned in both 'absent' and 'contains' clauses" } */ +void f8 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (target enter data, target exit data) absent (target enter data, parallel) /* { dg-error "'target enter data' directive mentioned in both 'absent' and 'contains' clauses" } */ +void f9 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (declare target) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +void f10 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (parallel for simd) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +void f11 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (target parallel) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +void f12 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (assume) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +void f13 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (assumes) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +void f14 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (begin assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +void f15 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (end assumes) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +void f16 (void) {} +#pragma omp end assumes +#pragma omp begin assumes contains (foo) /* { dg-error "unknown OpenMP directive name in 'contains' clause argument" } */ +void f17 (void) {} +#pragma omp end assumes +#pragma omp begin assumes absent (target enter something) /* { dg-error "unknown OpenMP directive name in 'absent' clause argument" } */ +void f18 (void) {} +#pragma omp end assumes +#pragma omp begin assumes foobar /* { dg-error "expected assumption clause" } */ +void f19 (void) {} +#pragma omp end assumes +#pragma omp begin assumes ext_GCC_foobarbaz, ext_GCC_baz (1, 12, 1 < 17), no_parallelism /* { dg-warning "unknown assumption clause 'ext_GCC_foobarbaz'" } */ +void f20 (void) {} /* { dg-warning "unknown assumption clause 'ext_GCC_baz'" "" { target *-*-* } .-1 } */ +#pragma omp end assumes +#pragma omp begin assumes /* { dg-error "expected at least one assumption clause" } */ +void f21 (void) {} +#pragma omp end assumes diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c new file mode 100644 index 00000000000..202d5c7741b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-3.c @@ -0,0 +1,2 @@ +#pragma omp begin assumes no_openmp_routines +void foo (void); /* { dg-error "'#pragma omp begin assumes' without corresponding '#pragma omp end assumes'" } */ diff --git a/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c b/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c new file mode 100644 index 00000000000..eea6f908d05 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/begin-assumes-4.c @@ -0,0 +1,2 @@ +#pragma omp end assumes /* { dg-error "'#pragma omp end assumes' without corresponding '#pragma omp begin assumes'" } */ +void foo (void); diff --git a/gcc/testsuite/c-c++-common/gomp/declare-target-6.c b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c new file mode 100644 index 00000000000..586eb50f801 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c @@ -0,0 +1,2 @@ +#pragma omp end declare target /* { dg-error "'#pragma omp end declare target' without corresponding '#pragma omp declare target'" } */ +void foo (void); diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C index 3f366aee581..dd33b073614 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-1.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C @@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s, void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s, int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm, - const char *msg) + const char *msg, int n1, int n2) { [[omp::directive (nothing)]]; [[omp::directive (error at (execution) severity (warning) message (msg))]]; @@ -612,6 +612,19 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s, ; [[omp::directive (parallel)]] switch (0) { case 1: break; default: break; } + [[omp::directive (assume no_openmp no_openmp_routines no_parallelism + absent (atomic, barrier, cancel, cancellation point) + absent (critical, depobj) + absent (distribute, flush, loop, masked, master, nothing, ordered) + absent (parallel, scan, scope, section, sections, simd, single, task) + absent (taskgroup, taskloop, taskwait, taskyield) + absent (target, teams, for, error) holds (n1 < n2))]] + if (0) + ; + [[omp::sequence (omp::directive (assume contains (simd)), + omp::directive (for simd))]] + for (int i = 0; i < 64; i++) + ; } void corge1 (); diff --git a/gcc/testsuite/g++.dg/gomp/attrs-15.C b/gcc/testsuite/g++.dg/gomp/attrs-15.C new file mode 100644 index 00000000000..d0598f47dff --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-15.C @@ -0,0 +1,41 @@ +// { dg-do compile { target c++11 } } + +#pragma omp begin assumes absent (target) +#pragma omp begin assumes absent (target) +[[omp::directive (begin assumes absent (target))]]; +int a; +[[omp::directive (end assumes)]]; +#pragma omp end assumes +#pragma omp end assumes +[[omp::directive (begin assumes absent (target))]]; +int b; +#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" } +#pragma omp begin assumes absent (target) +int c; +[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" } +#pragma omp begin assumes absent (target) +[[omp::directive (begin assumes absent (target))]]; +int d; +#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" } +#pragma omp begin assumes absent (target) +int e; +[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" } +#pragma omp end assumes +[[omp::directive (begin assumes absent (target))]]; +[[omp::directive (begin assumes absent (target))]]; +int f; +#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" } +#pragma omp begin assumes absent (target) +int g; +[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" } +[[omp::directive (end assumes)]]; +[[omp::directive (begin assumes absent (target))]]; +#pragma omp begin assumes absent (target) +int h; +#pragma omp end assumes +#pragma omp end assumes // { dg-error "'begin assumes' in attribute syntax terminated with 'end assumes' in pragma syntax" } +#pragma omp begin assumes absent (target) +[[omp::directive (begin assumes absent (target))]]; +int i; +[[omp::directive (end assumes)]]; +[[omp::directive (end assumes)]];// { dg-error "'begin assumes' in pragma syntax terminated with 'end assumes' in attribute syntax" } diff --git a/gcc/testsuite/g++.dg/gomp/attrs-16.C b/gcc/testsuite/g++.dg/gomp/attrs-16.C new file mode 100644 index 00000000000..5c1dcc587c5 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-16.C @@ -0,0 +1,26 @@ +// { dg-do compile { target c++11 } } + +int i; + +[[omp::directive (assumes no_openmp, absent (target, teams) holds (i < 32U) holds (i < 32U))]]; +void +bar (void) +{ +} + +[[omp::directive (assumes no_openmp_routines)]]; +[[omp::directive (assumes no_parallelism)]]; +[[omp::directive (assumes absent (for))]]; +void +fred (void) +{ +} + +[[omp::directive (assumes absent (atomic, barrier, cancel, cancellation point) absent (critical, depobj) + absent (distribute, flush, loop, masked, master, nothing, ordered) + absent (parallel, scan, scope, section, sections, simd, single, task) + absent (taskgroup, taskloop, taskwait, taskyield))]]; +void +foo (void) +{ +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-17.C b/gcc/testsuite/g++.dg/gomp/attrs-17.C new file mode 100644 index 00000000000..fe361467924 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-17.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +[[omp::directive (assumes contains (simd))]]; +[[omp::directive (assumes contains (error))]]; +[[omp::directive (assumes, contains (simd))]]; + +void +foo (int i, int *a) +{ + [[omp::directive (simd)]] + for (int j = 0; j < i; j++) + a[j] = j; + if (i >= 32) + { + [[omp::directive (error at (execution) message ("Should not happen"))]]; + } +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C index cb80415a4f8..7258d38c5a3 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-2.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C @@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s, void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s, int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm, - const char *msg) + const char *msg, int n1, int n2) { [[omp::directive (nothing)]]; [[omp::directive (error, at (execution), severity (warning), message (msg))]]; @@ -604,6 +604,19 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int hda, int s, extern int t2; [[omp::directive (declare reduction (dr: int: omp_out += omp_in),initializer (omp_priv = 0))]] ; + [[omp::directive (assume, no_openmp, no_openmp_routines, no_parallelism, + absent (atomic, barrier, cancel, cancellation point), + absent (critical, depobj), + absent (distribute, flush, loop, masked, master, nothing, ordered), + absent (parallel, scan, scope, section, sections, simd, single, task), + absent (taskgroup, taskloop, taskwait, taskyield), + absent (target, teams, for, error), holds (n1 < n2))]] + if (0) + ; + [[omp::sequence (omp::directive (assume, contains (simd)), + omp::directive (for simd))]] + for (int i = 0; i < 64; i++) + ; } void corge1 (); diff --git a/gcc/testsuite/g++.dg/gomp/attrs-9.C b/gcc/testsuite/g++.dg/gomp/attrs-9.C index 19a3b0a83c8..fa02299bcaf 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-9.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-9.C @@ -1,5 +1,6 @@ // { dg-do compile { target c++11 } } +int n1 = 0, n2 = 42; [[omp::sequence (directive (requires, atomic_default_mem_order (seq_cst)))]]; [[omp::directive (declare reduction (plus: int: omp_out += omp_in) initializer (omp_priv = 0))]]; int a; @@ -14,3 +15,22 @@ int d; [[omp::directive (end declare target)]]; [[omp::directive (end declare target)]]; [[omp::directive (nothing)]]; +[[omp::directive (begin assumes no_openmp no_openmp_routines no_parallelism + absent (atomic, barrier, cancel, cancellation point) + absent (critical, depobj) + absent (distribute, flush, loop, masked, master, nothing, ordered) + absent (parallel, scan, scope, section, sections, simd, single, task) + absent (taskgroup, taskloop, taskwait, taskyield) + absent (target, teams, for, error) holds (n1 < n2))]]; +void foo (void) {} +[[omp::directive (end assumes)]]; +[[omp::directive (begin assumes, no_openmp, no_openmp_routines, no_parallelism, + absent (atomic, barrier, cancel, cancellation point), + absent (critical, depobj), + absent (distribute, flush, loop, masked, master, nothing, ordered), + absent (parallel, scan, scope, section, sections, simd, single, task), + absent (taskgroup, taskloop, taskwait, taskyield), + absent (target, teams, for, error), holds (n1 < n2))]]; +[[omp::directive (begin assumes no_openmp)]]; +void bar (void) {} +[[omp::sequence (omp::directive (end assumes), omp::directive (end assumes))]];