diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 3e05e9e2498c0bb59371f4a846640ad27f6264b7..068a5a835182514dc0c75901e7157b9ada58eb1e 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -3745,55 +3745,105 @@ public:
 /// directive.
 ///
 /// \code
-/// #pragma omp task affinity(n)
+/// #pragma omp task affinity(numa:n,strict)
 /// \endcode
-/// In this example directive '#pragma omp task' has clause 'affinity' with
-/// single expression 'n'.
+/// In this example directive '#pragma omp task' has clause 'affinity' to a
+/// numa node determined by single expression 'n'. task has the strict binding
+/// depending on the boolean expression 'strict'
 ///
-class OMPAffinityClause : public OMPClause {
+class OMPAffinityClause final
+    : public OMPVarListClause<OMPAffinityClause>,
+      private llvm::TrailingObjects<OMPAffinityClause, Expr *> {
+  friend TrailingObjects;
+  friend OMPVarListClause;
   friend class OMPClauseReader;
-  /// \brief Location of '('.
-  SourceLocation LParenLoc;
-  /// \brief Affinity number.
-  Stmt *Affinity;
+  /// \brief Affinity type (one of depend, numa, core).
+  OpenMPAffinityClauseKind AffKind;
+  /// \brief Affinity type location.
+  SourceLocation AffLoc;
+  /// \brief Colon location.
+  SourceLocation ColonLoc;
   /// \brief Set the Affinity number.
   ///
   /// \param E Affinity number.
   ///
-  void setAffinity(Expr *E) { Affinity = E; }
+  void setAffinity(Expr *E) {  }
 
-public:
-  /// \brief Build 'affinity' clause.
+  /// \brief Build clause with two variables (affinity value, strictness)
   ///
-  /// \param E Expression associated with this clause.
   /// \param StartLoc Starting location of the clause.
   /// \param LParenLoc Location of '('.
   /// \param EndLoc Ending location of the clause.
   ///
-  OMPAffinityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
-                    SourceLocation EndLoc)
-      : OMPClause(OMPC_affinity, StartLoc, EndLoc), LParenLoc(LParenLoc),
-        Affinity(E) {}
+  OMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+                  SourceLocation EndLoc, unsigned N)
+      : OMPVarListClause<OMPAffinityClause>(OMPC_affinity, StartLoc, LParenLoc,
+                                            EndLoc, N),
+        AffKind(OMPC_AFFINITY_unknown) {}
 
   /// \brief Build an empty clause.
   ///
-  OMPAffinityClause()
-      : OMPClause(OMPC_affinity, SourceLocation(), SourceLocation()),
-        LParenLoc(SourceLocation()), Affinity(nullptr) {}
-  /// \brief Sets the location of '('.
-  void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
-  /// \brief Returns the location of '('.
-  SourceLocation getLParenLoc() const { return LParenLoc; }
-  /// \brief Return Affinity number.
-  Expr *getAffinity() { return cast<Expr>(Affinity); }
-  /// \brief Return Affinity number.
-  Expr *getAffinity() const { return cast<Expr>(Affinity); }
+  /// \param N Number of variables.
+  ///
+  explicit OMPAffinityClause(unsigned N)
+      : OMPVarListClause<OMPAffinityClause>(OMPC_affinity, SourceLocation(),
+                                            SourceLocation(), SourceLocation(),
+                                            N),
+        AffKind(OMPC_AFFINITY_unknown) {}
+  /// \brief Set affinity kind.
+  void setAFfinityKind(OpenMPAffinityClauseKind K) { AffKind = K; }
+
+  /// \brief Set dependency kind and its location.
+  void setAffinityLoc(SourceLocation Loc) { AffLoc = Loc; }
+
+  /// \brief Set colon location.
+  void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+public:
+  /// \brief Creates clause with a list of two variables.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  /// \param AffLoc Affinity type.
+  /// \param AffLoc Location of the dependency type.
+  /// \param ColonLoc Colon location.
+  /// \param VL List of references to the variables.
+  ///
+  static OMPAffinityClause *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+         SourceLocation EndLoc, OpenMPAffinityClauseKind AffKind,
+         SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+  /// \brief Creates an empty clause with \a 2 variables.
+  ///
+  /// \param C AST context.
+  ///
+  static OMPAffinityClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+  /// \brief Get affinity type.
+  OpenMPAffinityClauseKind getAffinityKind() const { return AffKind; }
+  /// \brief Get affinity type location.
+  SourceLocation getAffinityLoc() const { return AffLoc; }
+  /// \brief Get colon location.
+  SourceLocation getColonLoc() const { return ColonLoc; }
+
+  /// \brief Get 'affinity' expression
+  const Expr *getAffinity() const { return (getVarRefs().size() > 0)?
+                                            getVarRefs()[0]:nullptr; }
+
+  /// \brief Get 'strict' expression
+  const Expr *getStrict() const { return (getVarRefs().size() > 1)?
+                                          getVarRefs()[1]:nullptr; }
+
+  child_range children() {
+    return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+                       reinterpret_cast<Stmt **>(varlist_end()));
+  }
 
   static bool classof(const OMPClause *T) {
     return T->getClauseKind() == OMPC_affinity;
   }
