jyu2 updated this revision to Diff 475013.
jyu2 added a comment.

try fix format again


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137851/new/

https://reviews.llvm.org/D137851

Files:
  clang/include/clang/AST/OpenMPClause.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Basic/OpenMPKinds.def
  clang/include/clang/Basic/OpenMPKinds.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/OpenMPClause.cpp
  clang/lib/AST/StmtProfile.cpp
  clang/lib/Basic/OpenMPKinds.cpp
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/lib/Parse/ParseOpenMP.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/OpenMP/error_ast_print.cpp
  clang/test/OpenMP/error_message.cpp
  clang/tools/libclang/CIndex.cpp
  flang/lib/Semantics/check-omp-structure.cpp
  llvm/include/llvm/Frontend/OpenMP/OMP.td

Index: llvm/include/llvm/Frontend/OpenMP/OMP.td
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -301,6 +301,9 @@
   let clangClass = "OMPAtomicDefaultMemOrderClause";
   let flangClass = "OmpAtomicDefaultMemOrderClause";
 }
+def OMPC_At : Clause<"at"> {
+  let clangClass = "OMPAtClause";
+}
 def OMPC_Allocate : Clause<"allocate"> {
   let clangClass = "OMPAllocateClause";
   let flangClass = "OmpAllocateClause";
@@ -527,7 +530,11 @@
 }
 def OMP_TaskYield : Directive<"taskyield"> {}
 def OMP_Barrier : Directive<"barrier"> {}
-def OMP_Error : Directive<"error"> {}
+def OMP_Error : Directive<"error"> {
+  let allowedClauses = [
+    VersionedClause<OMPC_At>
+  ];
+}
 def OMP_TaskWait : Directive<"taskwait"> {
   let allowedClauses = [
     VersionedClause<OMPC_Depend, 50>
Index: flang/lib/Semantics/check-omp-structure.cpp
===================================================================
--- flang/lib/Semantics/check-omp-structure.cpp
+++ flang/lib/Semantics/check-omp-structure.cpp
@@ -1868,6 +1868,7 @@
 CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
 CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
 CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
+CHECK_SIMPLE_CLAUSE(At, OMPC_at)
 CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
 CHECK_SIMPLE_CLAUSE(When, OMPC_when)
 CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -2443,6 +2443,8 @@
 void OMPClauseEnqueue::VisitOMPAtomicDefaultMemOrderClause(
     const OMPAtomicDefaultMemOrderClause *) {}
 
+void OMPClauseEnqueue::VisitOMPAtClause(const OMPAtClause *) {}
+
 void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
   Visitor->AddStmt(C->getDevice());
 }
Index: clang/test/OpenMP/error_message.cpp
===================================================================
--- clang/test/OpenMP/error_message.cpp
+++ clang/test/OpenMP/error_message.cpp
@@ -7,19 +7,19 @@
   if (argc)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     if (argc) {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
     }
   while (argc)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     while (argc) {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
     }
   do
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     while (argc)
       ;
   do {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
   } while (argc);
   switch (argc)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
@@ -28,47 +28,75 @@
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
   switch (argc)
   case 1: {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
   }
   switch (argc) {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
   case 1:
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
     break;
   default: {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
   } break;
   }
   for (;;)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     for (;;) {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
     }
 label:
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
 label1 : {
-#pragma omp error
+#pragma omp error // expected-error {{ERROR}}
 }
 if (1)
   label2:
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
 
+// expected-error@+1 {{ERROR}}
+#pragma omp error at() // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
+
+// expected-error@+1 {{ERROR}}
+#pragma omp error at(up) // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
+
+// expected-error@+3 {{ERROR}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp error at(up(a)) // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
+
+#pragma omp error at(execution) // no error
+
+#pragma omp error at(compilation) // expected-error {{ERROR}}
   return T();
 }
 
