]> granicus.if.org Git - clang/commitdiff
[OPENMP] 'proc_bind' clause support - Parsing and sema analysis for OpenMP clause...
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 6 May 2014 06:04:14 +0000 (06:04 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 6 May 2014 06:04:14 +0000 (06:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208060 91177308-0d34-0410-b5e6-96231b3b80d8

17 files changed:
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/OpenMPClause.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/OpenMPKinds.def
include/clang/Basic/OpenMPKinds.h
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/parallel_ast_print.cpp
test/OpenMP/parallel_proc_bind_messages.cpp [new file with mode: 0644]
tools/libclang/CIndex.cpp

index c44a47f33e6b9503c338500ff5be3110aaa4665f..b515b6e04ab184cca4faf34c6be5142ee2451799 100644 (file)
@@ -2379,6 +2379,12 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C
   return true;
 }
 
+template<typename Derived>
+bool
+DataRecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
+  return true;
+}
+
 template<typename Derived>
 template<typename T>
 void DataRecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index f91b491b8f15a016607c19b796ab52f0589a3a71..392eb9a281ddc06a1a5641e4e138bf28265e2438 100644 (file)
@@ -375,6 +375,76 @@ public:
   StmtRange children() { return StmtRange(); }
 };
 
+/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp parallel proc_bind(master)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'proc_bind'
+/// clause with kind 'master'.
+///
+class OMPProcBindClause : public OMPClause {
+  friend class OMPClauseReader;
+  /// \brief Location of '('.
+  SourceLocation LParenLoc;
+  /// \brief A kind of the 'proc_bind' clause.
+  OpenMPProcBindClauseKind Kind;
+  /// \brief Start location of the kind in source code.
+  SourceLocation KindKwLoc;
+
+  /// \brief Set kind of the clause.
+  ///
+  /// \param K Kind of clause.
+  ///
+  void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
+
+  /// \brief Set clause kind location.
+  ///
+  /// \param KLoc Kind location.
+  ///
+  void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+
+public:
+  /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or
+  ///        'spread').
+  ///
+  /// \param A Argument of the clause ('master', 'close' or 'spread').
+  /// \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.
+  ///
+  OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
+                   SourceLocation StartLoc, SourceLocation LParenLoc,
+                   SourceLocation EndLoc)
+      : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
+        Kind(A), KindKwLoc(ALoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPProcBindClause()
+      : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()),
+        LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown),
+        KindKwLoc(SourceLocation()) {}
+
+  /// \brief Sets the location of '('.
+  void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+  /// \brief Returns the location of '('.
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+
+  /// \brief Returns kind of the clause.
+  OpenMPProcBindClauseKind getProcBindKind() const { return Kind; }
+
+  /// \brief Returns location of clause kind.
+  SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_proc_bind;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
 /// \brief This represents clause 'private' in the '#pragma omp ...' directives.
 ///
 /// \code
index 714d5a69215c15bde34814a4b1c12e1fefae02b7..31afa138d34e93c6152db76e3e753747192db38f 100644 (file)
@@ -2416,6 +2416,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
   return true;
 }
 
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
+  return true;
+}
+
 template<typename Derived>
 template<typename T>
 void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index 479ef3df30d6861164978943c31315cfc32d5454..8977f99917b0268bfb38d70cefc8a6061aedfd35 100644 (file)
@@ -27,6 +27,9 @@
 #ifndef OPENMP_DEFAULT_KIND
 #  define OPENMP_DEFAULT_KIND(Name)
 #endif
+#ifndef OPENMP_PROC_BIND_KIND
+#  define OPENMP_PROC_BIND_KIND(Name)
+#endif
 
 // OpenMP directives.
 OPENMP_DIRECTIVE(threadprivate)
@@ -44,11 +47,13 @@ OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
 OPENMP_CLAUSE(shared,  OMPSharedClause)
 OPENMP_CLAUSE(linear,  OMPLinearClause)
 OPENMP_CLAUSE(copyin,  OMPCopyinClause)
+OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
 
 // Clauses allowed for OpenMP directive 'parallel'.
 OPENMP_PARALLEL_CLAUSE(if)
 OPENMP_PARALLEL_CLAUSE(num_threads)
 OPENMP_PARALLEL_CLAUSE(default)