-
-  child_range children() { return child_range(&Affinity, &Affinity + 1); }
 };
 
 /// \brief This represents 'grainsize' clause in the '#pragma omp ...'
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 3e31829c8aee2c8933618ef7f9346884aabdf54a..3f2a9f698f3a420275bffbfadfaf3ec99e359063 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2882,6 +2882,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause(
+    OMPAffinityClause *C) {
+  TRY_TO(VisitOMPClauseList(C));
+  return true;
+}
+
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
   TRY_TO(TraverseStmt(C->getDevice()));
@@ -2922,13 +2929,6 @@ bool RecursiveASTVisitor<Derived>::VisitOMPOperationalIntensityClause(
   return true;
 }
 
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause(
-    OMPAffinityClause *C) {
-  TRY_TO(TraverseStmt(C->getAffinity()));
-  return true;
-}
-
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
     OMPGrainsizeClause *C) {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3963f7581880715485dea145728122ad6caa94d5..55a43489d929f6680d284664f1f5b53e3598c5f9 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8308,6 +8308,8 @@ def err_omp_firstprivate_and_lastprivate_in_distribute : Error<
   "lastprivate variable cannot be firstprivate in '#pragma omp distribute'">;
 def err_omp_firstprivate_distribute_in_teams_reduction : Error<
   "reduction variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_affinity_clause_wrong_number_var : Error<
+  "'affinity' clause must have one expression and optionally a 'strict' argument">;
 def err_omp_depend_clause_thread_simd : Error<
   "'depend' clauses cannot be mixed with '%0' clause">;
 def err_omp_depend_sink_expected_loop_iteration : Error<
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 124837e24a38216796a7a7fd772da89c209b733d..91ffe16babe871f57ee1b3acf22140e294e83dd9 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -105,6 +105,9 @@
 #ifndef OPENMP_INIT_KIND
 #define OPENMP_INIT_KIND(Name)
 #endif
+#ifndef OPENMP_AFFINITY_KIND
+#define OPENMP_AFFINITY_KIND(Name)
+#endif
 #ifndef OPENMP_SCHEDULE_KIND
 #define OPENMP_SCHEDULE_KIND(Name)
 #endif
@@ -335,6 +338,11 @@ OPENMP_DEFAULTMAP_KIND(scalar)
 // Modifiers for 'defaultmap' clause.
 OPENMP_DEFAULTMAP_MODIFIER(tofrom)
 
+// Static attributes for 'affinity' clause.
+OPENMP_AFFINITY_KIND(depend)
+OPENMP_AFFINITY_KIND(numa)
+OPENMP_AFFINITY_KIND(core)
+
 // Static attributes for 'depend' clause.
 OPENMP_DEPEND_KIND(in)
 OPENMP_DEPEND_KIND(out)
@@ -640,6 +648,7 @@ OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(aligned)
 #undef OPENMP_TASKLOOP_SIMD_CLAUSE
 #undef OPENMP_TASKLOOP_CLAUSE
 #undef OPENMP_LINEAR_KIND
+#undef OPENMP_AFFINITY_KIND
 #undef OPENMP_DEPEND_KIND
 #undef OPENMP_SCHEDULE_MODIFIER
 #undef OPENMP_SCHEDULE_KIND
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index 285ce0b5d8b9a08811dfcf5028f52cf28e54b9bd..3a2f3cedec137a0103f5918bc22fba04bb4fbcd5 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -88,6 +88,14 @@ enum OpenMPDependClauseKind {
   OMPC_DEPEND_unknown
 };
 
+/// \brief OpenMP attributes for 'affinity' clause.
+enum OpenMPAffinityClauseKind {
+#define OPENMP_AFFINITY_KIND(Name) \
+  OMPC_AFFINITY_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_AFFINITY_unknown
+};
+
 /// \brief OpenMP attributes for 'linear' clause.
 enum OpenMPLinearClauseKind {
 #define OPENMP_LINEAR_KIND(Name) \
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 5838a447c3b91984ace032cd4b0f597f71e67f91..ed5142a38d1c0bd14e10067bd0a4d152cbb479e8 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2562,6 +2562,7 @@ public:
     CXXScopeSpec ReductionIdScopeSpec;
     DeclarationNameInfo ReductionId;
     OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
+    OpenMPAffinityClauseKind AffKind = OMPC_AFFINITY_unknown;
     OpenMPLinearClauseKind LinKind = OMPC_LINEAR_val;
     OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
     OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 5342d35993f10420d3f9722c0fa250690cbccb57..824e56a24e6f112b4a2d305495fc00d5bd7d00b3 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -8395,6 +8395,7 @@ public:
       CXXScopeSpec &ReductionIdScopeSpec,
       const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
       OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+      OpenMPAffinityClauseKind AffKind,
       OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
       SourceLocation DepLinMapLoc);
   /// \brief Called on well-formed 'private' clause.
@@ -8518,7 +8519,11 @@ public:
                                                    SourceLocation LParenLoc,
                                                    SourceLocation EndLoc);
   /// \brief Called on well-formed 'affinity' clause.