+#pragma omp error at(execution) // expected-error {{unexpected 'execution' modifier in non-executable context}}
+
+#pragma omp error at(compilation) // expected-error {{ERROR}}
+class A {
+
+#pragma omp error at(compilation) // expected-error {{ERROR}}
+
+#pragma omp error at(execution) // expected-error {{unexpected 'execution' modifier in non-executable context}}
+  int A;
+};
+
 int main(int argc, char **argv) {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
   ;
+// expected-error@+1 {{ERROR}}
 #pragma omp error untied  // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp error'}}
-#pragma omp error unknown // expected-warning {{extra tokens at the end of '#pragma omp error' are ignored}}
   if (argc)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     if (argc) {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
     }
   while (argc)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     while (argc) {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
     }
   do
@@ -76,6 +104,7 @@
     while (argc)
       ;
   do {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
   } while (argc);
   switch (argc)
@@ -85,25 +114,32 @@
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
   switch (argc)
   case 1: {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
   }
   switch (argc) {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
   case 1:
+// expected-error@+1 {{ERROR}}
 #pragma omp error
     break;
   default: {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
   } break;
   }
   for (;;)
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     for (;;) {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
     }
 label:
+// expected-error@+1 {{ERROR}}
 #pragma omp error
 label1 : {
+// expected-error@+1 {{ERROR}}
 #pragma omp error
 }
 if (1)
Index: clang/test/OpenMP/error_ast_print.cpp
===================================================================
--- clang/test/OpenMP/error_ast_print.cpp
+++ clang/test/OpenMP/error_ast_print.cpp
@@ -13,16 +13,16 @@
 void foo() {}
 // CHECK: template <typename T, int N> int tmain(T argc, char **argv)
 // CHECK: static int a;
-// CHECK-NEXT: #pragma omp error
+// CHECK-NEXT: #pragma omp error at(execution)
 // CHECK-NEXT: a = argv[0][0];
 // CHECK-NEXT: ++a;
-// CHECK-NEXT: #pragma omp error
+// CHECK-NEXT: #pragma omp error at(execution)
 // CHECK-NEXT: {
 // CHECK-NEXT: int b = 10;
 // CHECK-NEXT: T c = 100;
 // CHECK-NEXT: a = b + c;
 // CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp error
+// CHECK-NEXT: #pragma omp error at(execution)
 // CHECK-NEXT: foo();
 // CHECK-NEXT: return N;
 
@@ -30,16 +30,16 @@
 int tmain(T argc, char **argv) {
   T b = argc, c, d, e, f, g;
   static int a;
-#pragma omp error
+#pragma omp error at(execution)
   a = argv[0][0];
   ++a;
-#pragma omp error
+#pragma omp error at(execution)
   {
     int b = 10;
     T c = 100;
     a = b + c;
   }
-#pragma omp  error
+#pragma omp  error at(execution)
   foo();
 return N;
 }
@@ -47,16 +47,16 @@
 // CHECK: int main(int argc, char **argv)
 // CHECK-NEXT: int b = argc, c, d, e, f, g;
 // CHECK-NEXT: static int a;
-// CHECK-NEXT: #pragma omp error
+// CHECK-NEXT: #pragma omp error at(execution)
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp error
+// CHECK-NEXT: #pragma omp error at(execution)
 // CHECK-NEXT: foo();
 int main (int argc, char **argv) {
   int b = argc, c, d, e, f, g;
   static int a;
-#pragma omp error
+#pragma omp error at(execution)
    a=2;
-#pragma omp error
+#pragma omp error at(execution)
   foo();
 }
 #endif
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -6982,6 +6982,12 @@
   Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());
 }
 
+void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) {
+  Record.push_back(C->getAtKind());
+  Record.AddSourceLocation(C->getLParenLoc());
+  Record.AddSourceLocation(C->getAtKindKwLoc());
+}
+
 void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) {
   Record.push_back(C->varlist_size());
   Record.AddSourceLocation(C->getLParenLoc());
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -9934,7 +9934,10 @@
   case llvm::omp::OMPC_atomic_default_mem_order:
     C = new (Context) OMPAtomicDefaultMemOrderClause();
     break;
- case llvm::omp::OMPC_private:
+  case llvm::omp::OMPC_at:
+    C = new (Context) OMPAtClause();
+    break;
+  case llvm::omp::OMPC_private:
     C = OMPPrivateClause::CreateEmpty(Context, Record.readInt());
     break;
   case llvm::omp::OMPC_firstprivate:
@@ -10336,6 +10339,12 @@
   C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation());
 }
 
+void OMPClauseReader::VisitOMPAtClause(OMPAtClause *C) {
+  C->setAtKind(static_cast<OpenMPAtClauseKind>(Record.readInt()));
+  C->setLParenLoc(Record.readSourceLocation());
+  C->setAtKindKwLoc(Record.readSourceLocation());
+}
+
 void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
   C->setLParenLoc(Record.readSourceLocation());
   unsigned NumVars = C->varlist_size();
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -2351,6 +2351,17 @@
     return getSema().ActOnOpenMPAlignClause(A, StartLoc, LParenLoc, EndLoc);
   }
 
