]> granicus.if.org Git - clang/commitdiff
[OPENMP] Initial parsing and sema analysis for clause 'seq_cst' of 'atomic' directive.
authorAlexey Bataev <a.bataev@hotmail.com>
Thu, 24 Jul 2014 08:55:34 +0000 (08:55 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Thu, 24 Jul 2014 08:55:34 +0000 (08:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213846 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/OpenMPClause.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/OpenMPKinds.def
include/clang/Sema/Sema.h
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Basic/OpenMPKinds.cpp
lib/Parse/ParseOpenMP.cpp
lib/Sema/SemaOpenMP.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/OpenMP/atomic_ast_print.cpp
test/OpenMP/atomic_messages.cpp
tools/libclang/CIndex.cpp

index 388d57e9255a876a3462500ad29df9939e27dd88..13a6dec7590a14a187344c44e85faefa3de62409 100644 (file)
@@ -2440,6 +2440,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
 template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index c6c2022b4ad8028f1465706166ef771b4bf2e3c1..5f05b449deba58947525ddd5a4c8f4d6bb5d32b0 100644 (file)
@@ -887,6 +887,36 @@ public:
   StmtRange children() { return StmtRange(); }
 };
 
+/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic seq_cst
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
+///
+class OMPSeqCstClause : public OMPClause {
+public:
+  /// \brief Build 'seq_cst' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPSeqCstClause()
+      : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_seq_cst;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
 /// \brief This represents clause 'private' in the '#pragma omp ...' directives.
 ///
 /// \code
index 8de3101df5e8c68962fc652298a533095201a0b2..ca66631c9bc4aed16378e54c5578ac1fd68abf63 100644 (file)
@@ -2462,6 +2462,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
 template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index dd1621eae021fd6cc61d105a7ff578f1f0dd5633..878bd9e4e6d9e75415dde06af50e14b0f86811cd 100644 (file)
@@ -105,6 +105,7 @@ OPENMP_CLAUSE(read, OMPReadClause)
 OPENMP_CLAUSE(write, OMPWriteClause)
 OPENMP_CLAUSE(update, OMPUpdateClause)
 OPENMP_CLAUSE(capture, OMPCaptureClause)
+OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
 
 // Clauses allowed for OpenMP directive 'parallel'.
 OPENMP_PARALLEL_CLAUSE(if)
@@ -202,11 +203,12 @@ OPENMP_TASK_CLAUSE(shared)
 OPENMP_TASK_CLAUSE(untied)
 OPENMP_TASK_CLAUSE(mergeable)
 
-// TODO More clauses allowed for OpenMP directive 'atomic'.
+// Clauses allowed for OpenMP directive 'atomic'.
 OPENMP_ATOMIC_CLAUSE(read)
 OPENMP_ATOMIC_CLAUSE(write)
 OPENMP_ATOMIC_CLAUSE(update)
 OPENMP_ATOMIC_CLAUSE(capture)
+OPENMP_ATOMIC_CLAUSE(seq_cst)
 
 #undef OPENMP_SCHEDULE_KIND
 #undef OPENMP_PROC_BIND_KIND
index 1fb42d1670cd3778cffd306dd44806e02b0f8979..d4181b7edd7146687edae1e3cab15d416eb3349b 100644 (file)
@@ -7494,6 +7494,9 @@ public:
   /// \brief Called on well-formed 'capture' clause.
   OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc,
                                       SourceLocation EndLoc);
+  /// \brief Called on well-formed 'seq_cst' clause.
+  OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
 
   OMPClause *
   ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars,
index 887f201742410a9c662e3627126cc4e25f222db2..1d1b2bca79a6eb8b1bb653900f138f95811c06d6 100644 (file)
@@ -677,6 +677,10 @@ void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
   OS << "capture";
 }
 