-  OMPClause *ActOnOpenMPAffinityClause(Expr *Affinity, SourceLocation StartLoc,
+  OMPClause *ActOnOpenMPAffinityClause(OpenMPAffinityClauseKind AffKind,
+                                       SourceLocation AffLoc,
+                                       SourceLocation ColonLoc,
+                                       ArrayRef<Expr *> VarList,
+                                       SourceLocation StartLoc,
                                        SourceLocation LParenLoc,
                                        SourceLocation EndLoc);
 
diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp
index 3f87b900123f5f59199078f1b409ef8250be2728..111169896cd6e4043d3f0961cc0657c2c2eb1853 100644
--- a/lib/AST/OpenMPClause.cpp
+++ b/lib/AST/OpenMPClause.cpp
@@ -81,6 +81,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_affinity:
+  case OMPC_oi:
   case OMPC_init:
   case OMPC_grainsize:
   case OMPC_nogroup:
@@ -148,6 +149,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_affinity:
+  case OMPC_oi:
   case OMPC_init:
   case OMPC_grainsize:
   case OMPC_nogroup:
@@ -584,6 +586,29 @@ unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber(
   return TotalNum;
 }
 
+OMPAffinityClause *
+OMPAffinityClause::Create(const ASTContext &C, SourceLocation StartLoc,
+                          SourceLocation LParenLoc, SourceLocation EndLoc,
+                          OpenMPAffinityClauseKind AffKind,
+                          SourceLocation AffLoc,
+                          SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+  OMPAffinityClause *Clause =
+      new (Mem) OMPAffinityClause(StartLoc, LParenLoc, EndLoc, VL.size());
+  Clause->setVarRefs(VL);
+  Clause->setAFfinityKind(AffKind);
+  Clause->setAffinityLoc(AffLoc);
+  Clause->setColonLoc(ColonLoc);
+  return Clause;
+}
+
+OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C,
+                                                  unsigned N) {
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(0));
+  return new (Mem) OMPAffinityClause(0);
+}
+
+
 OMPMapClause *
 OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc,
                      SourceLocation LParenLoc, SourceLocation EndLoc,
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 3e5a83f7d300f5afd6406315eb017e5adac33388..764595bcaa378c3b1804d448c0fb508d74854133 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -760,6 +760,7 @@ void OMPClausePrinter::VisitOMPOperationalIntensityClause(OMPOperationalIntensit
 }
 
 void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) {
+  //TODO fix this 
   OS << "affinity(";
   Node->getAffinity()->printPretty(OS, nullptr, Policy, 0);
   OS << ")";
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index be6c95e762649ebcd3f10cd1a63bd4b90988f7ce..62643ae9594bca0ad21676f72ead7111d9f4356a 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -130,6 +130,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   .Case(#Name, static_cast<unsigned>(OMPC_DEFAULTMAP_MODIFIER_##Name))
 #include "clang/Basic/OpenMPKinds.def"
         .Default(OMPC_DEFAULTMAP_unknown);
+  case OMPC_affinity:
+    return llvm::StringSwitch<OpenMPAffinityClauseKind>(Str)
+#define OPENMP_AFFINITY_KIND(Name) .Case(#Name, OMPC_AFFINITY_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+        .Default(OMPC_AFFINITY_unknown);
   case OMPC_unknown:
   case OMPC_threadprivate:
   case OMPC_if:
@@ -163,7 +168,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_oi:
-  case OMPC_affinity:
   case OMPC_grainsize:
   case OMPC_nogroup:
   case OMPC_num_tasks:
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index 36a29e919193e2a0f6795c998d7ae4d080b3efa3..16f57357170f6fec7e9f7c3ca2ad7b5b4d9a66d3 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -555,7 +555,8 @@ enum OpenMPRTLFunction {
   // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
   // int end_part);
   OMPRTL__kmpc_omp_taskyield,
-  // Call to void __kmpc_omp_set_task_affinity(ident_t *, kmp_int32 affinity);
+  // Call to void __kmpc_omp_set_task_affinity(int kind, kmp_int32 affinity,
+  // int strict);
   OMPRTL__kmpc_omp_set_task_affinity,
   // Call to void __kmpc_begin_push_init(int kind);
   OMPRTL__kmpc_begin_push_init,
@@ -1234,8 +1235,9 @@ CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
     break;
   }
   case OMPRTL__kmpc_omp_set_task_affinity: {
-    // Build void __kmpc_omp_set_task_affinity(ident_t *loc, kmp_int32 affinity,)
-    llvm::Type *TypeParams[] = {CGM.Int32Ty};
+    // Build void __kmpc_omp_set_task_affinity(int kind, kmp_int32 affinity,
+    //                                         int strict)
+    llvm::Type *TypeParams[] = {CGM.Int32Ty, CGM.Int64Ty, CGM.Int32Ty};
     llvm::FunctionType *FnTy =
         llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
     RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_set_task_affinity");
@@ -2680,6 +2682,49 @@ void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
   CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
 }
 
+void CGOpenMPRuntime::emitTaskAffinityClause(CodeGenFunction &CGF,
+                                             OpenMPAffinityClauseKind AffKind,
+                                             const Expr *Aff,
+                                             llvm::Value *Strict) {
+  //Emit Affinity
+  CodeGenFunction::RunCleanupsScope AffinityScope(CGF);
+
+  // Constants for affinity kind accepted by the runtime.
+  enum AffinityKindTy {
+    AffinityDepend = 0,
+    AffinityNuma,
+    AffinityCore
+  } RuntimeAffinity;
+  switch (AffKind) {
+  case OMPC_AFFINITY_numa:
+    RuntimeAffinity = AffinityNuma;
+    break;
+  case OMPC_AFFINITY_core:
+    RuntimeAffinity = AffinityCore;
+    break;
+  case OMPC_AFFINITY_depend:
+    RuntimeAffinity = AffinityDepend;
+    break;
+  case OMPC_AFFINITY_unknown:
+    llvm_unreachable("Unsupported affinity value.");
+  }
+
+  llvm::Value *Affinity = CGF.EmitScalarExpr(Aff, /*IgnoreResultAssign*/ true);
+  const Type *ExprTy = Aff->getType().getTypePtr();
+  if (AffKind == OMPC_AFFINITY_depend && ExprTy->isPointerType()) {
+    Affinity = CGF.Builder.CreatePtrToInt(Affinity, CGF.Int64Ty);
+  }
+
+  // Build call __kmpc_omp_set_affinity(affinity)
+  llvm::Value *Args[] = {
+    llvm::ConstantInt::get(CGM.IntTy, RuntimeAffinity, /*isSigned=*/true),
+    CGF.Builder.CreateIntCast(Affinity, CGF.Int64Ty, /*isSigned*/ false),
+    CGF.Builder.CreateIntCast(Strict, CGF.Int32Ty, /*isSigned*/ false)
+  };
+  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_set_task_affinity),
+      Args);
+}
+
 void CGOpenMPRuntime::emitBeginInitClause(CodeGenFunction &CGF,
                                           OpenMPInitClauseKind Init) {
   if (!CGF.HaveInsertPoint())
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 1f62bf1e9fef06ff8bed12ef3a5ba55c22f036a9..149920b5550399a841a0ec93ef3f2ea5d8504f31 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -749,6 +749,14 @@ public:
                                   OpenMPProcBindClauseKind ProcBind,
                                   SourceLocation Loc);
 