+  /// Build a new OpenMP 'at' clause.
+  ///
+  /// By default, performs semantic analysis to build the new OpenMP clause.
+  /// Subclasses may override this routine to provide different behavior.
+  OMPClause *RebuildOMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KwLoc,
+                                SourceLocation StartLoc,
+                                SourceLocation LParenLoc,
+                                SourceLocation EndLoc) {
+    return getSema().ActOnOpenMPAtClause(Kind, KwLoc, StartLoc, LParenLoc,
+                                         EndLoc);
+  }
   /// Rebuild the operand to an Objective-C \@synchronized statement.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -9855,6 +9866,13 @@
       "atomic_default_mem_order clause cannot appear in dependent context");
 }
 
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPAtClause(OMPAtClause *C) {
+  return getDerived().RebuildOMPAtClause(C->getAtKind(), C->getAtKindKwLoc(),
+                                         C->getBeginLoc(), C->getLParenLoc(),
+                                         C->getEndLoc());
+}
+
 template <typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -6308,7 +6308,7 @@
     break;
   case OMPD_error:
     assert(AStmt == nullptr &&
-           "No associated statement allowed for 'omp taskyield' directive");
+           "No associated statement allowed for 'omp error' directive");
     Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
     break;
   case OMPD_barrier:
@@ -6719,6 +6719,7 @@
       case OMPC_device_type:
       case OMPC_match:
       case OMPC_when:
+      case OMPC_at:
       default:
         llvm_unreachable("Unexpected clause");
       }
@@ -11029,6 +11030,15 @@
 StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
                                            SourceLocation StartLoc,
                                            SourceLocation EndLoc) {
+  const OMPAtClause *AtC = nullptr;
+  for (auto *AC :
+       OMPExecutableDirective::getClausesOfKind<OMPAtClause>(Clauses))
+    AtC = AC;
+  if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
+    Diag(AtC ? AtC->getBeginLoc() : StartLoc, diag::err_diagnose_if_succeeded)
+        << "ERROR";
+    return StmtError();
+  }
   return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
 }
 
@@ -15171,6 +15181,7 @@
   case OMPC_match:
   case OMPC_nontemporal:
   case OMPC_order:
+  case OMPC_at:
   case OMPC_destroy:
   case OMPC_inclusive:
   case OMPC_exclusive:
@@ -16096,6 +16107,7 @@
   case OMPC_match:
   case OMPC_nontemporal:
   case OMPC_order:
+  case OMPC_at:
   case OMPC_destroy:
   case OMPC_detach:
   case OMPC_inclusive:
@@ -16498,6 +16510,10 @@
     Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
                                 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
     break;
+  case OMPC_at:
+    Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
+                              ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+    break;
   case OMPC_if:
   case OMPC_final:
   case OMPC_num_threads:
@@ -16676,6 +16692,22 @@
                                                       LParenLoc, EndLoc);
 }
 
+OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
+                                     SourceLocation KindKwLoc,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc) {
+  if (Kind == OMPC_AT_unknown) {
+    Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+        << getListOfPossibleValues(OMPC_at, /*First=*/0,
+                                   /*Last=*/OMPC_AT_unknown)
+        << getOpenMPClauseName(OMPC_at);
+    return nullptr;
+  }
+  return new (Context)
+      OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
+}
+
 OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind,
                                         SourceLocation KindKwLoc,
                                         SourceLocation StartLoc,
@@ -16875,6 +16907,7 @@
   case OMPC_match:
   case OMPC_nontemporal:
   case OMPC_order:
+  case OMPC_at:
   case OMPC_destroy:
   case OMPC_novariants:
   case OMPC_nocontext:
@@ -17131,6 +17164,7 @@
   case OMPC_match:
   case OMPC_nontemporal:
   case OMPC_order:
+  case OMPC_at:
   case OMPC_novariants:
   case OMPC_nocontext:
   case OMPC_detach:
@@ -17685,6 +17719,7 @@
   case OMPC_device_type:
   case OMPC_match:
   case OMPC_order:
+  case OMPC_at:
   case OMPC_destroy:
   case OMPC_novariants:
   case OMPC_nocontext:
Index: clang/lib/Parse/ParseOpenMP.cpp
===================================================================
--- clang/lib/Parse/ParseOpenMP.cpp
+++ clang/lib/Parse/ParseOpenMP.cpp
@@ -1627,6 +1627,45 @@
   return false;
 }
 
