[llvm] d95d3d2 - [Flang][OpenMP] Rework parser changes for OpenMP atomic construct.

Sameeran joshi via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 14 01:50:46 PDT 2020


Author: sameeran joshi
Date: 2020-10-14T14:19:49+05:30
New Revision: d95d3d2a42cb43fca956efe60ab5965d84b0efd5

URL: https://github.com/llvm/llvm-project/commit/d95d3d2a42cb43fca956efe60ab5965d84b0efd5
DIFF: https://github.com/llvm/llvm-project/commit/d95d3d2a42cb43fca956efe60ab5965d84b0efd5.diff

LOG: [Flang][OpenMP] Rework parser changes for OpenMP atomic construct.

`OmpStructureChecker` is supposed to work only with `parser::OmpClause`
after tablegen changes for OpenMP and OpenACC were introduced.
Hence `OmpMemoryOrderClause`, `OmpAtomicMemoryOrderClause` and similar ones were failing
to catch semantic errors, inspite of having code for semantic checks.
This patch tries to change parser for `OmpMemoryOrderClause` and similar dependent ones
and use `OmpClauseList` which resides/comes from common tablegen for OpenMP/OpenACC eventually using `parser::OmpClause`.

This patch also tries to :
1. Change `OmpCriticalDirective` in `openmp-parsers.cpp` to support `OmpClauseList`.
2. Check-flang regresses when changes were introduced due to missing semantic checks in OmpCritical, patch implements them at the minimal level to pass the regression.
3. Change tablegen to support Hint clause.
4. Adds missing source locations `CharBlock Source` in each atomic construct.
5. Remove dead code realted to `memory-order-clauses` after moving to `OmpClauseList`.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D88965

Added: 
    flang/test/Parser/omp-atomic-unparse.f90