+  /// \brief Emit call to void __kmpc_omp_set_task_affinity(int kind, kmp_int32
+  // affinity, int strict)
+  /// to generate code for begin 'init' clause.
+  virtual void emitTaskAffinityClause(CodeGenFunction &CGF,
+                                      OpenMPAffinityClauseKind AffKind,
+                                      const Expr *Aff,
+                                      llvm::Value *Strict);
+
   /// \brief Emit call to void __kmpc_begin_push_init(int init)
   /// to generate code for begin 'init' clause.
   virtual void emitBeginInitClause(CodeGenFunction &CGF,
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 07ee10c6e1816e38b68ba40048cff679d1369d92..2495cc7e5f0910a38dd265664d799672da422407 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -2609,13 +2609,6 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
   // Emit outlined function for task construct.
   auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
   auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
-#if 0
-  //Check if there is an affinity clause
-  const Expr *Affinity = nullptr;
-  if (const auto *AffinityClause = S.getSingleClause<OMPAffinityClause>()) {
-    Affinity = AffinityClause->getAffinity();
-  }
-#endif
   auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
   const Expr *IfCond = nullptr;
   for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
@@ -2639,6 +2632,20 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
                                             SharedsTy, CapturedStruct, IfCond,
                                             Data);
   };
+#if 0
+  //Check if there is an affinity clause
+  if (const auto *AffinityClause = S.getSingleClause<OMPAffinityClause>()) {
+    auto Strict = AffinityClause->getStrict();
+    llvm::Value *StrictValue = Builder.getInt32(0);
+    if (Strict)
+      StrictValue = EvaluateExprAsBool(Strict);
+
+    CGM.getOpenMPRuntime().emitTaskAffinityClause(*this,
+                           AffinityClause->getAffinityKind(),
+                           AffinityClause->getAffinity(),
+                           StrictValue);
+  }
+#endif
   EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
 }
 
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 1eb25cc7210db4ed70dc050976cee894cfc4cb04..3577b6c70c45a1fde6ede47e6e1f28f2a5437d52 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -1086,7 +1086,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_oi:
-  case OMPC_affinity:
   case OMPC_grainsize:
   case OMPC_num_tasks:
   case OMPC_hint:
@@ -1197,6 +1196,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_copyprivate:
   case OMPC_flush:
   case OMPC_depend:
+  case OMPC_affinity:
   case OMPC_map:
   case OMPC_to:
   case OMPC_from:
@@ -1597,6 +1597,24 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
                                       : diag::warn_pragma_expected_colon)
           << "dependency type";
     }
+  } else if (Kind == OMPC_affinity) {
+  // Handle affinity type for affinity clause.
+    ColonProtectionRAIIObject ColonRAII(*this);
+    Data.AffKind = static_cast<OpenMPAffinityClauseKind>(getOpenMPSimpleClauseType(
+        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+    Data.DepLinMapLoc = Tok.getLocation();
+
+    if (Data.AffKind == OMPC_AFFINITY_unknown) {
+      //FIXME use correct error message
+      Diag(Tok, diag::err_omp_unknown_map_type);
+    }
+    ConsumeToken();
+    if (Tok.is(tok::colon)) {
+      Data.ColonLoc = ConsumeToken();
+    } else {
+      Diag(Tok, diag::warn_pragma_expected_colon)
+          << "affinity type";
+    }
   } else if (Kind == OMPC_linear) {
     // Try to parse modifier if any.
     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
@@ -1676,12 +1694,13 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
   }
 
   bool IsComma =
-      (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
+      (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map && (Kind != OMPC_affinity)) ||
       (Kind == OMPC_reduction && !InvalidReductionId) ||
       (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
        (!MapTypeModifierSpecified ||
         Data.MapTypeModifier == OMPC_MAP_always)) ||
-      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
+      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown) ||
+      (Kind == OMPC_affinity && Data.AffKind != OMPC_AFFINITY_unknown);
   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                      Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -1788,7 +1807,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
   return Actions.ActOnOpenMPVarListClause(
       Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
       Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
-      Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
+      Data.MapTypeModifier, Data.AffKind, Data.MapType, Data.IsMapTypeImplicit,
       Data.DepLinMapLoc);
 }
 
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index ee1bfcab14c2a1f55cd19f6b335b37d2ff531234..a27dae97b49f0bbe8b48b47a8e38e0239b40dc44 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -7246,9 +7246,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_oi:
     Res = ActOnOpenMPOperationalIntensityClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
-  case OMPC_affinity:
-    Res = ActOnOpenMPAffinityClause(Expr, StartLoc, LParenLoc, EndLoc);
-    break;
   case OMPC_grainsize:
     Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc);
     break;