+void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  OS << "seq_cst";
+}
+
 template<typename T>
 void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
   for (typename T::varlist_iterator I = Node->varlist_begin(),
index 6d6e319bd344dc335a138468d275c1ed209b8adf..76c7843481a0856f85492a24e09aa0803395de82 100644 (file)
@@ -318,6 +318,8 @@ void OMPClauseProfiler::VisitOMPUpdateClause(const OMPUpdateClause *) {}
 
 void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {}
 
+void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+
 template<typename T>
 void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
   for (auto *I : Node->varlists())
index b125586ed1adca41719940871591f195bf59be21..7b277b477d5b09fbd6e92beeb1b8b56b1fdccfa9 100644 (file)
@@ -112,6 +112,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -175,6 +176,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");
index 6c8fd640f97fb2f0cebcde2b626247a06ed839a1..4044b112c82bfc198f7191954c22bbe4b6d7fc75 100644 (file)
@@ -343,7 +343,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
 ///       lastprivate-clause | reduction-clause | proc_bind-clause |
 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
 ///       mergeable-clause | flush-clause | read-clause | write-clause |
-///       update-clause | capture-clause
+///       update-clause | capture-clause | seq_cst-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -413,6 +413,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
     // OpenMP [2.7.1, Restrictions, p. 9]
     //  Only one ordered clause can appear on a loop directive.
     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
index 5bbed6801130eaeaa002359f61ab487993a4dbc7..046ef55254c4677bf9b6918e1843054637acb451 100644 (file)
@@ -2485,6 +2485,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -2691,6 +2692,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -2810,6 +2812,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -2901,6 +2904,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
   case OMPC_capture:
     Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
     break;
+  case OMPC_seq_cst:
+    Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
+    break;
   case OMPC_if:
   case OMPC_final:
   case OMPC_num_threads:
@@ -2967,6 +2973,11 @@ OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
   return new (Context) OMPCaptureClause(StartLoc, EndLoc);
 }
 
+OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+                                         SourceLocation EndLoc) {
+  return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
+}
+
 OMPClause *Sema::ActOnOpenMPVarListClause(
     OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
@@ -3024,6 +3035,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
   case OMPC_write:
   case OMPC_update:
   case OMPC_capture:
+  case OMPC_seq_cst:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
index 95b027a71c844baee3d0974b8c97fcfb400db485..a098b537becdb249657a1d6cdb1b956847b270d6 100644 (file)
@@ -6787,6 +6787,13 @@ TreeTransform<Derived>::TransformOMPCaptureClause(OMPCaptureClause *C) {
   return C;
 }
 
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
+  // No need to rebuild this clause, no template-dependent parameters.
+  return C;
+}
+
 template <typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
index 90987fe7ae9a891e7d2ddeebdd121869308e8389..c4e88f0f18d35645b0673909e0bff173bb9f8cfa 100644 (file)
@@ -1727,6 +1727,9 @@ OMPClause *OMPClauseReader::readClause() {
   case OMPC_capture:
     C = new (Context) OMPCaptureClause();
     break;
+  case OMPC_seq_cst:
+    C = new (Context) OMPSeqCstClause();
+    break;
   case OMPC_private:
     C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
     break;
@@ -1829,6 +1832,8 @@ void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {}
 
 void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
 
+void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
 void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
   unsigned NumVars = C->varlist_size();
index 0ce5dfde832c0979589d3c6483be02e96347f6ad..cee94c401c11389d58954877be9aef1b1b52c9ec 100644 (file)
@@ -1743,6 +1743,8 @@ void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {}
 
 void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}
 
+void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
 void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
   Record.push_back(C->varlist_size());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
index 31c08920136eea1082872fb1abc6767837a0e3e1..e75d291eab5109d8745a081b9f8116bd5e38610a 100644 (file)
@@ -25,6 +25,21 @@ T foo(T argc) {
     a = b;
     b++;
   }
+#pragma omp atomic seq_cst
+  a++;
+#pragma omp atomic read seq_cst
+  a = argc;
+#pragma omp atomic seq_cst write
+  a = argc + argc;
+#pragma omp atomic update seq_cst
+  a = a + argc;
+#pragma omp atomic seq_cst capture
+  a = b++;
+#pragma omp atomic capture seq_cst
+  {
+    a = b;
+    b++;
+  }
   return T();
 }
 