Modified: 
    flang/include/flang/Parser/dump-parse-tree.h
    flang/include/flang/Parser/parse-tree.h
    flang/lib/Parser/openmp-parsers.cpp
    flang/lib/Parser/unparse.cpp
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/test/Semantics/omp-atomic.f90
    llvm/include/llvm/Frontend/OpenMP/OMP.td

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 921e6172bf89..e05c5d5e527e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -445,9 +445,6 @@ class ParseTreeDumper {
   NODE(parser, OmpAtomicCapture)
   NODE(OmpAtomicCapture, Stmt1)
   NODE(OmpAtomicCapture, Stmt2)
-  NODE(parser, OmpAtomicMemoryOrderClause)
-  NODE(parser, OmpAtomicMemoryOrderClauseList)
-  NODE(parser, OmpAtomicMemoryOrderClausePostList)
   NODE(parser, OmpAtomicRead)
   NODE(parser, OmpAtomicUpdate)
   NODE(parser, OmpAtomicWrite)
@@ -489,7 +486,6 @@ class ParseTreeDumper {
   NODE(parser, OmpEndCriticalDirective)
   NODE(parser, OmpEndLoopDirective)
   NODE(parser, OmpEndSectionsDirective)
-  NODE(parser, OmpHintExpr)
   NODE(parser, OmpIfClause)
   NODE_ENUM(OmpIfClause, DirectiveNameModifier)
   NODE(parser, OmpLinearClause)
@@ -502,7 +498,6 @@ class ParseTreeDumper {
   NODE(parser, OmpMapType)
   NODE(OmpMapType, Always)
   NODE_ENUM(OmpMapType, Type)
-  NODE(parser, OmpMemoryOrderClause)
   static std::string GetNodeName(const llvm::omp::Clause &x) {
     return llvm::Twine(
         "llvm::omp::Clause = ", llvm::omp::getOpenMPClauseName(x))

diff  --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index a9fb92cf2584..18559529eb69 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3591,14 +3591,11 @@ struct OpenMPDeclarativeConstruct {
       u;
 };
 
-// HINT(hint-expression)
-WRAPPER_CLASS(OmpHintExpr, ConstantExpr);
-
 // 2.13.2 CRITICAL [Name] <block> END CRITICAL [Name]
 struct OmpCriticalDirective {
   TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective);
   CharBlock source;
-  std::tuple<Verbatim, std::optional<Name>, std::optional<OmpHintExpr>> t;
+  std::tuple<Verbatim, std::optional<Name>, std::optional<OmpClause>> t;
 };
 struct OmpEndCriticalDirective {
   TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective);
@@ -3619,28 +3616,11 @@ struct OpenMPCriticalConstruct {
 // END ATOMIC
 EMPTY_CLASS(OmpEndAtomic);
 
-// Memory order clause
-struct OmpMemoryOrderClause {
-  WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, llvm::omp::Clause);
-  CharBlock source;
-};
-
-// ATOMIC Memory order clause or hint expression
-struct OmpAtomicMemoryOrderClause {
-  UNION_CLASS_BOILERPLATE(OmpAtomicMemoryOrderClause);
-  std::variant<OmpMemoryOrderClause, OmpHintExpr> u;
-};
-
-WRAPPER_CLASS(
-    OmpAtomicMemoryOrderClauseList, std::list<OmpAtomicMemoryOrderClause>);
-WRAPPER_CLASS(
-    OmpAtomicMemoryOrderClausePostList, std::list<OmpAtomicMemoryOrderClause>);
-
 // ATOMIC READ
 struct OmpAtomicRead {
   TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
-  std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
-      OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
+  CharBlock source;
+  std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
       std::optional<OmpEndAtomic>>
       t;
 };
@@ -3648,8 +3628,8 @@ struct OmpAtomicRead {
 // ATOMIC WRITE
 struct OmpAtomicWrite {
   TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
-  std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
-      OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
+  CharBlock source;
+  std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
       std::optional<OmpEndAtomic>>
       t;
 };
@@ -3657,8 +3637,8 @@ struct OmpAtomicWrite {
 // ATOMIC UPDATE
 struct OmpAtomicUpdate {
   TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
-  std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
-      OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
+  CharBlock source;
+  std::tuple<OmpClauseList, Verbatim, OmpClauseList, Statement<AssignmentStmt>,
       std::optional<OmpEndAtomic>>
       t;
 };
@@ -3666,18 +3646,19 @@ struct OmpAtomicUpdate {
 // ATOMIC CAPTURE
 struct OmpAtomicCapture {
   TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
+  CharBlock source;
   WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
   WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
-  std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
-      OmpAtomicMemoryOrderClausePostList, Stmt1, Stmt2, OmpEndAtomic>
+  std::tuple<OmpClauseList, Verbatim, OmpClauseList, Stmt1, Stmt2, OmpEndAtomic>
       t;
 };
 
 // ATOMIC
 struct OmpAtomic {
   TUPLE_CLASS_BOILERPLATE(OmpAtomic);
-  std::tuple<Verbatim, OmpAtomicMemoryOrderClauseList,
-      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+  CharBlock source;
+  std::tuple<Verbatim, OmpClauseList, Statement<AssignmentStmt>,
+      std::optional<OmpEndAtomic>>
       t;
 };
 

diff  --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index a7f4a1ae492c..5a7fd3d9c353 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -152,8 +152,13 @@ TYPE_PARSER(construct<OmpAlignedClause>(
 TYPE_PARSER(
     construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
 
-TYPE_PARSER("ALIGNED" >>
+TYPE_PARSER(
+    "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
+    "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
+    "ALIGNED" >>
         construct<OmpClause>(parenthesized(Parser<OmpAlignedClause>{})) ||
+    "ALLOCATE" >>
+        construct<OmpClause>(parenthesized(Parser<OmpAllocateClause>{})) ||
     "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
                       parenthesized(scalarIntConstantExpr))) ||
     "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
@@ -179,6 +184,7 @@ TYPE_PARSER("ALIGNED" >>
                   parenthesized(Parser<OmpObjectList>{}))) ||
     "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
                        parenthesized(scalarIntExpr))) ||
+    "HINT" >> construct<OmpClause>(parenthesized(constantExpr)) ||
     "IF" >> construct<OmpClause>(parenthesized(Parser<OmpIfClause>{})) ||
     "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
     "IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
@@ -211,12 +217,13 @@ TYPE_PARSER("ALIGNED" >>
         construct<OmpClause>(parenthesized(Parser<OmpProcBindClause>{})) ||
     "REDUCTION" >>
         construct<OmpClause>(parenthesized(Parser<OmpReductionClause>{})) ||
-    "ALLOCATE" >>
-        construct<OmpClause>(parenthesized(Parser<OmpAllocateClause>{})) ||
+    "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
+    "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
     "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
                      parenthesized(scalarIntConstantExpr))) ||
     "SCHEDULE" >>
         construct<OmpClause>(parenthesized(Parser<OmpScheduleClause>{})) ||
+    "SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
     "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
                     parenthesized(Parser<OmpObjectList>{}))) ||
     "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
@@ -384,9 +391,6 @@ TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
             construct<Call>(Parser<ProcedureDesignator>{},
                 parenthesized(optionalList(actualArgSpec))))))
 
