Hi!

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<bool, va_gc> *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.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2021-08-12  Jakub Jelinek  <ja...@redhat.com>

        * cp-tree.h (omp_declare_target_attr): New type.
        (struct saved_scope): Change type of omp_declare_target_attribute
        from int to vec<omp_declare_target_attr, va_gc> * 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.jj 2021-08-11 23:43:59.167894114 +0200
+++ gcc/cp/cp-tree.h    2021-08-11 23:46:28.447823665 +0200
@@ -1789,6 +1789,10 @@ union GTY((desc ("cp_tree_node_structure
 };
 
 
+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<tree, tree> *GTY((skip)) x_local_specializations;
+  vec<omp_declare_target_attr, va_gc> *omp_declare_target_attribute;
 
   struct saved_scope *prev;
 };
--- gcc/cp/parser.c.jj  2021-08-11 23:43:59.192893768 +0200
+++ gcc/cp/parser.c     2021-08-11 23:51:20.622755996 +0200
@@ -44605,8 +44605,10 @@ cp_parser_omp_declare_target (cp_parser
     }
   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))
@@ -44687,6 +44689,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;
@@ -44717,12 +44720,26 @@ cp_parser_omp_end_declare_target (cp_par
       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,
+                     "%<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
--- gcc/cp/semantics.c.jj       2021-08-11 23:43:45.892077375 +0200
+++ gcc/cp/semantics.c  2021-08-11 23:50:59.420051181 +0200
@@ -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);
     }
 }
 
--- gcc/cp/decl2.c.jj   2021-08-11 23:43:59.184893879 +0200
+++ gcc/cp/decl2.c      2021-08-11 23:47:52.025660091 +0200
@@ -1551,7 +1551,7 @@ cplus_decl_attributes (tree *decl, tree
     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))
--- gcc/testsuite/g++.dg/gomp/attrs-12.C.jj     2021-08-11 23:44:47.666224635 
+0200
+++ gcc/testsuite/g++.dg/gomp/attrs-12.C        2021-08-11 23:44:47.666224635 
+0200
@@ -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" }

        Jakub

Reply via email to