+/// <clause> [clause[ [,] clause] ... ]
+///
+///  clauses: for error directive
+///     'at' '(' compilation | execution ')'
+///     'severity' '(' fatal | warning ')'
+///     'message' '(' msg-string ')'
+/// ....
+void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
+                                SmallVector<clang::OMPClause *, 1> *Clauses,
+                                SourceLocation Loc) {
+  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
+              llvm::omp::Clause_enumSize + 1>
+      FirstClauses(llvm::omp::Clause_enumSize + 1);
+  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+    OpenMPClauseKind CKind = Tok.isAnnotation()
+                                 ? OMPC_unknown
+                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
+    Actions.StartOpenMPClause(CKind);
+    OMPClause *Clause = ParseOpenMPClause(
+        DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
+    SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
+              StopBeforeMatch);
+    FirstClauses[unsigned(CKind)].setInt(true);
+    if (Clause != nullptr)
+      Clauses->push_back(Clause);
+    OMPAtClause *AtC = CKind == OMPC_at ? cast<OMPAtClause>(Clause) : nullptr;
+    if (CKind == OMPC_at && AtC->getAtKind() == OMPC_AT_execution)
+      Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
+    if (Tok.is(tok::annot_pragma_openmp_end)) {
+      Actions.EndOpenMPClause();
+      break;
+    }
+    // Skip ',' if any.
+    if (Tok.is(tok::comma))
+      ConsumeToken();
+    Actions.EndOpenMPClause();
+  }
+}
+
 /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
 /// where
 ///
@@ -2124,6 +2163,13 @@
     ConsumeAnnotationToken();
     return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
   }
+  case OMPD_error: {
+    SmallVector<OMPClause *, 1> Clauses;
+    SourceLocation StartLoc = ConsumeToken();
+    ParseOpenMPClauses(DKind, &Clauses, StartLoc);
+    Actions.ActOnOpenMPErrorDirective(Clauses, StartLoc, SourceLocation());
+    break;
+  }
   case OMPD_assumes:
   case OMPD_begin_assumes:
     ParseOpenMPAssumesDirective(DKind, ConsumeToken());
@@ -2310,7 +2356,6 @@
   case OMPD_unroll:
   case OMPD_task:
   case OMPD_taskyield:
-  case OMPD_error:
   case OMPD_barrier:
   case OMPD_taskwait:
   case OMPD_taskgroup:
@@ -2711,6 +2756,10 @@
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
           << getOpenMPDirectiveName(DKind) << 0;
+      if (DKind == OMPD_error) {
+        SkipUntil(tok::annot_pragma_openmp_end);
+        break;
+      }
     }
     HasAssociatedStatement = false;
     // Fall through for further analysis.
@@ -3170,6 +3219,7 @@
   case OMPC_default:
   case OMPC_proc_bind:
   case OMPC_atomic_default_mem_order:
+  case OMPC_at:
   case OMPC_order:
   case OMPC_bind:
     // OpenMP [2.14.3.1, Restrictions]
@@ -3180,6 +3230,8 @@
     // OpenMP [5.0, Requires directive, Restrictions]
     //  At most one atomic_default_mem_order clause can appear
     //  on the directive
+    // OpenMP [5.1, Requires directive, Restrictions]
+    //  At most one at clause can appear on the directive
     // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
     // At most one bind clause can appear on a loop directive.
     if (!FirstClause && CKind != OMPC_order) {
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -6512,6 +6512,7 @@
   case OMPC_reverse_offload:
   case OMPC_dynamic_allocators:
   case OMPC_atomic_default_mem_order:
+  case OMPC_at:
   case OMPC_device_type:
   case OMPC_match:
   case OMPC_nontemporal:
Index: clang/lib/Basic/OpenMPKinds.cpp
===================================================================
--- clang/lib/Basic/OpenMPKinds.cpp
+++ clang/lib/Basic/OpenMPKinds.cpp
@@ -104,6 +104,11 @@
 #define OPENMP_DEVICE_TYPE_KIND(Name) .Case(#Name, OMPC_DEVICE_TYPE_##Name)
 #include "clang/Basic/OpenMPKinds.def"
         .Default(OMPC_DEVICE_TYPE_unknown);
+  case OMPC_at:
+    return llvm::StringSwitch<OpenMPAtClauseKind>(Str)
+#define OPENMP_AT_KIND(Name) .Case(#Name, OMPC_AT_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+        .Default(OMPC_AT_unknown);
   case OMPC_lastprivate:
     return llvm::StringSwitch<OpenMPLastprivateModifier>(Str)
 #define OPENMP_LASTPRIVATE_KIND(Name) .Case(#Name, OMPC_LASTPRIVATE_##Name)
@@ -336,6 +341,17 @@
 #include "clang/Basic/OpenMPKinds.def"
     }
     llvm_unreachable("Invalid OpenMP 'device_type' clause type");
