@@ -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,
@@ -1546,14 +1546,16 @@ static const struct omp_pragma_def oacc_
};
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 },
{ "nothing", PRAGMA_OMP_NOTHING },
{ "requires", PRAGMA_OMP_REQUIRES },
@@ -1568,6 +1570,7 @@ static const struct omp_pragma_def omp_p
{ "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 },
@@ -1286,6 +1286,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 *);
@@ -3097,21 +3097,21 @@ c_omp_adjust_map_clauses (tree clauses,
}
}
-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,
@@ -3140,9 +3140,9 @@ static const struct c_omp_directive omp_
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 }, */
@@ -3224,26 +3224,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;
}
@@ -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 */
@@ -71,6 +71,7 @@ along with GCC; see the file COPYING3.
#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.
@@ -1594,10 +1595,13 @@ enum pragma_context { pragma_external, p
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);
@@ -1678,6 +1682,13 @@ c_parser_translation_unit (c_parser *par
"%<#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).
@@ -12594,8 +12605,12 @@ c_parser_pragma (c_parser *parser, enum
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:
@@ -12619,13 +12634,26 @@ c_parser_pragma (c_parser *parser, enum
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;
@@ -22405,14 +22433,44 @@ c_parser_omp_declare_target (c_parser *p
"directive with only %<device_type%> clauses ignored");
}
+/* OpenMP 5.1
+ #pragma omp begin assumes clauses[optseq] new-line */
+
static void
-c_parser_omp_end_declare_target (c_parser *parser)
+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 %<assumes%>");
+ 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 (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)
@@ -22425,22 +22483,30 @@ c_parser_omp_end_declare_target (c_parse
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 %<declare%>");
+ 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 %<declare%> or %<assumes%>");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
-
/* OpenMP 4.0
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
@@ -23299,6 +23365,211 @@ c_parser_omp_error (c_parser *parser, en
return false;
}
+/* 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 %<absent%> and "
+ "%<contains%> 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
@@ -23404,6 +23675,9 @@ c_parser_omp_construct (c_parser *parser
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 ();
}
@@ -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
@@ -1834,6 +1834,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 {
@@ -1881,6 +1885,7 @@ struct GTY(()) saved_scope {
hash_map<tree, tree> *GTY((skip)) x_local_specializations;
vec<omp_declare_target_attr, va_gc> *omp_declare_target_attribute;
+ vec<omp_begin_assumes_data, va_gc> *omp_begin_assumes;
struct saved_scope *prev;
};
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
#include "cp-name-hint.h"
#include "memmodel.h"
#include "c-family/known-headers.h"
+#include "bitmap.h"
/* The lexer. */
@@ -46018,6 +46019,218 @@ cp_parser_omp_context_selector_specifica
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 %<absent%> and "
+ "%<contains%> 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. */
@@ -46467,8 +46680,41 @@ cp_parser_omp_declare_target (cp_parser
"directive with only %<device_type%> 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 %<assumes%>");
+ 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;
@@ -46494,34 +46740,59 @@ cp_parser_omp_end_declare_target (cp_par
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,
+ "%<declare target%> in attribute syntax terminated "
+ "with %<end declare target%> in pragma syntax");
+ else
+ error_at (pragma_tok->location,
+ "%<declare target%> in pragma syntax terminated "
+ "with %<end declare target%> in attribute syntax");
+ }
+ }
+ }
+ else if (strcmp (p, "assumes") == 0)
+ {
+ 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,
+ "%<begin assumes%> in attribute syntax terminated "
+ "with %<end assumes%> in pragma syntax");
+ else
+ error_at (pragma_tok->location,
+ "%<begin assumes%> in pragma syntax terminated "
+ "with %<end assumes%> in attribute syntax");
+ }
+ }
}
else
{
- cp_parser_error (parser, "expected %<declare%>");
+ cp_parser_error (parser, "expected %<declare%> or %<assumes%>");
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,
- "%<declare target%> in attribute syntax terminated "
- "with %<end declare target%> in pragma syntax");
- else
- error_at (pragma_tok->location,
- "%<declare target%> in pragma syntax terminated "
- "with %<end declare target%> in attribute syntax");
- }
- }
}
/* Helper function of cp_parser_omp_declare_reduction. Parse the combiner
@@ -47803,6 +48074,9 @@ cp_parser_omp_construct (cp_parser *pars
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 ();
}
@@ -48406,6 +48680,7 @@ cp_parser_pragma (cp_parser *parser, enu
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:
@@ -48440,6 +48715,17 @@ cp_parser_pragma (cp_parser *parser, enu
}
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;
@@ -48463,8 +48749,12 @@ cp_parser_pragma (cp_parser *parser, enu
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:
@@ -11945,6 +11945,7 @@ apply_late_template_attributes (tree *de
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);
@@ -3363,6 +3363,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.
@@ -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)
+ ;
+}
@@ -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" } */
+ ;
+}
@@ -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;
+}
@@ -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)
+{
+}
@@ -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;
@@ -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")
+ }
+}
@@ -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 } */
+}
@@ -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
@@ -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
@@ -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'" } */
@@ -0,0 +1,2 @@
+#pragma omp end assumes /* { dg-error "'#pragma omp end assumes' without corresponding '#pragma omp begin assumes'" } */
+void foo (void);
@@ -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);
@@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p
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 i
;
[[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 ();
@@ -123,7 +123,7 @@ baz (int d, int m, int i1, int i2, int p
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 i
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 ();
@@ -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))]];
@@ -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" }
@@ -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)
+{
+}
@@ -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"))]];
+ }
+}