@@ -7283,6 +7280,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_capture:
   case OMPC_seq_cst:
   case OMPC_depend:
+  case OMPC_affinity:
   case OMPC_threads:
   case OMPC_simd:
   case OMPC_map:
@@ -8023,6 +8021,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
     SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
     const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
     OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+    OpenMPAffinityClauseKind AffKind,
     OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
     SourceLocation DepLinMapLoc) {
   OMPClause *Res = nullptr;
@@ -8061,9 +8060,13 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
     Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
     break;
   case OMPC_depend:
-    Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList, 
+    Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,
                                   StartLoc, LParenLoc, EndLoc);
     break;
+  case OMPC_affinity:
+    Res = ActOnOpenMPAffinityClause(AffKind, DepLinMapLoc, ColonLoc, VarList,
+                                    StartLoc, LParenLoc, EndLoc);
+    break;
   case OMPC_map:
     Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, IsMapTypeImplicit,
                                DepLinMapLoc, ColonLoc, VarList, StartLoc,
@@ -8108,7 +8111,6 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
   case OMPC_thread_limit:
   case OMPC_priority:
   case OMPC_oi:
-  case OMPC_affinity:
   case OMPC_grainsize:
   case OMPC_nogroup:
   case OMPC_num_tasks:
@@ -11354,19 +11356,25 @@ OMPClause *Sema::ActOnOpenMPOperationalIntensityClause(Expr *OperationalIntensit
   return new (Context) OMPOperationalIntensityClause(ValExpr, StartLoc, LParenLoc, EndLoc);
 }
 
-OMPClause *Sema::ActOnOpenMPAffinityClause(Expr *Affinity,
-                                           SourceLocation StartLoc,
-                                           SourceLocation LParenLoc,
-                                           SourceLocation EndLoc) {
-  Expr *ValExpr = Affinity;
-
+OMPClause *
+Sema::ActOnOpenMPAffinityClause(OpenMPAffinityClauseKind AffKind,
+                                SourceLocation AffLoc, SourceLocation ColonLoc,
+                                ArrayRef<Expr *> VarList,
+                                SourceLocation StartLoc,
+                                SourceLocation LParenLoc,
+                                SourceLocation EndLoc) {
+
+  if (VarList.size() == 0 || VarList.size() > 2)
+    Diag(AffLoc, diag::err_omp_affinity_clause_wrong_number_var);
+  // FIXME do a proper check on this
   // The affinity is a non-negative numerical scalar expression.
   // It should also correspond to a NUMA node id
-  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_affinity,
-                                 /*StrictlyPositive=*/false))
-    return nullptr;
+  //if (!IsNonNegativeIntegerValue(VarList[0], *this, OMPC_affinity,
+                                 //StrictlyPositive=false))
+    //return nullptr;
 