+OPENMP_PARALLEL_CLAUSE(proc_bind)
 OPENMP_PARALLEL_CLAUSE(private)
 OPENMP_PARALLEL_CLAUSE(firstprivate)
 OPENMP_PARALLEL_CLAUSE(shared)
@@ -63,6 +68,12 @@ OPENMP_SIMD_CLAUSE(safelen)
 OPENMP_DEFAULT_KIND(none)
 OPENMP_DEFAULT_KIND(shared)
 
+// Static attributes for 'proc_bind' clause.
+OPENMP_PROC_BIND_KIND(master)
+OPENMP_PROC_BIND_KIND(close)
+OPENMP_PROC_BIND_KIND(spread)
+
+#undef OPENMP_PROC_BIND_KIND
 #undef OPENMP_DEFAULT_KIND
 #undef OPENMP_DIRECTIVE
 #undef OPENMP_CLAUSE
index 5b4573124f21fe153d0f2c53b2bc433e86ececbe..93ba41e85334faf34d7406cd4759ffef5007ea53 100644 (file)
@@ -47,6 +47,14 @@ enum OpenMPDefaultClauseKind {
   NUM_OPENMP_DEFAULT_KINDS
 };
 
+/// \brief OpenMP attributes for 'proc_bind' clause.
+enum OpenMPProcBindClauseKind {
+#define OPENMP_PROC_BIND_KIND(Name) \
+  OMPC_PROC_BIND_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_PROC_BIND_unknown
+};
+
 OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
 const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
 
index 0ec99701b3c545d7f7ba265c9e2403884be861cc..9c2918b2a86963cf88be88ac48403640925b3666 100644 (file)
@@ -7301,6 +7301,12 @@ public:
                                       SourceLocation StartLoc,
                                       SourceLocation LParenLoc,
                                       SourceLocation EndLoc);
+  /// \brief Called on well-formed 'proc_bind' clause.
+  OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+                                       SourceLocation KindLoc,
+                                       SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
 
   OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
                                       ArrayRef<Expr *> Vars,
index 758db448288674a09d4b7ffda470299bc901cd8b..8cc2306b25522bc1835fa053ab156223b0d43057 100644 (file)
@@ -625,6 +625,12 @@ void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
      << ")";
 }
 
+void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
+  OS << "proc_bind("
+     << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
+     << ")";
+}
+
 template<typename T>
 void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
   for (typename T::varlist_iterator I = Node->varlist_begin(),
index 1a6d1812dca50876f26c4d5be032df31dfa6599b..e7db0e6fcead6603f5bd0b8f536a66213c8f75d0 100644 (file)
@@ -281,6 +281,8 @@ void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
 
 void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
 
+void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
+
 template<typename T>
 void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
   for (auto *I : Node->varlists())
index 6a7f89069a631537638b17a402c50caca30e16bb..90d563051817a15b81aa58d317fdc155c061b173 100644 (file)
@@ -75,6 +75,12 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
              .Case(#Name, OMPC_DEFAULT_##Name)
 #include "clang/Basic/OpenMPKinds.def"
              .Default(OMPC_DEFAULT_unknown);
+  case OMPC_proc_bind:
+    return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str)
+#define OPENMP_PROC_BIND_KIND(Name) \
+             .Case(#Name, OMPC_PROC_BIND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+             .Default(OMPC_PROC_BIND_unknown);
   case OMPC_unknown:
   case OMPC_threadprivate:
   case OMPC_if:
@@ -103,6 +109,15 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
 #include "clang/Basic/OpenMPKinds.def"
     }
     llvm_unreachable("Invalid OpenMP 'default' clause type");
+  case OMPC_proc_bind:
+    switch (Type) {
+    case OMPC_PROC_BIND_unknown:
+      return "unknown";
+#define OPENMP_PROC_BIND_KIND(Name) \
+    case OMPC_PROC_BIND_##Name : return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+    }
+    llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
   case OMPC_unknown:
   case OMPC_threadprivate:
   case OMPC_if:
index bf3753fd8142bd26b111c67694780612edc59abe..c8da31706b11223a6c431ac3f11af6177086104a 100644 (file)
@@ -288,9 +288,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
     Clause = ParseOpenMPSingleExprClause(CKind);
     break;
   case OMPC_default:
+  case OMPC_proc_bind:
     // OpenMP [2.14.3.1, Restrictions]
     //  Only a single default clause may be specified on a parallel, task or
     //  teams directive.
+    // OpenMP [2.5, parallel Construct, Restrictions]
+    //  At most one proc_bind clause can appear on the directive.
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@@ -355,11 +358,14 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
                                              T.getCloseLocation());
 }
 
