From 01f8a8b48e50cbaa68b878d9f8a330b8c0736bed Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Aug 2021 09:26:27 +0200 Subject: [PATCH] openmp: Diagnose syntax mismatches between declare target and end declare target OpenMP 5.1 says: For any directive that has a paired end directive, including those with a begin and end pair, both directives must use either the attribute syntax or the pragma syntax. The following patch enforces it with the only pair so far recognized in C++ (Fortran has many, but on the other side doesn't have attribute syntax). While I initially wanted to use vec *member; in there, that unfortunately doesn't work, one gets linker errors and I guess it is fixable, but for begin declare target we'll need a struct anyway to store device_type etc. 2021-08-12 Jakub Jelinek * cp-tree.h (omp_declare_target_attr): New type. (struct saved_scope): Change type of omp_declare_target_attribute from int to vec * and move it. * parser.c (cp_parser_omp_declare_target): Instead of incrementing scope_chain->omp_declare_target_attribute, push a struct containing parser->lexer->in_omp_attribute_pragma to the vector. (cp_parser_omp_end_declare_target): Instead of decrementing scope_chain->omp_declare_target_attribute, pop a structure from it. Diagnose mismatching declare target vs. end declare target syntax. * semantics.c (finish_translation_unit): Use vec_safe_length and vec_safe_truncate on scope_chain->omp_declare_target_attributes. * decl2.c (cplus_decl_attributes): Use vec_safe_length on scope_chain->omp_declare_target_attributes. * g++.dg/gomp/attrs-12.C: New test. --- gcc/cp/cp-tree.h | 8 ++++--- gcc/cp/decl2.c | 2 +- gcc/cp/parser.c | 23 +++++++++++++++++--- gcc/cp/semantics.c | 4 ++-- gcc/testsuite/g++.dg/gomp/attrs-12.C | 41 ++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/attrs-12.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6a8264b..bd3f12a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1789,6 +1789,10 @@ union GTY((desc ("cp_tree_node_structure (&%h)"), }; +struct GTY(()) omp_declare_target_attr { + bool attr_syntax; +}; + /* Global state. */ struct GTY(()) saved_scope { @@ -1826,9 +1830,6 @@ struct GTY(()) saved_scope { int unevaluated_operand; int inhibit_evaluation_warnings; int noexcept_operand; - /* If non-zero, implicit "omp declare target" attribute is added into the - attribute lists. */ - int omp_declare_target_attribute; int ref_temp_count; struct stmt_tree_s x_stmt_tree; @@ -1837,6 +1838,7 @@ struct GTY(()) saved_scope { cp_binding_level *bindings; hash_map *GTY((skip)) x_local_specializations; + vec *omp_declare_target_attribute; struct saved_scope *prev; }; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index ba27388..0c9d2f4 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1551,7 +1551,7 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) return; /* Add implicit "omp declare target" attribute if requested. */ - if (scope_chain->omp_declare_target_attribute + if (vec_safe_length (scope_chain->omp_declare_target_attribute) && ((VAR_P (*decl) && (TREE_STATIC (*decl) || DECL_EXTERNAL (*decl))) || TREE_CODE (*decl) == FUNCTION_DECL)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index fbb8130..74de529 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -44641,8 +44641,10 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) } else { + struct omp_declare_target_attr a + = { parser->lexer->in_omp_attribute_pragma }; + vec_safe_push (scope_chain->omp_declare_target_attribute, a); cp_parser_require_pragma_eol (parser, pragma_tok); - scope_chain->omp_declare_target_attribute++; return; } for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) @@ -44723,6 +44725,7 @@ static void cp_parser_omp_end_declare_target (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; @@ -44753,12 +44756,26 @@ cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) return; } cp_parser_require_pragma_eol (parser, pragma_tok); - if (!scope_chain->omp_declare_target_attribute) + 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 - scope_chain->omp_declare_target_attribute--; + { + 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"); + } + } } /* Helper function of cp_parser_omp_declare_reduction. Parse the combiner diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 34e5d76..2e23818 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3271,12 +3271,12 @@ finish_translation_unit (void) /* Do file scope __FUNCTION__ et al. */ finish_fname_decls (); - if (scope_chain->omp_declare_target_attribute) + if (vec_safe_length (scope_chain->omp_declare_target_attribute)) { if (!errorcount) error ("%<#pragma omp declare target%> without corresponding " "%<#pragma omp end declare target%>"); - scope_chain->omp_declare_target_attribute = 0; + vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0); } } diff --git a/gcc/testsuite/g++.dg/gomp/attrs-12.C b/gcc/testsuite/g++.dg/gomp/attrs-12.C new file mode 100644 index 0000000..b613872 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-12.C @@ -0,0 +1,41 @@ +// { dg-do compile { target c++11 } } + +#pragma omp declare target +#pragma omp declare target +[[omp::directive (declare target)]]; +int a; +[[omp::directive (end declare target)]]; +#pragma omp end declare target +#pragma omp end declare target +[[omp::directive (declare target)]]; +int b; +#pragma omp end declare target // { dg-error "'declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" } +#pragma omp declare target +int c; +[[omp::directive (end declare target)]];// { dg-error "'declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" } +#pragma omp declare target +[[omp::directive (declare target)]]; +int d; +#pragma omp end declare target // { dg-error "'declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" } +#pragma omp declare target +int e; +[[omp::directive (end declare target)]];// { dg-error "'declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" } +#pragma omp end declare target +[[omp::directive (declare target)]]; +[[omp::directive (declare target)]]; +int f; +#pragma omp end declare target // { dg-error "'declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" } +#pragma omp declare target +int g; +[[omp::directive (end declare target)]];// { dg-error "'declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" } +[[omp::directive (end declare target)]]; +[[omp::directive (declare target)]]; +#pragma omp declare target +int h; +#pragma omp end declare target +#pragma omp end declare target // { dg-error "'declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" } +#pragma omp declare target +[[omp::directive (declare target)]]; +int i; +[[omp::directive (end declare target)]]; +[[omp::directive (end declare target)]];// { dg-error "'declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" } -- 2.7.4