+  case OMPC_at:
+    switch (Type) {
+    case OMPC_AT_unknown:
+      return "unknown";
+#define OPENMP_AT_KIND(Name)                                                   \
+  case OMPC_AT_##Name:                                                         \
+    return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+    }
+    llvm_unreachable("Invalid OpenMP 'at' clause type");
+    llvm_unreachable("Invalid OpenMP 'at' clause type");
   case OMPC_lastprivate:
     switch (Type) {
     case OMPC_LASTPRIVATE_unknown:
Index: clang/lib/AST/StmtProfile.cpp
===================================================================
--- clang/lib/AST/StmtProfile.cpp
+++ clang/lib/AST/StmtProfile.cpp
@@ -530,6 +530,8 @@
 void OMPClauseProfiler::VisitOMPAtomicDefaultMemOrderClause(
     const OMPAtomicDefaultMemOrderClause *C) {}
 
+void OMPClauseProfiler::VisitOMPAtClause(const OMPAtClause *C) {}
+
 void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
   VistOMPClauseWithPreInit(C);
   if (auto *S = C->getChunkSize())
Index: clang/lib/AST/OpenMPClause.cpp
===================================================================
--- clang/lib/AST/OpenMPClause.cpp
+++ clang/lib/AST/OpenMPClause.cpp
@@ -152,6 +152,7 @@
   case OMPC_reverse_offload:
   case OMPC_dynamic_allocators:
   case OMPC_atomic_default_mem_order:
+  case OMPC_at:
   case OMPC_device_type:
   case OMPC_match:
   case OMPC_nontemporal:
@@ -251,6 +252,7 @@
   case OMPC_reverse_offload:
   case OMPC_dynamic_allocators:
   case OMPC_atomic_default_mem_order:
+  case OMPC_at:
   case OMPC_device_type:
   case OMPC_match:
   case OMPC_nontemporal:
@@ -1781,6 +1783,11 @@
      << ")";
 }
 
+void OMPClausePrinter::VisitOMPAtClause(OMPAtClause *Node) {
+  OS << "at(" << getOpenMPSimpleClauseTypeName(OMPC_at, Node->getAtKind())
+     << ")";
+}
+
 void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
   OS << "schedule(";
   if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11826,6 +11826,13 @@
       OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
       SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
 
+  /// Called on well-formed 'at' clause.
+  OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
+                                 SourceLocation KindLoc,
+                                 SourceLocation StartLoc,
+                                 SourceLocation LParenLoc,
+                                 SourceLocation EndLoc);
+
   /// Data used for processing a list of variables in OpenMP clauses.
   struct OpenMPVarListDataTy final {
     Expr *DepModOrTailExpr = nullptr;
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -3293,6 +3293,15 @@
   /// Parse 'omp end assumes' directive.
   void ParseOpenMPEndAssumesDirective(SourceLocation Loc);
 
+  /// Parses clauses for directive.
+  ///
+  /// \param DKind Kind of current directive.
+  /// \param clauses for current directive.
+  /// \param start location for clauses of current directive
+  void ParseOpenMPClauses(OpenMPDirectiveKind DKind,
+                          SmallVector<clang::OMPClause *, 1> *Clauses,
+                          SourceLocation Loc);
+
   /// Parse clauses for '#pragma omp [begin] declare target'.
   void ParseOMPDeclareTargetClauses(Sema::DeclareTargetContextInfo &DTCI);
 
Index: clang/include/clang/Basic/OpenMPKinds.h
===================================================================
--- clang/include/clang/Basic/OpenMPKinds.h
+++ clang/include/clang/Basic/OpenMPKinds.h
@@ -131,6 +131,13 @@
   OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
 };
 