-/// \brief Parsing of simple OpenMP clauses like 'default'.
+/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
 ///
 ///    default-clause:
 ///         'default' '(' 'none' | 'shared' ')
 ///
+///    proc_bind-clause:
+///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
+///
 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
   SourceLocation Loc = Tok.getLocation();
   SourceLocation LOpen = ConsumeToken();
@@ -369,9 +375,9 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
                          getOpenMPClauseName(Kind)))
     return 0;
 
-  unsigned Type = Tok.isAnnotation() ?
-                     unsigned(OMPC_DEFAULT_unknown) :
-                     getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
+  unsigned Type =
+      getOpenMPSimpleClauseType(Kind,
+                                Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
   SourceLocation TypeLoc = Tok.getLocation();
   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
       Tok.isNot(tok::annot_pragma_openmp_end))
index b41f7e35d14dfd77b58473756dd2bd7effaf490a..441fc56a7fca6c8f51f34030c4d1fd59129e0e63 100644 (file)
@@ -771,6 +771,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
     Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
   case OMPC_default:
+  case OMPC_proc_bind:
   case OMPC_private:
   case OMPC_firstprivate:
   case OMPC_shared:
@@ -924,6 +925,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
       ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
                                ArgumentLoc, StartLoc, LParenLoc, EndLoc);
     break;
+  case OMPC_proc_bind:
+    Res =
+      ActOnOpenMPProcBindClause(static_cast<OpenMPProcBindClauseKind>(Argument),
+                                ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+    break;
   case OMPC_if:
   case OMPC_num_threads:
   case OMPC_safelen:
@@ -986,6 +992,37 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
                                         EndLoc);
 }
 
+OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+                                           SourceLocation KindKwLoc,
+                                           SourceLocation StartLoc,
+                                           SourceLocation LParenLoc,
+                                           SourceLocation EndLoc) {
+  if (Kind == OMPC_PROC_BIND_unknown) {
+    std::string Values;
+    std::string Sep(", ");
+    for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
+      Values += "'";
+      Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
+      Values += "'";
+      switch (i) {
+      case OMPC_PROC_BIND_unknown - 2:
+        Values += " or ";
+        break;
+      case OMPC_PROC_BIND_unknown - 1:
+        break;
+      default:
+        Values += Sep;
+        break;
+      }
+    }
+    Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+      << Values << getOpenMPClauseName(OMPC_proc_bind);
+    return 0;
+  }
+  return new (Context) OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc,
+                                         EndLoc);
+}
+
 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
                                           ArrayRef<Expr *> VarList,
                                           Expr *TailExpr,
@@ -1015,6 +1052,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
   case OMPC_num_threads:
   case OMPC_safelen:
   case OMPC_default:
+  case OMPC_proc_bind:
   case OMPC_threadprivate:
   case OMPC_unknown:
   case NUM_OPENMP_CLAUSES:
index 9d62e7c4daee8e944d27cb09fa37543c70843bad..29bfcd453706c5c1794f8d2e91fffeec06703afd 100644 (file)
@@ -1345,6 +1345,19 @@ public:
                                               StartLoc, LParenLoc, EndLoc);
   }
 
+  /// \brief Build a new OpenMP 'proc_bind' clause.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OMPClause *RebuildOMPProcBindClause(OpenMPProcBindClauseKind Kind,
+                                      SourceLocation KindKwLoc,
+                                      SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc) {
+    return getSema().ActOnOpenMPProcBindClause(Kind, KindKwLoc,
+                                               StartLoc, LParenLoc, EndLoc);
+  }
+
   /// \brief Build a new OpenMP 'private' clause.
   ///
   /// By default, performs semantic analysis to build the new statement.
