public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/omp/gcc-11] openmp: Diagnose invalid mixing of the attribute and pragma syntax directives
@ 2021-07-23  8:36 Tobias Burnus
  0 siblings, 0 replies; only message in thread
From: Tobias Burnus @ 2021-07-23  8:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3c64d631f88de70e2dc6ddb78e0a1d833f4305b4

commit 3c64d631f88de70e2dc6ddb78e0a1d833f4305b4
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Jul 23 10:29:12 2021 +0200

    openmp: Diagnose invalid mixing of the attribute and pragma syntax directives
    
    The OpenMP 5.1 spec says that the attribute and pragma syntax directives
    should not be mixed on the same statement.  The following patch adds diagnostic
    for that,
      [[omp::directive (...)]]
      #pragma omp ...
    is always an error and for the other order
      #pragma omp ...
      [[omp::directive (...)]]
    it depends on whether the pragma directive is an OpenMP construct
    (then it is an error because it needs a structured block or loop
    or statement as body) or e.g. a standalone directive (then it is fine).
    
    Only block scope is handled for now though, namespace scope and class scope
    still needs implementing even the basic support.
    
    2021-07-23  Jakub Jelinek  <jakub@redhat.com>
    
    gcc/c-family/
            * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP__START_ and
            PRAGMA_OMP__LAST_ enumerators.
    gcc/cp/
            * parser.h (struct cp_parser): Add omp_attrs_forbidden_p member.
            * parser.c (cp_parser_handle_statement_omp_attributes): Diagnose
            mixing of attribute and pragma syntax directives when seeing
            omp::directive if parser->omp_attrs_forbidden_p or if attribute syntax
            directives are followed by OpenMP pragma.
            (cp_parser_statement): Clear parser->omp_attrs_forbidden_p after
            the cp_parser_handle_statement_omp_attributes call.
            (cp_parser_omp_structured_block): Add disallow_omp_attrs argument,
            if true, set parser->omp_attrs_forbidden_p.
            (cp_parser_omp_scan_loop_body, cp_parser_omp_sections_scope): Pass
            false as disallow_omp_attrs to cp_parser_omp_structured_block.
            (cp_parser_omp_parallel, cp_parser_omp_task): Set
            parser->omp_attrs_forbidden_p.
    gcc/testsuite/
            * g++.dg/gomp/attrs-4.C: New test.
            * g++.dg/gomp/attrs-5.C: New test.
    
    (cherry picked from commit 2c5d803d03209478b4f060785c6f6ba2f0de88ad)

Diff:
---
 gcc/c-family/ChangeLog.omp          |  8 +++++
 gcc/c-family/c-pragma.h             |  4 +++
 gcc/cp/ChangeLog.omp                | 19 ++++++++++++
 gcc/cp/parser.c                     | 40 +++++++++++++++++++++---
 gcc/cp/parser.h                     |  3 ++
 gcc/testsuite/ChangeLog.omp         |  8 +++++
 gcc/testsuite/g++.dg/gomp/attrs-4.C | 61 +++++++++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/gomp/attrs-5.C | 46 ++++++++++++++++++++++++++++
 8 files changed, 184 insertions(+), 5 deletions(-)