-// Hint Expression => HINT(hint-expression)
-TYPE_PARSER("HINT" >> construct<OmpHintExpr>(parenthesized(constantExpr)))
-
 // 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
 //                  ATOMIC [clause]
 //       clause -> memory-order-clause | HINT(hint-expression)
@@ -396,62 +400,34 @@ TYPE_PARSER("HINT" >> construct<OmpHintExpr>(parenthesized(constantExpr)))
 // OMP END ATOMIC
 TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
 
-// Memory order clause
-TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
-    "SEQ_CST" >> pure(llvm::omp::Clause::OMPC_seq_cst) ||
-    "ACQ_REL" >> pure(llvm::omp::Clause::OMPC_acq_rel) ||
-    "RELEASE" >> pure(llvm::omp::Clause::OMPC_release) ||
-    "ACQUIRE" >> pure(llvm::omp::Clause::OMPC_acquire) ||
-    "RELAXED" >> pure(llvm::omp::Clause::OMPC_relaxed))))
-
-// ATOMIC Memory order clause or Hint expression
-TYPE_PARSER(
-    construct<OmpAtomicMemoryOrderClause>(Parser<OmpMemoryOrderClause>{}) ||
-    construct<OmpAtomicMemoryOrderClause>(Parser<OmpHintExpr>{}))
-
-// ATOMIC Memory order Clause List
-TYPE_PARSER(construct<OmpAtomicMemoryOrderClauseList>(
-    many(maybe(","_tok) >> Parser<OmpAtomicMemoryOrderClause>{})))
-
-TYPE_PARSER(construct<OmpAtomicMemoryOrderClausePostList>(
-    many(maybe(","_tok) >> Parser<OmpAtomicMemoryOrderClause>{})))
-
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER("ATOMIC" >>
-    construct<OmpAtomicRead>(
-        Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
-        verbatim("READ"_tok),
-        Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
+    construct<OmpAtomicRead>(Parser<OmpClauseList>{} / maybe(","_tok),
+        verbatim("READ"_tok), Parser<OmpClauseList>{} / endOmpLine,
         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
-TYPE_PARSER(
-    "ATOMIC" >> construct<OmpAtomicCapture>(
-                    Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
-                    verbatim("CAPTURE"_tok),
-                    Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
-                    statement(assignmentStmt), statement(assignmentStmt),
-                    Parser<OmpEndAtomic>{} / endOmpLine))
+TYPE_PARSER("ATOMIC" >>
+    construct<OmpAtomicCapture>(Parser<OmpClauseList>{} / maybe(","_tok),
+        verbatim("CAPTURE"_tok), Parser<OmpClauseList>{} / endOmpLine,
+        statement(assignmentStmt), statement(assignmentStmt),
+        Parser<OmpEndAtomic>{} / endOmpLine))
 
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER("ATOMIC" >>
-    construct<OmpAtomicUpdate>(
-        Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
-        verbatim("UPDATE"_tok),
-        Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
+    construct<OmpAtomicUpdate>(Parser<OmpClauseList>{} / maybe(","_tok),
+        verbatim("UPDATE"_tok), Parser<OmpClauseList>{} / endOmpLine,
         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
-    Parser<OmpAtomicMemoryOrderClauseList>{} / endOmpLine,
-    statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
+    Parser<OmpClauseList>{} / endOmpLine, statement(assignmentStmt),
+    maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
 TYPE_PARSER("ATOMIC" >>
-    construct<OmpAtomicWrite>(
-        Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
-        verbatim("WRITE"_tok),
-        Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
+    construct<OmpAtomicWrite>(Parser<OmpClauseList>{} / maybe(","_tok),
+        verbatim("WRITE"_tok), Parser<OmpClauseList>{} / endOmpLine,
         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // Atomic Construct
@@ -467,7 +443,7 @@ TYPE_PARSER(startOmpLine >>
         verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) /
         endOmpLine)
 TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
-                maybe(parenthesized(name)), maybe(Parser<OmpHintExpr>{}))) /
+                maybe(parenthesized(name)), maybe(Parser<OmpClause>{}))) /
     endOmpLine)
 
 TYPE_PARSER(construct<OpenMPCriticalConstruct>(

diff  --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index b558bee41dbc..2a6b0a6490e4 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2222,36 +2222,10 @@ class UnparseVisitor {
       break;
     }
   }
-  void Unparse(const OmpHintExpr &x) { Word("HINT("), Walk(x.v), Put(')'); }
-  void Unparse(const OmpMemoryOrderClause &x) {
-    switch (x.v) {
-    case llvm::omp::Clause::OMPC_seq_cst:
-      Word("SEQ_CST");
-      break;
-    case llvm::omp::Clause::OMPC_acq_rel:
-      Word("ACQ_REL");
-      break;
-    case llvm::omp::Clause::OMPC_release:
-      Word("RELEASE");
-      break;
-    case llvm::omp::Clause::OMPC_acquire:
-      Word("ACQUIRE");
-      break;
-    case llvm::omp::Clause::OMPC_relaxed:
-      Word("RELAXED");
-      break;
-    default:
-      break;
-    }
-  }
-  void Unparse(const OmpAtomicMemoryOrderClauseList &x) { Walk(" ", x.v, " "); }
-  void Unparse(const OmpAtomicMemoryOrderClausePostList &x) {
-    Walk(" ", x.v, " ");
-  }
   void Unparse(const OmpAtomic &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
-    Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
+    Walk(std::get<OmpClauseList>(x.t));
     Put("\n");
     EndOpenMP();
     Walk(std::get<Statement<AssignmentStmt>>(x.t));
@@ -2262,9 +2236,9 @@ class UnparseVisitor {
   void Unparse(const OmpAtomicCapture &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
-    Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
+    Walk(std::get<0>(x.t));
     Word(" CAPTURE");
-    Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
+    Walk(std::get<2>(x.t));
     Put("\n");
     EndOpenMP();
     Walk(std::get<OmpAtomicCapture::Stmt1>(x.t));
@@ -2277,9 +2251,9 @@ class UnparseVisitor {
   void Unparse(const OmpAtomicRead &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
-    Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
+    Walk(std::get<0>(x.t));
     Word(" READ");
-    Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
+    Walk(std::get<2>(x.t));
     Put("\n");
     EndOpenMP();
     Walk(std::get<Statement<AssignmentStmt>>(x.t));
@@ -2290,9 +2264,9 @@ class UnparseVisitor {
   void Unparse(const OmpAtomicUpdate &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
-    Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
+    Walk(std::get<0>(x.t));
     Word(" UPDATE");
-    Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
+    Walk(std::get<2>(x.t));
     Put("\n");
     EndOpenMP();
     Walk(std::get<Statement<AssignmentStmt>>(x.t));
@@ -2303,9 +2277,9 @@ class UnparseVisitor {
   void Unparse(const OmpAtomicWrite &x) {
     BeginOpenMP();
     Word("!$OMP ATOMIC");
-    Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
+    Walk(std::get<0>(x.t));
     Word(" WRITE");
-    Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
+    Walk(std::get<2>(x.t));
     Put("\n");
     EndOpenMP();
     Walk(std::get<Statement<AssignmentStmt>>(x.t));
@@ -2317,7 +2291,7 @@ class UnparseVisitor {
     BeginOpenMP();
     Word("!$OMP CRITICAL");
     Walk(" (", std::get<std::optional<Name>>(x.t), ")");
-    Walk(std::get<std::optional<OmpHintExpr>>(x.t));
+    Walk(std::get<std::optional<OmpClause>>(x.t));
     Put("\n");
     EndOpenMP();
   }

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 3e360b8ec4ca..c07f43eeed52 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -187,6 +187,15 @@ void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
   dirContext_.pop_back();
 }
 
+void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) {
+  const auto &dir{std::get<parser::OmpCriticalDirective>(x.t)};
+  PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_critical);
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) {
+  dirContext_.pop_back();
+}
+
 void OmpStructureChecker::Enter(
     const parser::OpenMPCancellationPointConstruct &x) {
   const auto &dir{std::get<parser::Verbatim>(x.t)};

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index fbe95d0ee2e0..738ceabb8a22 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -115,6 +115,8 @@ class OmpStructureChecker
   void Leave(const parser::OpenMPCancelConstruct &);
   void Enter(const parser::OpenMPCancellationPointConstruct &);
   void Leave(const parser::OpenMPCancellationPointConstruct &);
+  void Enter(const parser::OpenMPCriticalConstruct &);
+  void Leave(const parser::OpenMPCriticalConstruct &);
 
   void Leave(const parser::OmpClauseList &);
   void Enter(const parser::OmpClause &);

diff  --git a/flang/test/Parser/omp-atomic-unparse.f90 b/flang/test/Parser/omp-atomic-unparse.f90
new file mode 100644
index 000000000000..10d1a61df07c
--- /dev/null
+++ b/flang/test/Parser/omp-atomic-unparse.f90
@@ -0,0 +1,214 @@
+! RUN: %f18 -fdebug-no-semantics -funparse -fopenmp %s | FileCheck %s
+
+program main
+   implicit none
+   integer :: i, j = 10
+!READ
+!$omp atomic read
+   i = j
+!$omp atomic seq_cst read
+   i = j
+!$omp atomic read seq_cst
+   i = j
+!$omp atomic release read
+   i = j
+!$omp atomic read release
+   i = j
+!$omp atomic acq_rel read
+   i = j
+!$omp atomic read acq_rel
+   i = j
+!$omp atomic acquire read
+   i = j
+!$omp atomic read acquire
+   i = j
+!$omp atomic relaxed read
+   i = j
+!$omp atomic read relaxed
+   i = j
+
+! WRITE
+!$omp atomic write
+   i = j
+!$omp atomic seq_cst write
+   i = j
+!$omp atomic write seq_cst
+   i = j
+!$omp atomic release write
+   i = j
+!$omp atomic write release
+   i = j
+!$omp atomic acq_rel write
+   i = j
+!$omp atomic write acq_rel
+   i = j
+!$omp atomic acquire write
+   i = j
+!$omp atomic write acquire
+   i = j
+!$omp atomic relaxed write
+   i = j
+!$omp atomic write relaxed
+   i = j
+
+!UPDATE
+!$omp atomic update
+   i = j
+!$omp atomic seq_cst update
+   i = j
+!$omp atomic update seq_cst
+   i = j
+!$omp atomic release update
+   i = j
+!$omp atomic update release
+   i = j
+!$omp atomic acq_rel update
+   i = j
+!$omp atomic update acq_rel
+   i = j
+!$omp atomic acquire update
+   i = j
+!$omp atomic update acquire
+   i = j
+!$omp atomic relaxed update
+   i = j
+!$omp atomic update relaxed
+   i = j
+
+!CAPTURE
+!$omp atomic capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic seq_cst capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic capture seq_cst
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic release capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic capture release
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic acq_rel capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic capture acq_rel
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic acquire capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic capture acquire
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic relaxed capture
+   i = j
+   i = j
+!$omp end atomic
+!$omp atomic capture relaxed
+   i = j
+   i = j
+!$omp end atomic
+
+!ATOMIC
+!$omp atomic
+   i = j
+!$omp atomic seq_cst
+   i = j
+!$omp atomic release
+   i = j
+!$omp atomic acq_rel
+   i = j
+!$omp atomic acquire
+   i = j
+!$omp atomic relaxed
+   i = j
+
+end program main
+!CHECK-LABEL: PROGRAM main
+
+!READ
+
+!CHECK: !$OMP ATOMIC READ
+!CHECK: !$OMP ATOMIC SEQ_CST READ
+!CHECK: !$OMP ATOMIC READ SEQ_CST
+!CHECK: !$OMP ATOMIC RELEASE READ
+!CHECK: !$OMP ATOMIC READ RELEASE
+!CHECK: !$OMP ATOMIC ACQ_REL READ
+!CHECK: !$OMP ATOMIC READ ACQ_REL
+!CHECK: !$OMP ATOMIC ACQUIRE READ
+!CHECK: !$OMP ATOMIC READ ACQUIRE
+!CHECK: !$OMP ATOMIC RELAXED READ
+!CHECK: !$OMP ATOMIC READ RELAXED
+
+!WRITE
+
+!CHECK: !$OMP ATOMIC WRITE
+!CHECK: !$OMP ATOMIC SEQ_CST WRITE
+!CHECK: !$OMP ATOMIC WRITE SEQ_CST
+!CHECK: !$OMP ATOMIC RELEASE WRITE
+!CHECK: !$OMP ATOMIC WRITE RELEASE
+!CHECK: !$OMP ATOMIC ACQ_REL WRITE
+!CHECK: !$OMP ATOMIC WRITE ACQ_REL
+!CHECK: !$OMP ATOMIC ACQUIRE WRITE
+!CHECK: !$OMP ATOMIC WRITE ACQUIRE
+!CHECK: !$OMP ATOMIC RELAXED WRITE
+!CHECK: !$OMP ATOMIC WRITE RELAXED
+
+!UPDATE
+
+!CHECK: !$OMP ATOMIC UPDATE
+!CHECK: !$OMP ATOMIC SEQ_CST UPDATE
+!CHECK: !$OMP ATOMIC UPDATE SEQ_CST
+!CHECK: !$OMP ATOMIC RELEASE UPDATE
+!CHECK: !$OMP ATOMIC UPDATE RELEASE
+!CHECK: !$OMP ATOMIC ACQ_REL UPDATE
+!CHECK: !$OMP ATOMIC UPDATE ACQ_REL
+!CHECK: !$OMP ATOMIC ACQUIRE UPDATE
+!CHECK: !$OMP ATOMIC UPDATE ACQUIRE
+!CHECK: !$OMP ATOMIC RELAXED UPDATE
+!CHECK: !$OMP ATOMIC UPDATE RELAXED
+
+!CAPTURE
+
+!CHECK: !$OMP ATOMIC CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC SEQ_CST CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC CAPTURE SEQ_CST
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC RELEASE CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC CAPTURE RELEASE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC ACQ_REL CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC CAPTURE ACQ_REL
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC ACQUIRE CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC CAPTURE ACQUIRE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC RELAXED CAPTURE
+!CHECK: !$OMP END ATOMIC
+!CHECK: !$OMP ATOMIC CAPTURE RELAXED
+!CHECK: !$OMP END ATOMIC
+
+!ATOMIC
+!CHECK: !$OMP ATOMIC
+!CHECK: !$OMP ATOMIC SEQ_CST
+!CHECK: !$OMP ATOMIC RELEASE
+!CHECK: !$OMP ATOMIC ACQ_REL
+!CHECK: !$OMP ATOMIC ACQUIRE
+!CHECK: !$OMP ATOMIC RELAXED

diff  --git a/flang/test/Semantics/omp-atomic.f90 b/flang/test/Semantics/omp-atomic.f90
index 8d3f95a77045..6f48f94331d6 100644
--- a/flang/test/Semantics/omp-atomic.f90
+++ b/flang/test/Semantics/omp-atomic.f90
@@ -38,5 +38,12 @@
   !$omp atomic relaxed
   a = a + 1
 
+  !ERROR: expected 'UPDATE'
+  !ERROR: expected 'WRITE'
+  !ERROR: expected 'CAPTURE'
+  !ERROR: expected 'READ'
+  !$omp atomic num_threads write
+  a = a + 1
+
   !$omp end parallel
 end

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index de1651369ebc..7727827835e0 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -181,6 +181,7 @@ def OMPC_NumTasks : Clause<"num_tasks"> {
 }
 def OMPC_Hint : Clause<"hint"> {
   let clangClass = "OMPHintClause";
+  let flangClass = "ConstantExpr";
 }
 def OMPC_DistSchedule : Clause<"dist_schedule"> {
   let clangClass = "OMPDistScheduleClause";


        


More information about the llvm-commits mailing list