aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-07-02 21:59:21 +0200
committerJakub Jelinek <jakub@redhat.com>2021-07-02 21:59:21 +0200
commit9984f63aab93a370101966b7eb198dc61130b3c8 (patch)
tree88a41229e3f99fe790101d1400024e8e30d90909 /gcc/c-family
parent2ca89394280da4afad6074ec3cb7136b6142af7b (diff)
downloadgcc-9984f63aab93a370101966b7eb198dc61130b3c8.zip
gcc-9984f63aab93a370101966b7eb198dc61130b3c8.tar.gz
gcc-9984f63aab93a370101966b7eb198dc61130b3c8.tar.bz2
openmp: Initial support for OpenMP directives expressed as C++11 attributes
This is an OpenMP 5.1 feature, but I think it is something very useful for OpenMP users, so I'm committing it now instead of waiting until all 5.0 work is done. The support is incomplete, only attributes on statements (or block local declarations) are supported right now, while for non-executable directives they should be also supported at namespace scope and at class scope, and for declarations in all places that appertain to the declarations rather than e.g. types. I need to also fix up handling of C++11 non-OpenMP attributes mixed with OpenMP attributes before block local declarations (currently it throws them away), probably reject if the directives appertain to labels etc. In order not to complicate all the OpenMP directive parsing, it is done by remembering the tokens from the attribute, slightly adjusting them and feeding them through a temporary new lexer to cp_parse_pragma. 2021-07-02 Jakub Jelinek <jakub@redhat.com> gcc/c-family/ * c-common.h (enum c_omp_directive_kind): New enum. (struct c_omp_directive): New type. (c_omp_categorize_directive): Declare. * c-omp.c (omp_directives): New variable. (c_omp_categorize_directive): New function. gcc/cp/ * parser.h (struct cp_lexer): Add in_omp_attribute_pragma member. (struct cp_omp_declare_simd_data): Likewise. * cp-tree.h (enum cp_tree_index): Add CPTI_OMP_IDENTIFIER. (omp_identifier): Define. * parser.c (cp_parser_skip_to_pragma_eol): Handle in_omp_attribute_pragma CPP_PRAGMA_EOL followed by CPP_EOF. (cp_parser_require_pragma_eol): Likewise. (struct cp_omp_attribute_data): New type. (cp_parser_handle_statement_omp_attributes): New function. (cp_parser_statement): Handle OpenMP directives in statement's attribute-specifier-seq. (cp_parser_omp_directive_args, cp_parser_omp_sequence_args): New functions. (cp_parser_std_attribute): Handle omp::directive and omp::sequence attributes. (cp_parser_omp_all_clauses): If in_omp_attribute_pragma, allow a comma also before the first clause. (cp_parser_omp_allocate): Likewise. (cp_parser_omp_atomic): Likewise. (cp_parser_omp_depobj): Likewise. (cp_parser_omp_flush): Likewise. (cp_parser_omp_ordered): Likewise. (cp_parser_omp_declare_simd): Save in_omp_attribute_pragma into struct cp_omp_declare_simd_data. (cp_finish_omp_declare_variant): Add in_omp_attribute_pragma argument. If set, allow a comma also before match clause. (cp_parser_late_parsing_omp_declare_simd): If in_omp_attribute_pragma, allow a comma also before the first clause. Adjust cp_finish_omp_declare_variant caller. (cp_parser_omp_declare_target): If in_omp_attribute_pragma, allow a comma also before the first clause. (cp_parser_omp_declare_reduction_exprs): Likewise. (cp_parser_omp_requires): Likewise. * decl.c (initialize_predefined_identifiers): Initialize omp_identifier. * decl2.c (cplus_decl_attributes): Reject omp::directive and omp::sequence attributes. gcc/testsuite/ * g++.dg/gomp/attrs-1.C: New test. * g++.dg/gomp/attrs-2.C: New test. * g++.dg/gomp/attrs-3.C: New test.
Diffstat (limited to 'gcc/c-family')
-rw-r--r--gcc/c-family/c-common.h19
-rw-r--r--gcc/c-family/c-omp.c151
2 files changed, 170 insertions, 0 deletions
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 88022d0..50ca8fb 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1246,6 +1246,25 @@ extern void c_omp_mark_declare_variant (location_t, tree, tree);
extern const char *c_omp_map_clause_name (tree, bool);
extern void c_omp_adjust_map_clauses (tree, bool);
+enum c_omp_directive_kind {
+ C_OMP_DIR_STANDALONE,
+ C_OMP_DIR_CONSTRUCT,
+ C_OMP_DIR_DECLARATIVE,
+ C_OMP_DIR_UTILITY,
+ C_OMP_DIR_INFORMATIONAL
+};
+
+struct c_omp_directive {
+ const char *first, *second, *third;
+ unsigned int id;
+ enum c_omp_directive_kind kind;
+ bool simd;
+};
+
+extern const struct c_omp_directive *c_omp_categorize_directive (const char *,
+ const char *,
+ const char *);
+
/* Return next tree in the chain for chain_next walking of tree nodes. */
static inline tree
c_tree_chain_next (tree t)
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index cd81a08..e70974d 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -2912,3 +2912,154 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target)
}
}
}
+
+static const struct c_omp_directive 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 }, */
+ { "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", "declare", "target", PRAGMA_OMP_BEGIN,
+ C_OMP_DIR_DECLARATIVE, false }, */
+ /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
+ C_OMP_DIR_DECLARATIVE, false }, */
+ /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
+ C_OMP_DIR_???, ??? }, */
+ { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
+ C_OMP_DIR_STANDALONE, false },
+ { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
+ C_OMP_DIR_STANDALONE, false },
+ { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
+ C_OMP_DIR_CONSTRUCT, false },
+ /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
+ C_OMP_DIR_DECLARATIVE, false }, */
+ { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
+ C_OMP_DIR_DECLARATIVE, true },
+ { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
+ C_OMP_DIR_DECLARATIVE, true },
+ { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
+ C_OMP_DIR_DECLARATIVE, false },
+ { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
+ C_OMP_DIR_DECLARATIVE, false },
+ { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
+ C_OMP_DIR_STANDALONE, false },
+ /* { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
+ 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,
+ C_OMP_DIR_DECLARATIVE, false },
+ /* { "end", "declare", "variant", PRAGMA_OMP_END,
+ C_OMP_DIR_DECLARATIVE, false }, */
+ /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
+ C_OMP_DIR_???, ??? }, */
+ /* error with at(execution) is C_OMP_DIR_STANDALONE. */
+ /* { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
+ C_OMP_DIR_UTILITY, false }, */
+ { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
+ C_OMP_DIR_STANDALONE, false },
+ { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
+ C_OMP_DIR_CONSTRUCT, true },
+ /* { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
+ C_OMP_DIR_STANDALONE, false }, */
+ { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
+ C_OMP_DIR_CONSTRUCT, true },
+ /* { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
+ C_OMP_DIR_CONSTRUCT, true }, */
+ { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
+ C_OMP_DIR_CONSTRUCT, true },
+ /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
+ C_OMP_DIR_???, ??? }, */
+ /* { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
+ C_OMP_DIR_UTILITY, false }, */
+ /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
+ { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
+ C_OMP_DIR_INFORMATIONAL, false },
+ { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
+ C_OMP_DIR_CONSTRUCT, true },
+ /* { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
+ C_OMP_DIR_CONSTRUCT, false }, */
+ { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "target", "data", nullptr, PRAGMA_OMP_TARGET,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "target", "enter", "data", PRAGMA_OMP_TARGET,
+ C_OMP_DIR_STANDALONE, false },
+ { "target", "exit", "data", PRAGMA_OMP_TARGET,
+ C_OMP_DIR_STANDALONE, false },
+ { "target", "update", nullptr, PRAGMA_OMP_TARGET,
+ C_OMP_DIR_STANDALONE, false },
+ { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
+ C_OMP_DIR_CONSTRUCT, false },
+ { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
+ C_OMP_DIR_STANDALONE, false },
+ { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
+ C_OMP_DIR_STANDALONE, false },
+ /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
+ C_OMP_DIR_CONSTRUCT, false }, */
+ { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
+ C_OMP_DIR_CONSTRUCT, true },
+ { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
+ C_OMP_DIR_DECLARATIVE, false }
+ /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
+ C_OMP_DIR_CONSTRUCT, false }, */
+};
+
+/* Find (non-combined/composite) OpenMP directive (if any) which starts
+ with FIRST keyword and for multi-word directives has SECOND and
+ THIRD keyword after it. */
+
+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);
+ for (size_t i = 0; i < n_omp_directives; i++)
+ {
+ if ((unsigned char) omp_directives[i].first[0]
+ < (unsigned char) first[0])
+ continue;
+ if ((unsigned char) omp_directives[i].first[0]
+ > (unsigned char) first[0])
+ break;
+ if (strcmp (omp_directives[i].first, first))
+ continue;
+ if (!omp_directives[i].second)
+ return &omp_directives[i];
+ if (!second || strcmp (omp_directives[i].second, second))
+ continue;
+ if (!omp_directives[i].third)
+ return &omp_directives[i];
+ if (!third || strcmp (omp_directives[i].third, third))
+ continue;
+ return &omp_directives[i];
+ }
+ return NULL;
+}