diff --git a/gcc/c-family/ChangeLog.omp b/gcc/c-family/ChangeLog.omp
index 44921d56afa..2b7e0c9d163 100644
--- a/gcc/c-family/ChangeLog.omp
+++ b/gcc/c-family/ChangeLog.omp
@@ -1,3 +1,11 @@
+2021-07-23  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backported from master:
+	2021-07-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP__START_ and
+	PRAGMA_OMP__LAST_ enumerators.
+
 2021-07-19  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backported from master:
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index c5d11ce0a52..abd66672f52 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -42,7 +42,9 @@ enum pragma_kind {
   PRAGMA_OACC_UPDATE,
   PRAGMA_OACC_WAIT,
 
+  /* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code.  */
   PRAGMA_OMP_ALLOCATE,
+  PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE,
   PRAGMA_OMP_ATOMIC,
   PRAGMA_OMP_BARRIER,
   PRAGMA_OMP_CANCEL,
@@ -72,6 +74,8 @@ enum pragma_kind {
   PRAGMA_OMP_TASKYIELD,
   PRAGMA_OMP_THREADPRIVATE,
   PRAGMA_OMP_TEAMS,
+  /* PRAGMA_OMP__LAST_ should be equal to the last PRAGMA_OMP_* code.  */
+  PRAGMA_OMP__LAST_ = PRAGMA_OMP_TEAMS,
 
   PRAGMA_GCC_PCH_PREPROCESS,
   PRAGMA_IVDEP,
diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index 99ea15071dd..9460749112f 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,22 @@
+2021-07-23  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backported from master:
+	2021-07-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* parser.h (struct cp_parser): Add omp_attrs_forbidden_p member.
+	* parser.c (cp_parser_handle_statement_omp_attributes): Diagnose
+	mixing of attribute and pragma syntax directives when seeing
+	omp::directive if parser->omp_attrs_forbidden_p or if attribute syntax
+	directives are followed by OpenMP pragma.
+	(cp_parser_statement): Clear parser->omp_attrs_forbidden_p after
+	the cp_parser_handle_statement_omp_attributes call.
+	(cp_parser_omp_structured_block): Add disallow_omp_attrs argument,
+	if true, set parser->omp_attrs_forbidden_p.
+	(cp_parser_omp_scan_loop_body, cp_parser_omp_sections_scope): Pass
+	false as disallow_omp_attrs to cp_parser_omp_structured_block.
+	(cp_parser_omp_parallel, cp_parser_omp_task): Set
+	parser->omp_attrs_forbidden_p.
+
 2021-07-21  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backported from master:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 90be79a3d66..9255bd3519e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11639,6 +11639,7 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs)
   auto_vec<cp_omp_attribute_data, 16> vec;
   int cnt = 0;
   int tokens = 0;
+  bool bad = false;
   for (tree *pa = &attrs; *pa; )
     if (get_attribute_namespace (*pa) == omp_identifier
 	&& is_attribute_p ("directive", get_attribute_name (*pa)))
@@ -11650,6 +11651,14 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs)
 	    gcc_assert (TREE_CODE (d) == DEFERRED_PARSE);
 	    cp_token *first = DEFPARSE_TOKENS (d)->first;
 	    cp_token *last = DEFPARSE_TOKENS (d)->last;
+	    if (parser->omp_attrs_forbidden_p)
+	      {
+		error_at (first->location,
+			  "mixing OpenMP directives with attribute and pragma "
+			  "syntax on the same statement");
+		parser->omp_attrs_forbidden_p = false;
+		bad = true;
+	      }
 	    const char *directive[3] = {};
 	    for (int i = 0; i < 3; i++)
 	      {
@@ -11705,6 +11714,9 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs)
     else
       pa = &TREE_CHAIN (*pa);
 
+  if (bad)
+    return attrs;
+
   unsigned int i;
   cp_omp_attribute_data *v;
   cp_omp_attribute_data *construct_seen = nullptr;
@@ -11754,6 +11766,18 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs)
 		" can only appear on an empty statement");
       return attrs;
     }
+  if (cnt && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      enum pragma_kind kind = cp_parser_pragma_kind (token);
+      if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
+	{
+	  error_at (token->location,
+		    "mixing OpenMP directives with attribute and pragma "
+		    "syntax on the same statement");
+	  return attrs;
+	}
+    }
 
   if (!tokens)
     return attrs;
@@ -11878,6 +11902,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
   if (std_attrs && (flag_openmp || flag_openmp_simd))
     std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs);
+  parser->omp_attrs_forbidden_p = false;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -39288,11 +39313,14 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
 }
 
 static tree
-cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p,
+				bool disallow_omp_attrs = true)
 {
   tree stmt = begin_omp_structured_block ();
   unsigned int save = cp_parser_begin_omp_structured_block (parser);
 
+  if (disallow_omp_attrs)
+    parser->omp_attrs_forbidden_p = true;
   cp_parser_statement (parser, NULL_TREE, false, if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
@@ -40658,7 +40686,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
   if (!braces.require_open (parser))
     return;
 
-  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = cp_parser_omp_structured_block (parser, NULL, false);
   substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
   add_stmt (substmt);
 
@@ -40693,7 +40721,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser)
     error ("expected %<#pragma omp scan%>");
 
   clauses = finish_omp_clauses (clauses, C_ORT_OMP);
-  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = cp_parser_omp_structured_block (parser, NULL, false);
   substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
 			clauses);
   add_stmt (substmt);
@@ -41492,7 +41520,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
   if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))
       != PRAGMA_OMP_SECTION)
     {
-      substmt = cp_parser_omp_structured_block (parser, NULL);
+      substmt = cp_parser_omp_structured_block (parser, NULL, false);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
@@ -41517,7 +41545,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
 	  error_suppress = true;
 	}
 
-      substmt = cp_parser_omp_structured_block (parser, NULL);
+      substmt = cp_parser_omp_structured_block (parser, NULL, false);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
@@ -41737,6 +41765,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
 
   block = begin_omp_parallel ();
   save = cp_parser_begin_omp_structured_block (parser);
+  parser->omp_attrs_forbidden_p = true;
   cp_parser_statement (parser, NULL_TREE, false, if_p);
   cp_parser_end_omp_structured_block (parser, save);
   stmt = finish_omp_parallel (clauses, block);
