[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)
llvm-svn: 213846

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

index 388d57e..13a6dec 100644 (file)
@@ -2441,6 +2441,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
 }
 
 template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
+template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
   for (auto *E : Node->varlists()) {
index c6c2022..5f05b44 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 8de3101..ca66631 100644 (file)
@@ -2463,6 +2463,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
 }
 
 template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
+template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
   for (auto *E : Node->varlists()) {
index dd1621e..878bd9e 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 1fb42d1..d4181b7 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 887f201..1d1b2bc 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 6d6e319..76c7843 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 b125586..7b277b4 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 6c8fd64..4044b11 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 5bbed68..046ef55 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 95b027a..a098b53 100644 (file)
@@ -6789,6 +6789,13 @@ TreeTransform<Derived>::TransformOMPCaptureClause(OMPCaptureClause *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) {
   llvm::SmallVector<Expr *, 16> Vars;
   Vars.reserve(C->varlist_size());
index 90987fe..c4e88f0 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 0ce5dfd..cee94c4 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 31c0892..e75d291 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 66f7c9d..b53133f 100644 (file)
@@ -144,6 +144,41 @@ int capture() {
 }
 
 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();
 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
index e5a438b..57bea99 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())