+/// OpenMP attributes for 'at' clause.
+enum OpenMPAtClauseKind {
+#define OPENMP_AT_KIND(Name) OMPC_AT_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_AT_unknown
+};
+
 /// OpenMP device type for 'device_type' clause.
 enum OpenMPDeviceType {
 #define OPENMP_DEVICE_TYPE_KIND(Name) \
Index: clang/include/clang/Basic/OpenMPKinds.def
===================================================================
--- clang/include/clang/Basic/OpenMPKinds.def
+++ clang/include/clang/Basic/OpenMPKinds.def
@@ -41,6 +41,9 @@
 #ifndef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
 #define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name)
 #endif
+#ifndef OPENMP_AT_KIND
+#define OPENMP_AT_KIND(Name)
+#endif
 #ifndef OPENMP_DEFAULTMAP_MODIFIER
 #define OPENMP_DEFAULTMAP_MODIFIER(Name)
 #endif
@@ -119,6 +122,10 @@
 OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(acq_rel)
 OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(relaxed)
 
+// Modifiers for 'at' clause.
+OPENMP_AT_KIND(compilation)
+OPENMP_AT_KIND(execution)
+
 // Map types for 'map' clause.
 OPENMP_MAP_KIND(alloc)
 OPENMP_MAP_KIND(to)
@@ -179,6 +186,7 @@
 #undef OPENMP_SCHEDULE_MODIFIER
 #undef OPENMP_SCHEDULE_KIND
 #undef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
+#undef OPENMP_AT_KIND
 #undef OPENMP_MAP_KIND
 #undef OPENMP_MAP_MODIFIER_KIND
 #undef OPENMP_MOTION_MODIFIER_KIND
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1401,6 +1401,8 @@
   "expected declarator on 'omp declare mapper' directive">;
 def err_omp_unexpected_append_op : Error<
   "unexpected operation specified in 'append_args' clause, expected 'interop'">;
+def err_omp_unexpected_execution_modifier : Error<
+  "unexpected 'execution' modifier in non-executable context">;
 def err_omp_declare_variant_wrong_clause : Error<
   "expected %select{'match'|'match', 'adjust_args', or 'append_args'}0 clause "
   "on 'omp declare variant' directive">;
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3310,6 +3310,11 @@
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPAtClause(OMPAtClause *) {
+  return true;
+}
+
 template <typename Derived>
 bool
 RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
Index: clang/include/clang/AST/OpenMPClause.h
===================================================================
--- clang/include/clang/AST/OpenMPClause.h
+++ clang/include/clang/AST/OpenMPClause.h
@@ -1563,6 +1563,85 @@
   }
 };
 
+/// This represents 'at' clause in the '#pragma omp error' directive
+///
+/// \code
+/// #pragma omp error at(compilation)
+/// \endcode
+/// In this example directive '#pragma omp error' has simple
+/// 'at' clause with kind 'complilation'.
+class OMPAtClause final : public OMPClause {
+  friend class OMPClauseReader;
+
+  /// Location of '('
+  SourceLocation LParenLoc;
+
+  /// A kind of the 'at' clause.
+  OpenMPAtClauseKind Kind = OMPC_AT_unknown;
+
+  /// Start location of the kind in source code.
+  SourceLocation KindKwLoc;
+
+  /// Set kind of the clause.
+  ///
+  /// \param K Kind of clause.
+  void setAtKind(OpenMPAtClauseKind K) { Kind = K; }
+
+  /// Set clause kind location.
+  ///
+  /// \param KLoc Kind location.
+  void setAtKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+
+  /// Sets the location of '('.
+  void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+public:
+  /// Build 'at' clause with argument \a A ('compilation' or 'execution').
+  ///
+  /// \param A Argument of the clause ('compilation' or 'execution').
+  /// \param ALoc Starting location of the argument.
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  OMPAtClause(OpenMPAtClauseKind A, SourceLocation ALoc,
+              SourceLocation StartLoc, SourceLocation LParenLoc,
+              SourceLocation EndLoc)
+      : OMPClause(llvm::omp::OMPC_at, StartLoc, EndLoc), LParenLoc(LParenLoc),
+        Kind(A), KindKwLoc(ALoc) {}
+
+  /// Build an empty clause.
+  OMPAtClause()
+      : OMPClause(llvm::omp::OMPC_at, SourceLocation(), SourceLocation()) {}
+
+  /// Returns the locaiton of '('.
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+
+  /// Returns kind of the clause.
+  OpenMPAtClauseKind getAtKind() const { return Kind; }
+
+  /// Returns location of clause kind.
+  SourceLocation getAtKindKwLoc() const { return KindKwLoc; }
+
+  child_range children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+
+  const_child_range children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  child_range used_children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+  const_child_range used_children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == llvm::omp::OMPC_at;
+  }
+};
+
 /// This represents 'schedule' clause in the '#pragma omp ...' directive.
 ///
 /// \code
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to