@@ -41799,6 +41828,7 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 				       "#pragma omp task", pragma_tok);
   block = begin_omp_task ();
   save = cp_parser_begin_omp_structured_block (parser);
+  parser->omp_attrs_forbidden_p = true;
   cp_parser_statement (parser, NULL_TREE, false, if_p);
   cp_parser_end_omp_structured_block (parser, save);
   return finish_omp_task (clauses, block);
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 5ef704721e2..6fdd214788a 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -398,6 +398,9 @@ struct GTY(()) cp_parser {
      identifiers) rather than an explicit template parameter list.  */
   bool fully_implicit_function_template_p;
 
+  /* TRUE if omp::directive or omp::sequence attributes may not appear.  */
+  bool omp_attrs_forbidden_p;
+
   /* Tracks the function's template parameter list when declaring a function
      using generic type parameters.  This is either a new chain in the case of a
      fully implicit function template or an extension of the function's existing
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index a6fa0776d60..a6ba454c4bb 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,11 @@
+2021-07-23  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backported from master:
+	2021-07-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* g++.dg/gomp/attrs-4.C: New test.
+	* g++.dg/gomp/attrs-5.C: New test.
+
 2021-07-21  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backported from master:
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-4.C b/gcc/testsuite/g++.dg/gomp/attrs-4.C
new file mode 100644
index 00000000000..005add826ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-4.C
@@ -0,0 +1,61 @@
+// { dg-do compile { target c++11 } }
+
+void
+foo (int x)
+{
+  [[omp::directive (parallel)]]
+  #pragma omp for						// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  for (int i = 0; i < 16; i++)
+    ;
+  [[omp::directive (barrier)]]					// { dg-error "standalone OpenMP directives in 'omp::directive' attribute can only appear on an empty statement" }
+  #pragma omp flush
+  ;
+  #pragma omp parallel
+  [[omp::directive (master)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp teams
+  [[omp::sequence (directive (parallel), directive (master))]]	// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp task
+  [[omp::directive (flush)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp master
+  [[omp::directive (flush)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp for ordered
+  for (int i = 0; i < 16; i++)
+    #pragma omp ordered
+    [[omp::directive (flush)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+    ;
+  #pragma omp single
+  [[omp::directive (flush)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp taskgroup
+  [[omp::directive (taskyield)]]				// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp target data map (tofrom: x)
+  [[omp::directive (flush)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp target
+  [[omp::directive (teams)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  [[omp::directive (parallel)]]
+  #pragma omp master						// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  [[omp::sequence (omp::directive (taskloop))]]			// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  for (int i = 0; i < 16; i++)
+    ;
+  #pragma omp parallel
+  [[omp::directive (for)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  for (int i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  [[omp::directive (master)]]					// { dg-error "for statement expected before '\\\[' token" }
+  ;
+  #pragma omp target teams
+  [[omp::directive (parallel)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  ;
+  #pragma omp parallel master
+  [[omp::directive (taskloop)]]					// { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+  for (int i = 0; i < 16; i++)
+    ;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-5.C b/gcc/testsuite/g++.dg/gomp/attrs-5.C
new file mode 100644
index 00000000000..f6d24b9540c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-5.C
@@ -0,0 +1,46 @@
+// { dg-do compile { target c++11 } }
+
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+  char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+void
+foo (int x)
+{
+  #pragma omp barrier
+  [[omp::directive (barrier)]];
+  #pragma omp parallel
+  {
+    #pragma omp cancel parallel
+    [[omp::directive (cancellation point, parallel)]];
+  }
+  #pragma omp parallel
+  {
+    #pragma omp cancellation point parallel
+    [[omp::directive (cancel parallel)]];
+  }
+  #pragma omp parallel
+  {
+    [[omp::directive (cancel, parallel)]];
+    #pragma omp cancellation point parallel
+  }
+  omp_depend_t depobj;
+  #pragma omp depobj(depobj) update(inout)
+  [[omp::directive (depobj(depobj), destroy)]];
+  #pragma omp flush
+  [[omp::directive (flush)]];
+  #pragma omp target enter data map (to: x)
+  [[omp::directive (target exit data, map (from: x))]];
+  [[omp::directive (target enter data, map (to: x))]];
+  #pragma omp target exit data map (from: x)
+  [[omp::directive (flush)]];
+  #pragma omp target update to (x)
+  [[omp::directive (flush)]];
+  #pragma omp taskwait
+  [[omp::directive (flush)]];
+  #pragma omp taskyield
+  [[omp::directive (flush)]];
+  extern int t;
+  #pragma omp threadprivate (t)
+  [[omp::directive (flush)]];
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-23  8:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-23  8:36 [gcc/devel/omp/gcc-11] openmp: Diagnose invalid mixing of the attribute and pragma syntax directives Tobias Burnus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).