@@ -44,6 +59,21 @@ T foo(T argc) {
 // CHECK-NEXT: a = b;
 // CHECK-NEXT: b++;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp atomic seq_cst
+// CHECK-NEXT: a++;
+// CHECK-NEXT: #pragma omp atomic read seq_cst
+// CHECK-NEXT: a = argc;
+// CHECK-NEXT: #pragma omp atomic seq_cst write
+// CHECK-NEXT: a = argc + argc;
+// CHECK-NEXT: #pragma omp atomic update seq_cst
+// CHECK-NEXT: a = a + argc;
+// CHECK-NEXT: #pragma omp atomic seq_cst capture
+// CHECK-NEXT: a = b++;
+// CHECK-NEXT: #pragma omp atomic capture seq_cst
+// CHECK-NEXT: {
+// CHECK-NEXT: a = b;
+// CHECK-NEXT: b++;
+// CHECK-NEXT: }
 // CHECK: T a = T();
 // CHECK-NEXT: #pragma omp atomic
 // CHECK-NEXT: a++;
@@ -60,6 +90,21 @@ T foo(T argc) {
 // CHECK-NEXT: a = b;
 // CHECK-NEXT: b++;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp atomic seq_cst
+// CHECK-NEXT: a++;
+// CHECK-NEXT: #pragma omp atomic read seq_cst
+// CHECK-NEXT: a = argc;
+// CHECK-NEXT: #pragma omp atomic seq_cst write
+// CHECK-NEXT: a = argc + argc;
+// CHECK-NEXT: #pragma omp atomic update seq_cst
+// CHECK-NEXT: a = a + argc;
+// CHECK-NEXT: #pragma omp atomic seq_cst capture
+// CHECK-NEXT: a = b++;
+// CHECK-NEXT: #pragma omp atomic capture seq_cst
+// CHECK-NEXT: {
+// CHECK-NEXT: a = b;
+// CHECK-NEXT: b++;
+// CHECK-NEXT: }
 
 int main(int argc, char **argv) {
   int b = 0;
@@ -80,6 +125,21 @@ int main(int argc, char **argv) {
     a = b;
     b++;
   }
+#pragma omp atomic seq_cst
+  a++;
+#pragma omp atomic read seq_cst
+  a = argc;
+#pragma omp atomic seq_cst write
+  a = argc + argc;
+#pragma omp atomic update seq_cst
+  a = a + argc;
+#pragma omp atomic seq_cst capture
+  a = b++;
+#pragma omp atomic capture seq_cst
+  {
+    a = b;
+    b++;
+  }
   // CHECK-NEXT: #pragma omp atomic
   // CHECK-NEXT: a++;
   // CHECK-NEXT: #pragma omp atomic read
@@ -95,6 +155,21 @@ int main(int argc, char **argv) {
   // CHECK-NEXT: a = b;
   // CHECK-NEXT: b++;
   // CHECK-NEXT: }
+  // CHECK-NEXT: #pragma omp atomic seq_cst
+  // CHECK-NEXT: a++;
+  // CHECK-NEXT: #pragma omp atomic read seq_cst
+  // CHECK-NEXT: a = argc;
+  // CHECK-NEXT: #pragma omp atomic seq_cst write
+  // CHECK-NEXT: a = argc + argc;
+  // CHECK-NEXT: #pragma omp atomic update seq_cst
+  // CHECK-NEXT: a = a + argc;
+  // CHECK-NEXT: #pragma omp atomic seq_cst capture
+  // CHECK-NEXT: a = b++;
+  // CHECK-NEXT: #pragma omp atomic capture seq_cst
+  // CHECK-NEXT: {
+  // CHECK-NEXT: a = b;
+  // CHECK-NEXT: b++;
+  // CHECK-NEXT: }
   return foo(a);
 }
 
index 66f7c9db64be2b6aa42a2fc3fb9013297db6f863..b53133f35240e4d399e18d7f9f75af04f7ae6465 100644 (file)
@@ -143,6 +143,41 @@ int capture() {
   return capture<int>();
 }
 
+template <class T>
+T seq_cst() {
+  T a, b = 0;
+// Test for atomic seq_cst
+#pragma omp atomic seq_cst
+  // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  ;
+// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
+#pragma omp atomic seq_cst seq_cst
+  a += b;
+
+#pragma omp atomic update seq_cst
+  // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  ;
+
+  return T();
+}
+
+int seq_cst() {
+  int a, b = 0;
+// Test for atomic seq_cst
+#pragma omp atomic seq_cst
+  // expected-error@+1 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  ;
+// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
+#pragma omp atomic seq_cst seq_cst
+  a += b;
+
+#pragma omp atomic update seq_cst
+  // expected-error@+1 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  ;
+
+ return seq_cst<int>();
+}
+
 template <class T>
 T mixed() {
   T a, b = T();
index e5a438bd302ddef600a80eed1b17833a52648ce2..57bea9927dbcef2620f641bf6f7a72ce0df1c264 100644 (file)
@@ -1989,6 +1989,8 @@ void OMPClauseEnqueue::VisitOMPUpdateClause(const OMPUpdateClause *) {}
 
 void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {}
 
+void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+
 template<typename T>
 void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
   for (const auto *I : Node->varlists())