@@ -6394,6 +6407,16 @@ TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
                                               C->getLocEnd());
 }
 
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
+  return getDerived().RebuildOMPProcBindClause(C->getProcBindKind(),
+                                               C->getProcBindKindKwLoc(),
+                                               C->getLocStart(),
+                                               C->getLParenLoc(),
+                                               C->getLocEnd());
+}
+
 template<typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
index b42aa24cd7c1c7d1bf5358904f57f21ea7ced7aa..ce44fea84a1399cbe42ccb0323aad036f99f4503 100644 (file)
@@ -1685,6 +1685,9 @@ OMPClause *OMPClauseReader::readClause() {
   case OMPC_default:
     C = new (Context) OMPDefaultClause();
     break;
+  case OMPC_proc_bind:
+    C = new (Context) OMPProcBindClause();
+    break;
   case OMPC_private:
     C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
     break;
@@ -1730,6 +1733,13 @@ void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
   C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
 }
 
+void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
+  C->setProcBindKind(
+       static_cast<OpenMPProcBindClauseKind>(Record[Idx++]));
+  C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+  C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
 void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
   unsigned NumVars = C->varlist_size();
index 2fcf5450a3c1606099b713456fd5ec165970ef1b..947bca746ad6014164f65bd7b82460f4b9381979 100644 (file)
@@ -1696,6 +1696,12 @@ void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
   Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record);
 }
 
+void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
+  Record.push_back(C->getProcBindKind());
+  Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+  Writer->Writer.AddSourceLocation(C->getProcBindKindKwLoc(), Record);
+}
+
 void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
   Record.push_back(C->varlist_size());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
index c12c5b8dec604ce476a71b1ea4055a28c84744cf..631d179c588880f9d798c0806357b69a17f26a7d 100644 (file)
@@ -35,9 +35,9 @@ T tmain(T argc, T *argv) {
   S<T> s;
 #pragma omp parallel
   a=2;
-#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS)
+#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
   foo();
-#pragma omp parallel if (C) num_threads(s)
+#pragma omp parallel if (C) num_threads(s) proc_bind(close)
   foo();
   return 0;
 }
@@ -48,9 +48,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<int> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s)
+// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
 // CHECK-NEXT: long b = argc, c, d, e, f, g;
@@ -58,9 +58,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<long> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s)
+// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close)
 // CHECK-NEXT: foo()
 // CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
 // CHECK-NEXT: T b = argc, c, d, e, f, g;
@@ -68,9 +68,9 @@ T tmain(T argc, T *argv) {
 // CHECK-NEXT: S<T> s;
 // CHECK-NEXT: #pragma omp parallel
 // CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
 // CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s)
+// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close)
 // CHECK-NEXT: foo()
 
 enum Enum { };
@@ -86,8 +86,8 @@ int main (int argc, char **argv) {
 // CHECK-NEXT: #pragma omp parallel
   a=2;
 // CHECK-NEXT: a = 2;
-#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a)
-// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a)
+#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
+// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
   foo();
 // CHECK-NEXT: foo();
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
diff --git a/test/OpenMP/parallel_proc_bind_messages.cpp b/test/OpenMP/parallel_proc_bind_messages.cpp
new file mode 100644 (file)
index 0000000..0bb9fc7
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
+
+void foo();
+
+int main(int argc, char **argv) {
+  #pragma omp parallel proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+  #pragma omp parallel proc_bind ( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel proc_bind () // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+  #pragma omp parallel proc_bind (master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp parallel proc_bind (close), proc_bind(spread) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'proc_bind' clause}}
+  #pragma omp parallel proc_bind (x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+  foo();
+
+  #pragma omp parallel proc_bind(master)
+  ++argc;
+
+  #pragma omp parallel proc_bind(close)
+  #pragma omp parallel proc_bind(spread)
+  ++argc;
+  return 0;
+}
index 5191dbfa9b7d6cb49c6dcaeea800b6753a613853..754026eae174e4178cab42c4bed7c7c81d762af3 100644 (file)
@@ -1937,6 +1937,8 @@ void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
 
 void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
 
+void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
+
 template<typename T>
 void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
   for (const auto *I : Node->varlists())