-  return new (Context) OMPAffinityClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+  return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+                                   AffKind, AffLoc, ColonLoc, VarList);
 }
 
 OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 990c669ee3c941fb20018b9f92b0afebf7e0c837..f14c3d3643ed8fb04e0138c589a2bde1349757cc 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1743,10 +1743,15 @@ public:
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  OMPClause *RebuildOMPAffinityClause(Expr *Affinity, SourceLocation StartLoc,
+  OMPClause *RebuildOMPAffinityClause(OpenMPAffinityClauseKind AffKind,
+                                      SourceLocation AffLoc,
+                                      SourceLocation ColonLoc,
+                                      ArrayRef<Expr *> VarList,
+                                      SourceLocation StartLoc,
                                       SourceLocation LParenLoc,
                                       SourceLocation EndLoc) {
-    return getSema().ActOnOpenMPAffinityClause(Affinity, StartLoc, LParenLoc,
+    return getSema().ActOnOpenMPAffinityClause(AffKind, AffLoc, ColonLoc,
+                                               VarList, StartLoc, LParenLoc,
                                                EndLoc);
   }
 
@@ -8123,11 +8128,17 @@ TreeTransform<Derived>::TransformOMPOperationalIntensityClause(OMPOperationalInt
 template <typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPAffinityClause(OMPAffinityClause *C) {
-  ExprResult E = getDerived().TransformExpr(C->getAffinity());
-  if (E.isInvalid())
-    return nullptr;
+  llvm::SmallVector<Expr *, 16> Vars;
+  Vars.reserve(C->varlist_size());
+  for (auto *VE : C->varlists()) {
+    ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+    if (EVar.isInvalid())
+      return nullptr;
+    Vars.push_back(EVar.get());
+  }
   return getDerived().RebuildOMPAffinityClause(
-      E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+      C->getAffinityKind(), C->getAffinityLoc(), C->getColonLoc(), Vars,
+      C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
 }
 
 template <typename Derived>
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 65e01131ec0f586f39130240e51a900998d54244..63af2390f9727e3524ea0104f57f146e5d661af1 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1906,7 +1906,7 @@ OMPClause *OMPClauseReader::readClause() {
     C = new (Context) OMPOperationalIntensityClause();
     break;
   case OMPC_affinity:
-    C = new (Context) OMPAffinityClause();
+    C = OMPAffinityClause::CreateEmpty(Context, Record[Idx++]);
     break;
   case OMPC_grainsize:
     C = new (Context) OMPGrainsizeClause();
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 260842ef7d881c92f82f42885089842bddef4061..cab911cc5b417000ce346346d89fd69c79b2bc1f 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -2089,8 +2089,13 @@ void OMPClauseWriter::VisitOMPOperationalIntensityClause(OMPOperationalIntensity
 }
 
 void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) {
-  Record.AddStmt(C->getAffinity());
+  Record.push_back(C->varlist_size());
   Record.AddSourceLocation(C->getLParenLoc());
+  Record.push_back(C->getAffinityKind());
+  Record.AddSourceLocation(C->getAffinityLoc());
+  Record.AddSourceLocation(C->getColonLoc());
+  for (auto *VE : C->varlists())
+    Record.AddStmt(VE);
 }
 
 void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 00319bfd83678acd2948d289234c7c6ed09b73b2..86072b96a6a5438e033918e494d0b09fddc7ef88 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -2144,7 +2144,7 @@ void OMPClauseEnqueue::VisitOMPOperationalIntensityClause(const OMPOperationalIn
 }
 
 void OMPClauseEnqueue::VisitOMPAffinityClause(const OMPAffinityClause *C) {
-  Visitor->AddStmt(C->getAffinity());
+  VisitOMPClauseList(C);
 }
 
 void OMPClauseEnqueue::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {