abidmalikwaterloo updated this revision to Diff 495925.
abidmalikwaterloo added a comment.

Rebase the patch to origin/main with all updates. Made changes 
to make it buildable using the new changes. 
(WIP).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122255

Files:
  clang/include/clang/AST/OpenMPClause.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/AST/StmtOpenMP.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/OpenMPClause.cpp
  clang/lib/AST/StmtPrinter.cpp
  clang/lib/Parse/ParseOpenMP.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/OpenMP/metadirective_ast_print_new_1.cpp
  clang/test/OpenMP/metadirective_ast_print_new_2.cpp
  clang/test/OpenMP/metadirective_ast_print_new_3.cpp
  llvm/include/llvm/Frontend/OpenMP/OMPContext.h
  llvm/lib/Frontend/OpenMP/OMPContext.cpp

Index: llvm/lib/Frontend/OpenMP/OMPContext.cpp
===================================================================
--- llvm/lib/Frontend/OpenMP/OMPContext.cpp
+++ llvm/lib/Frontend/OpenMP/OMPContext.cpp
@@ -19,6 +19,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include <map>
 #define DEBUG_TYPE "openmp-ir-builder"
 
 using namespace llvm;
@@ -336,6 +337,44 @@
   return Score;
 }
 
+/// Takes \p VMI and \p Ctx and sort the
+/// scores using \p VectorOfClauses
+void llvm::omp::getArrayVariantMatchForContext(
+    const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx,
+    SmallVector<std::pair<unsigned, APInt>> &VectorOfClauses) {
+
+  // APInt BestScore(64, 0);
+  APInt Score(64, 0);
+  // The MapOfClauses will contain the index of the cluase and its context socre
+  llvm::DenseMap<unsigned, llvm::APInt> MapOfCluases;
+
+  for (unsigned u = 0, e = VMIs.size(); u < e; ++u) {
+    const VariantMatchInfo &VMI = VMIs[u];
+
+    SmallVector<unsigned, 8> ConstructMatches;
+    // If the variant is not applicable its not the best.
+    if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches,
+                                            /* DeviceSetOnly */ false)) {
+      Score = 0;
+      // adding index and its corresdoning score
+      MapOfCluases.insert({u, Score});
+      continue;
+    }
+    // Else get the score
+    Score = getVariantMatchScore(VMI, Ctx, ConstructMatches);
+    MapOfCluases.insert({u, Score});
+  }
+
+  for (auto &it : MapOfCluases)
+    VectorOfClauses.push_back(it);
+
+  // The following Lamda will sort the VectorOfClauses based on the score
+  std::sort(VectorOfClauses.begin(), VectorOfClauses.end(),
+            [](std::pair<unsigned, APInt> &a, std::pair<unsigned, APInt> &b) {
+              return a.second.ugt(b.second);
+            });
+}
+
 int llvm::omp::getBestVariantMatchForContext(
     const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx) {
 
Index: llvm/include/llvm/Frontend/OpenMP/OMPContext.h
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPContext.h
+++ llvm/include/llvm/Frontend/OpenMP/OMPContext.h
@@ -189,6 +189,15 @@
 int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs,
                                   const OMPContext &Ctx);
 
+/// Sort array \p A of clause index  with score
+/// This will be used to produce AST clauses
+/// in a sorted order with the clause with the highiest order
+/// on the top and default clause at the bottom
+void getArrayVariantMatchForContext(
+    const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx,
+    SmallVector<std::pair<unsigned, APInt>> &A);
+
+// new--
 } // namespace omp
 
 template <> struct DenseMapInfo<omp::TraitProperty> {
Index: clang/test/OpenMP/metadirective_ast_print_new_3.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/metadirective_ast_print_new_3.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -verify  -fopenmp  -ast-print %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+int main() {
+  int N = 15;
+#pragma omp metadirective when(user = {condition(N > 10)} : parallel for)\
+ 				default(target teams) 
+  for (int i = 0; i < N; i++)
+    ;
+
+
+#pragma omp metadirective when(device = {arch("nvptx64")}, user = {condition(N >= 100)} : parallel for)\
+  				default(target parallel for)
+  for (int i = 0; i < N; i++)
+    ;
+  return 0;
+}
+
+
+
+// CHECK: #pragma omp metadirective when(user={condition(N > 10)}: parallel for) default(target teams)
+// CHECK: #pragma omp metadirective when(device={arch(nvptx64)}, user={condition(N >= 100)}: parallel for) default(target parallel for)
Index: clang/test/OpenMP/metadirective_ast_print_new_2.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/metadirective_ast_print_new_2.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify  -fopenmp  -ast-print %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+void bar(){
+	int i=0;	
+}
+
+void myfoo(void){
+
+	int N = 13;
+	int b,n;
+	int a[100];
+
+	
+	#pragma omp  metadirective when (user = {condition(N>10)}: target  teams distribute parallel for ) \
+					when (user = {condition(N==10)}: parallel for )\
+					when (user = {condition(N==13)}: parallel for simd) \
+					when ( device={arch("arm")}:   target teams num_teams(512) thread_limit(32))\
+					when ( device={arch("nvptx")}: target teams num_teams(512) thread_limit(32))\
+					default ( parallel for)\
+
+	{		for (int i = 0; i < N; i++)
+		bar();
+	}
+}
+
+// CHECK: bar()
+// CHECK: myfoo
+// CHECK: #pragma omp metadirective when(user={condition(N > 10)}: target teams distribute parallel for) when(user={condition(N == 13)}: parallel for simd) when(device={arch(nvptx)}: target teams)
Index: clang/test/OpenMP/metadirective_ast_print_new_1.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/metadirective_ast_print_new_1.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -verify  -fopenmp  -ast-print %s -o - | FileCheck %s
+// expected-no-diagnostics
+void bar(){
+        int i=0;
+}
+
+void myfoo(void){
+
+        int N = 13;
+        int b,n;
+        int a[100];
+
+        #pragma omp metadirective when(user={condition(N>10)}:  target teams ) default(parallel for)
+                for (int i = 0; i < N; i++)
+                bar();
+
+}
+
+// CHECK: void bar()
+// CHECK: #pragma omp metadirective when(user={condition(N > 10)}: target teams) default(parallel for)
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4822,7 +4822,7 @@
       getASTContext(), S, static_cast<CapturedRegionKind>(RSI->CapRegionKind),
       Captures, CaptureInits, CD, RD);
 
-  CD->setBody(Res->getCapturedStmt());
+  CD->setBody(Res->getCapturedStmt());   
   RD->completeDefinition();
 
   return Res;
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Frontend/OpenMP/OMPAssume.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
+#include "llvm/Frontend/OpenMP/OMPContext.h"
 #include <set>
 
 using namespace clang;
@@ -4145,6 +4146,7 @@
 
 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
   switch (DKind) {
+  case OMPD_metadirective:
   case OMPD_parallel:
   case OMPD_parallel_for:
   case OMPD_parallel_for_simd:
@@ -4579,7 +4581,6 @@
   case OMPD_declare_variant:
   case OMPD_begin_declare_variant:
   case OMPD_end_declare_variant:
-  case OMPD_metadirective:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
   default:
@@ -4763,7 +4764,7 @@
 }
 
 StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
-                                      ArrayRef<OMPClause *> Clauses) {
+                                      ArrayRef<OMPClause *> Clauses){
   handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
                                      /* ScopeEntry */ false);
   if (DSAStack->getCurrentDirective() == OMPD_atomic ||
@@ -4854,6 +4855,7 @@
         << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
     ErrorFound = true;
   }
+  
   // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
   // If an order(concurrent) clause is present, an ordered clause may not appear
   // on the same directive.
@@ -4865,7 +4867,7 @@
           << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
     }
     ErrorFound = true;
-  }
+  } 
   if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
       isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
       OC->getNumForLoops()) {
@@ -4877,8 +4879,9 @@
     return StmtError();
   }
   StmtResult SR = S;
-  unsigned CompletedRegions = 0;
+  unsigned CompletedRegions = 0;  
   for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
+  
     // Mark all variables in private list clauses as used in inner region.
     // Required for proper codegen of combined directives.
     // TODO: add processing for other clauses.
@@ -4899,6 +4902,7 @@
         }
       }
     }
+    
     if (ThisCaptureRegion == OMPD_target) {
       // Capture allocator traits in the target region. They are used implicitly
       // and, thus, are not captured by default.
@@ -4914,6 +4918,7 @@
         }
       }
     }
+    
     if (ThisCaptureRegion == OMPD_parallel) {
       // Capture temp arrays for inscan reductions and locals in aligned
       // clauses.
@@ -4930,10 +4935,14 @@
         }
       }
     }
+    
     if (++CompletedRegions == CaptureRegions.size())
       DSAStack->setBodyComplete();
+  
     SR = ActOnCapturedRegionEnd(SR.get());
+    
   }
+  
   return SR;
 }
 
@@ -6250,6 +6259,12 @@
 
   llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
   switch (Kind) {
+
+  case OMPD_metadirective:
+    Res = ActOnOpenMPMetaDirective(ClausesWithImplicit, AStmt, StartLoc, 
+    					EndLoc);
+    AllowedNameModifiers.push_back(OMPD_metadirective); 
+    break;
   case OMPD_parallel:
     Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
                                        EndLoc);
@@ -7705,10 +7720,126 @@
   FD->addAttr(NewAttr);
 }
 
+StmtResult Sema::ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
+                                              Stmt *AStmt,
+                                              SourceLocation StartLoc,
+                                              SourceLocation EndLoc){
+  if (!AStmt)
+    return StmtError();
+
+  auto *CS = cast<CapturedStmt>(AStmt);
+  // 1.2.2 OpenMP Language Terminology
+  // Structured block - An executable statement with a single entry at the
+  // top and a single exit at the bottom.
+  // The point of exit cannot be a branch out of the structured block.
+  // longjmp() and throw() must not violate the entry/exit criteria.
+  
+  CS->getCapturedDecl()->setNothrow();
+
+  StmtResult IfStmt = StmtError();
+  Stmt *ElseStmt = nullptr;
+
+  for (auto i = Clauses.rbegin(); i < Clauses.rend(); i++) {
+    OMPWhenClause *WhenClause = dyn_cast<OMPWhenClause>(*i);
+    Expr *WhenCondExpr = nullptr;
+    Stmt *ThenStmt = nullptr;
+    OpenMPDirectiveKind DKind = WhenClause->getDKind();
+
+    if (DKind != OMPD_unknown)
+      ThenStmt = CompoundStmt::Create(Context, {WhenClause->getDirective()},
+                                      FPOptionsOverride(), SourceLocation(),
+                                      SourceLocation());
+
+    for (const OMPTraitSet &Set : WhenClause->getTI().Sets){
+      for (const OMPTraitSelector &Selector : Set.Selectors){
+        switch (Selector.Kind){
+        case TraitSelector::device_arch:{
+          bool ArchMatch = false;
+          for (const OMPTraitProperty &Property : Selector.Properties){
+            for (auto &T : getLangOpts().OMPTargetTriples){
+              if (T.getArchName() == Property.RawString){
+                ArchMatch = true;
+                break;
+              }
+            }
+            if (ArchMatch)
+              break;
+          }
+          // Create a true/false boolean expression and assign to WhenCondExpr
+          auto *C = new (Context)
+              CXXBoolLiteralExpr(ArchMatch, Context.BoolTy, StartLoc);
+          WhenCondExpr = dyn_cast<Expr>(C);
+          break;
+        }
+        case TraitSelector::user_condition:{
+          assert(Selector.ScoreOrCondition &&
+                 "Ill-formed user condition, expected condition expression!");
+
+          WhenCondExpr = Selector.ScoreOrCondition;
+          break;
+        }
+        case TraitSelector::implementation_vendor:{
+          bool vendorMatch = false;
+          for (const OMPTraitProperty &Property : Selector.Properties){
+            for (auto &T : getLangOpts().OMPTargetTriples){
+              if (T.getVendorName() == Property.RawString){
+                vendorMatch = true;
+                break;
+              }
+            }
+            if (vendorMatch)
+              break;
+          }
+          // Create a true/false boolean expression and assign to WhenCondExpr
+          auto *WhenCondition = new (Context)
+              CXXBoolLiteralExpr(vendorMatch, Context.BoolTy, StartLoc);
+          WhenCondExpr = dyn_cast<Expr>(WhenCondition);
+          break;
+        }
+        case TraitSelector::device_isa:
+        case TraitSelector::device_kind:
+        case TraitSelector::implementation_extension:
+        default:
+          break;
+        }
+      }
+    }
+
+    if (WhenCondExpr == nullptr) {
+      if (ElseStmt != nullptr) {
+        Diag(WhenClause->getBeginLoc(), diag::err_omp_misplaced_default_clause);
+        return StmtError();
+      }
+      if (DKind == OMPD_unknown)
+        ElseStmt = CompoundStmt::Create(Context, {CS->getCapturedStmt()},
+                                        FPOptionsOverride(), SourceLocation(),
+                                        SourceLocation());
+      else
+        ElseStmt = ThenStmt;
+      continue;
+    }
+
+    if (ThenStmt == NULL)
+      ThenStmt = CompoundStmt::Create(Context, {CS->getCapturedStmt()},
+                                      FPOptionsOverride(), SourceLocation(),
+                                      SourceLocation());
+
+    IfStmt =
+        ActOnIfStmt(SourceLocation(), /*false*/ IfStatementKind::Ordinary, SourceLocation(), nullptr,
+                    ActOnCondition(getCurScope(), SourceLocation(),
+                                   WhenCondExpr, Sema::ConditionKind::Boolean),
+                    SourceLocation(), ThenStmt, SourceLocation(), ElseStmt);
+    ElseStmt = IfStmt.get();
+  }
+
+  return OMPMetaDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+                                  IfStmt.get());                                            
+}
+
 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
                                               Stmt *AStmt,
                                               SourceLocation StartLoc,
-                                              SourceLocation EndLoc) {
+                                              SourceLocation EndLoc){
   if (!AStmt)
     return StmtError();
 
@@ -16690,6 +16821,17 @@
   return std::string(Out.str());
 }
 
+OMPClause *
+Sema::ActOnOpenMPWhenClause(OMPTraitInfo &TI, OpenMPDirectiveKind DKind,
+                            StmtResult Directive, SourceLocation StartLoc,
+                            SourceLocation LParenLoc, SourceLocation EndLoc) {
+  return new (Context)
+      OMPWhenClause(TI, DKind, Directive.get(), StartLoc, LParenLoc, EndLoc);
+}
+
+
+
+
 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
                                           SourceLocation KindKwLoc,
                                           SourceLocation StartLoc,
Index: clang/lib/Parse/ParseOpenMP.cpp
===================================================================
--- clang/lib/Parse/ParseOpenMP.cpp
+++ clang/lib/Parse/ParseOpenMP.cpp
@@ -2536,10 +2536,12 @@
 
     BalancedDelimiterTracker T(*this, tok::l_paren,
                                tok::annot_pragma_openmp_end);
+                                                          
     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
       OpenMPClauseKind CKind = Tok.isAnnotation()
                                    ? OMPC_unknown
                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
+                                   
       SourceLocation Loc = ConsumeToken();
 
       // Parse '('.
@@ -2557,7 +2559,7 @@
           return Directive;
         }
 
-        // Parse ':'
+        // Parse ':' // You have parsed the OpenMP Context in the meta directive 
         if (Tok.is(tok::colon))
           ConsumeAnyToken();
         else {
@@ -2566,6 +2568,7 @@
           return Directive;
         }
       }
+      
       // Skip Directive for now. We will parse directive in the second iteration
       int paren = 0;
       while (Tok.isNot(tok::r_paren) || paren != 0) {
@@ -2579,62 +2582,56 @@
           TPA.Commit();
           return Directive;
         }
-        ConsumeAnyToken();
-      }
+        ConsumeAnyToken();  
+      } 
+      
       // Parse ')'
       if (Tok.is(tok::r_paren))
         T.consumeClose();
-
+      
       VariantMatchInfo VMI;
       TI.getAsVariantMatchInfo(ASTContext, VMI);
-
-      VMIs.push_back(VMI);
-    }
-
+      
+      if (CKind == OMPC_when )	
+     		 VMIs.push_back(VMI);
+    } 
+    
+    // This is the end of the first iteration
+    // The pointer is moved back
     TPA.Revert();
     // End of the first iteration. Parser is reset to the start of metadirective
 
+
     std::function<void(StringRef)> DiagUnknownTrait =
         [this, Loc](StringRef ISATrait) {
           // TODO Track the selector locations in a way that is accessible here
           // to improve the diagnostic location.
           Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
         };
-    TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
+    // TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
+
+    TargetOMPContext OMPCtx(ASTContext, /* DiagUnknownTrait */ nullptr,
                             /* CurrentFunctionDecl */ nullptr,
                             ArrayRef<llvm::omp::TraitProperty>());
-
-    // A single match is returned for OpenMP 5.0
-    int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
-
-    int Idx = 0;
-    // In OpenMP 5.0 metadirective is either replaced by another directive or
-    // ignored.
-    // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
-    // found by getBestWhenMatchForContext.
-    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
-      // OpenMP 5.0 implementation - Skip to the best index found.
-      if (Idx++ != BestIdx) {
-        ConsumeToken();  // Consume clause name
-        T.consumeOpen(); // Consume '('
-        int paren = 0;
-        // Skip everything inside the clause
-        while (Tok.isNot(tok::r_paren) || paren != 0) {
-          if (Tok.is(tok::l_paren))
-            paren++;
-          if (Tok.is(tok::r_paren))
-            paren--;
-          ConsumeAnyToken();
-        }
-        // Parse ')'
-        if (Tok.is(tok::r_paren))
-          T.consumeClose();
-        continue;
-      }
-
+    
+    // Array SortedCluases will be used for sorting  clauses
+    // based on the context selector score                      
+    SmallVector<std::pair<unsigned, llvm::APInt>> SortedCluases;
+    
+    // The function will get the score for each clause and sort it 
+    // based on the score number
+    
+    getArrayVariantMatchForContext(VMIs, OMPCtx, SortedCluases) ;          
+                              	    
+    ParseScope OMPDirectiveScope(this, ScopeFlags);	
+    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);  
+    
+    while(Tok.isNot(tok::annot_pragma_openmp_end)){
+   	
       OpenMPClauseKind CKind = Tok.isAnnotation()
                                    ? OMPC_unknown
                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
+
       SourceLocation Loc = ConsumeToken();
 
       // Parse '('.
@@ -2662,9 +2659,71 @@
           StmtCtx,
           /*ReadDirectiveWithinMetadirective=*/true);
       break;
+                                   
+      Actions.StartOpenMPClause(CKind);
+      OMPClause *Clause = ParseOpenMPMetaDirectiveClause( DKind, CKind);
+      
+      FirstClauses[(unsigned) CKind].setInt(true);
+      if (Clause) {
+      	FirstClauses[(unsigned) CKind].setPointer(Clause);
+      	Clauses.push_back(Clause);
+      }	
+      
+      if (Tok.is(tok::comma))
+      	ConsumeToken();
+      
+      Actions.EndOpenMPClause();
+      
+      if (Tok.is(tok::r_paren))
+      	ConsumeAnyToken();	
+      		
     }
-    break;
-  }
+   
+    // End location of the directive
+    EndLoc = Tok.getLocation();
+   
+    //Consume final annot_pragma_openmp_end
+    ConsumeAnnotationToken();
+   
+    SmallVector<OMPClause *, 5> Clauses_new;
+    unsigned count = 0;
+   
+    // SortedClauses has index and score, and are sorted with respect to the
+    // the context score. The first iteration will take each element. The 
+    // first element will have the highiest score. The element will have the
+    // index of the cluase for the best score. The second iteration tries to
+    // find that specific clause by checking the count numder with the 
+    // index (Iteration1.first)  
+    for ( auto &Iteration1 : SortedCluases){
+   	count = 0;
+   	for ( auto &Iteration2 : Clauses){
+   		if ( count == Iteration1.first ){
+   			Clauses_new.push_back(Iteration2);
+   			break;
+   		} else count++;
+   	}
+    }
+   // Adding the default clasue at the end
+   Clauses_new.push_back(Clauses.back());
+   
+   // Parsing the OpenMP region which will take the
+   // metadirective
+   
+   Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
+   ParsingOpenMPDirectiveRAII NormalScope(*this, /*value=*/ false);
+   // This is parsing the region
+   StmtResult AStmt = ParseStatement();
+   
+   StmtResult AssociatedStmt = (Sema::CompoundScopeRAII(Actions), AStmt);
+   // Ending of the parallel region
+   AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses_new);
+   Directive = Actions.ActOnOpenMPExecutableDirective(
+   	DKind, DirName, CancelRegion, Clauses_new, AssociatedStmt.get(), Loc, 
+   	EndLoc);
+   // Exit scope
+   Actions.EndOpenMPDSABlock(Directive.get());
+   break;
+  } // end of case OMPD_metadirective:
   case OMPD_threadprivate: {
     // FIXME: Should this be permitted in C++?
     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
@@ -3136,6 +3195,164 @@
   return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(),
                                                 T.getCloseLocation(), Data);
 }
+/// Parsing of OpenMP MetaDirective Clauses
+
+OMPClause *Parser::ParseOpenMPMetaDirectiveClause(OpenMPDirectiveKind DKind,
+                                         OpenMPClauseKind CKind) {
+  OMPClause *Clause = nullptr;
+  bool ErrorFound = false;
+  bool WrongDirective = false;
+  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
+              llvm::omp::Clause_enumSize + 1>
+      FirstClauses(llvm::omp::Clause_enumSize + 1);
+
+  // Check if it is called from metadirective.
+  if (DKind != OMPD_metadirective) {
+    Diag(Tok, diag::err_omp_unexpected_clause)
+        << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+    ErrorFound = true;
+  }
+
+  // Check if clause is allowed for the given directive.
+  if (CKind != OMPC_unknown &&
+      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
+    Diag(Tok, diag::err_omp_unexpected_clause)
+        << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+    ErrorFound = true;
+    WrongDirective = true;
+  }
+
+ // Check if clause is not allowed
+ if (CKind == OMPC_unknown) {
+    Diag(Tok, diag::err_omp_unexpected_clause)
+        << getOpenMPClauseName(CKind) << "Unknown clause: Not allowed";
+    ErrorFound = true;
+    WrongDirective = true;
+  }
+	
+  if (CKind == OMPC_default || CKind == OMPC_when) {
+    SourceLocation Loc = ConsumeToken();
+    SourceLocation DelimLoc;
+    // Parse '('.
+    BalancedDelimiterTracker T(*this, tok::l_paren,
+                               tok::annot_pragma_openmp_end);
+    if (T.expectAndConsume(diag::err_expected_lparen_after,
+                           getOpenMPClauseName(CKind).data()))
+      return nullptr;
+
+    OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
+    if (CKind == OMPC_when) {
+      // parse and get condition expression to pass to the When clause
+      parseOMPContextSelectors(Loc, TI);
+
+      // Parse ':'
+      if (Tok.is(tok::colon))
+        ConsumeAnyToken();
+      else {
+        Diag(Tok, diag::warn_pragma_expected_colon) << "when clause";
+        return nullptr;
+      }
+    }
+
+    // Parse Directive
+    OpenMPDirectiveKind DirKind = OMPD_unknown;
+    SmallVector<OMPClause *, 5> Clauses;
+    StmtResult AssociatedStmt;
+    StmtResult Directive = StmtError();
+
+    if (Tok.isNot(tok::r_paren)) {
+      ParsingOpenMPDirectiveRAII DirScope(*this);
+      ParenBraceBracketBalancer BalancerRAIIObj(*this);
+      DeclarationNameInfo DirName;
+      unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
+                            Scope::CompoundStmtScope |
+                            Scope::OpenMPDirectiveScope;
+
+      DirKind = parseOpenMPDirectiveKind(*this);
+      ConsumeToken();
+      ParseScope OMPDirectiveScope(this, ScopeFlags);
+      Actions.StartOpenMPDSABlock(DirKind, DirName, Actions.getCurScope(), Loc);
+      
+      int paren = 0;
+      
+      while (Tok.isNot(tok::r_paren) || paren != 0) {
+        if (Tok.is(tok::l_paren))
+          paren++;
+        if (Tok.is(tok::r_paren))
+          paren--;
+	
+        OpenMPClauseKind CKind = Tok.isAnnotation()
+                                     ? OMPC_unknown
+                                     : getOpenMPClauseKind(PP.getSpelling(Tok));
+         
+        if (CKind == OMPC_unknown &&
+      		!isAllowedClauseForDirective(DirKind, CKind, getLangOpts().OpenMP)) {
+    		Diag(Tok, diag::err_omp_unexpected_clause)
+        		<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+    		ErrorFound = true;
+    		WrongDirective = true;
+  	}
+                               
+        Actions.StartOpenMPClause(CKind);
+        OMPClause *Clause = ParseOpenMPClause(
+            DirKind, CKind, !FirstClauses[(unsigned)CKind].getInt());
+        FirstClauses[(unsigned)CKind].setInt(true);
+        if (Clause) {
+          FirstClauses[(unsigned)CKind].setPointer(Clause);
+          Clauses.push_back(Clause);
+        }
+
+        // Skip ',' if any.
+        if (Tok.is(tok::comma))
+          ConsumeToken();
+        Actions.EndOpenMPClause();
+      }
+	
+      Actions.ActOnOpenMPRegionStart(DirKind, getCurScope());
+      ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
+
+      /* Get Stmt and revert back */
+      TentativeParsingAction TPA(*this);
+      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+        ConsumeAnyToken();
+      }
+      
+      ConsumeAnnotationToken();
+      ParseScope InnerStmtScope(this, Scope::DeclScope,
+                                getLangOpts().C99 || getLangOpts().CPlusPlus,
+                                Tok.is(tok::l_brace));
+                                                      
+      StmtResult AStmt = ParseStatement();
+      InnerStmtScope.Exit();
+      TPA.Revert();
+      /* End Get Stmt */
+
+      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), AStmt);
+      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+	
+      Directive = Actions.ActOnOpenMPExecutableDirective(
+          DirKind, DirName, OMPD_unknown, llvm::makeArrayRef(Clauses),
+          AssociatedStmt.get(), Loc, Tok.getLocation());
+	
+      Actions.EndOpenMPDSABlock(Directive.get());
+      OMPDirectiveScope.Exit();
+    }
+    // Parse ')'
+    T.consumeClose();
+
+    if (WrongDirective)
+      return nullptr;
+
+    Clause = Actions.ActOnOpenMPWhenClause(TI, DirKind, Directive, Loc,
+                                           DelimLoc, Tok.getLocation());
+  } else {
+    ErrorFound = false;
+    Diag(Tok, diag::err_omp_unexpected_clause)
+        << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);     
+  }
+ 		
+  return ErrorFound ? nullptr : Clause;
+}
 
 /// Parsing of OpenMP clauses.
 ///
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -719,11 +719,20 @@
                                               bool ForceNoStmt) {
   OMPClausePrinter Printer(OS, Policy);
   ArrayRef<OMPClause *> Clauses = S->clauses();
-  for (auto *Clause : Clauses)
-    if (Clause && !Clause->isImplicit()) {
+  for (auto *Clause : Clauses){    
+    if (Clause && !Clause->isImplicit()){
       OS << ' ';
       Printer.Visit(Clause);
-    }
+      if (isa<OMPMetaDirective>(S)){
+      	OMPWhenClause *WhenClause = dyn_cast<OMPWhenClause>(Clause);
+      	if (WhenClause!=nullptr){
+      	  if (WhenClause->getDKind() != llvm::omp::OMPD_unknown){
+      	   	Printer.VisitOMPWhenClause(WhenClause);
+      	    }
+      	 }
+      }
+    }	
+   }
   OS << NL;
   if (!ForceNoStmt && S->hasAssociatedStmt())
     PrintStmt(S->getRawStmt());
Index: clang/lib/AST/OpenMPClause.cpp
===================================================================
--- clang/lib/AST/OpenMPClause.cpp
+++ clang/lib/AST/OpenMPClause.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/StmtOpenMP.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/OpenMPKinds.h"
 #include "clang/Basic/TargetInfo.h"
@@ -180,7 +181,8 @@
   return Res ? const_cast<OMPClauseWithPostUpdate *>(Res) : nullptr;
 }
 
-const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) {
+const OMPClauseWithPostUpdate *
+OMPClauseWithPostUpdate::get(const OMPClause *C) {
   switch (C->getClauseKind()) {
   case OMPC_lastprivate:
     return static_cast<const OMPLastprivateClause *>(C);
@@ -610,7 +612,8 @@
                                               unsigned NumVars) {
   // Allocate space for 5 lists (Vars, Inits, Updates, Finals), 2 expressions
   // (Step and CalcStep), list of used expression + step.
-  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2 + NumVars  +1));
+  void *Mem =
+      C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2 + NumVars + 1));
   return new (Mem) OMPLinearClause(NumVars);
 }
 
@@ -1059,7 +1062,7 @@
   Clause->setOmpAllMemoryLoc(Data.OmpAllMemoryLoc);
   Clause->setModifier(DepModifier);
   Clause->setVarRefs(VL);
-  for (unsigned I = 0 ; I < NumLoops; ++I)
+  for (unsigned I = 0; I < NumLoops; ++I)
     Clause->setLoopData(I, nullptr);
   return Clause;
 }
@@ -1667,6 +1670,31 @@
 //  OpenMP clauses printing methods
 //===----------------------------------------------------------------------===//
 
+void OMPClausePrinter::VisitOMPWhenClause(OMPWhenClause *Node) {
+  OMPTraitInfo &TI = Node->getTI();
+  if (TI.Sets.empty())
+    OS << "default(";
+  else
+    OS << "when(";
+  TI.print(OS, Policy);
+
+  if (Stmt *S = Node->getDirective()) {
+    OS << ":";
+    OMPExecutableDirective *D = cast<OMPExecutableDirective>(S);
+    auto DKind = D->getDirectiveKind();
+    OS << getOpenMPDirectiveName(DKind);
+
+    OMPClausePrinter Printer(OS, Policy);
+    ArrayRef<OMPClause *> Clauses = D->clauses();
+    for (auto *Clause : Clauses)
+      if (Clause && !Clause->isImplicit()) {
+        OS << ' ';
+        Printer.Visit(Clause);
+      }
+  }
+  OS << ")";
+}
+
 void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
   OS << "if(";
   if (Node->getNameModifier() != OMPD_unknown)
@@ -2011,7 +2039,7 @@
   }
 }
 
-template<typename T>
+template <typename T>
 void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
   for (typename T::varlist_iterator I = Node->varlist_begin(),
                                     E = Node->varlist_end();
@@ -2307,8 +2335,9 @@
 }
 
 void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
-  OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
-                           OMPC_dist_schedule, Node->getDistScheduleKind());
+  OS << "dist_schedule("
+     << getOpenMPSimpleClauseTypeName(OMPC_dist_schedule,
+                                      Node->getDistScheduleKind());
   if (auto *E = Node->getChunkSize()) {
     OS << ", ";
     E->printPretty(OS, nullptr, Policy);
@@ -2353,7 +2382,8 @@
   }
 }
 
-void OMPClausePrinter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *Node) {
+void OMPClausePrinter::VisitOMPHasDeviceAddrClause(
+    OMPHasDeviceAddrClause *Node) {
   if (!Node->varlist_empty()) {
     OS << "has_device_addr";
     VisitOMPClauseList(Node, '(');
@@ -2483,8 +2513,7 @@
       // TODO: This might not hold once we implement SIMD properly.
       assert(Selector.Properties.size() == 1 &&
              Selector.Properties.front().Kind ==
-                 getOpenMPContextTraitPropertyForSelector(
-                     Selector.Kind) &&
+                 getOpenMPContextTraitPropertyForSelector(Selector.Kind) &&
              "Ill-formed construct selector!");
     }
   }
@@ -2508,8 +2537,8 @@
 
       bool AllowsTraitScore = false;
       bool RequiresProperty = false;
-      isValidTraitSelectorForTraitSet(
-          Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
+      isValidTraitSelectorForTraitSet(Selector.Kind, Set.Kind, AllowsTraitScore,
+                                      RequiresProperty);
 
       if (!RequiresProperty)
         continue;
@@ -2552,12 +2581,11 @@
 
       bool AllowsTraitScore = false;
       bool RequiresProperty = false;
-      isValidTraitSelectorForTraitSet(
-          Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
+      isValidTraitSelectorForTraitSet(Selector.Kind, Set.Kind, AllowsTraitScore,
+                                      RequiresProperty);
       OS << '$' << 's' << unsigned(Selector.Kind);
 
-      if (!RequiresProperty ||
-          Selector.Kind == TraitSelector::user_condition)
+      if (!RequiresProperty || Selector.Kind == TraitSelector::user_condition)
         continue;
 
       for (const OMPTraitProperty &Property : Selector.Properties)
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -66,6 +66,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
+#include "llvm/Frontend/OpenMP/OMPContext.h"
 #include <deque>
 #include <memory>
 #include <string>
@@ -11202,10 +11203,18 @@
   ///
   /// \returns Statement for finished OpenMP region.
   StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef<OMPClause *> Clauses);
+  
+  /// Called on well-formed
   StmtResult ActOnOpenMPExecutableDirective(
       OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
       OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
       Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
+   
+  /// Called on meta directive    
+  StmtResult ActOnOpenMPExecutableMetaDirective( 
+      OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, 
+      OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
+      Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
   /// Called on well-formed '\#pragma omp parallel' after parsing
   /// of the  associated statement.
   StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
@@ -11708,7 +11717,9 @@
                                      SourceLocation LParenLoc,
                                      SourceLocation EndLoc);
   /// Called on well-formed 'when' clause.
-  OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc,
+  OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, OpenMPDirectiveKind DKind,
+                                   StmtResult Directive,
+                                   SourceLocation StartLoc,
                                    SourceLocation LParenLoc,
                                    SourceLocation EndLoc);
   /// Called on well-formed 'default' clause.
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -3367,6 +3367,14 @@
   /// metadirective and therefore ends on the closing paren.
   StmtResult ParseOpenMPDeclarativeOrExecutableDirective(
       ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective = false);
+
+  /// Parse clause for metadirective
+  ///
+  /// \param Dkind Kind of current directive
+  /// \param CKind Kind of current clause
+  /// 
+  OMPClause *ParseOpenMPMetaDirectiveClause(OpenMPDirectiveKind DKind,
+                                            OpenMPClauseKind CKind);
   /// Parses clause of kind \a CKind for directive of a kind \a Kind.
   ///
   /// \param DKind Kind of current directive.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11086,6 +11086,8 @@
 def warn_omp_unterminated_declare_target : Warning<
   "expected '#pragma omp end declare target' at end of file to match '#pragma omp %0'">,
   InGroup<SourceUsesOpenMP>;
+def err_omp_misplaced_default_clause : Error<
+  "Only one 'default clause' is allowed">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
Index: clang/include/clang/AST/StmtOpenMP.h
===================================================================
--- clang/include/clang/AST/StmtOpenMP.h
+++ clang/include/clang/AST/StmtOpenMP.h
@@ -300,7 +300,7 @@
   template <typename T, typename... Params>
   static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
                             Stmt *AssociatedStmt, unsigned NumChildren,
-                            Params &&... P) {
+                            Params &&...P) {
     void *Mem =
         C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
                                                  NumChildren),
@@ -316,7 +316,7 @@
   template <typename T, typename... Params>
   static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
                                  bool HasAssociatedStmt, unsigned NumChildren,
-                                 Params &&... P) {
+                                 Params &&...P) {
     void *Mem =
         C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
                                                  NumChildren),
@@ -478,8 +478,7 @@
 
   /// Returns true if the current directive has one or more clauses of a
   /// specific kind.
-  template <typename SpecificClause>
-  bool hasClausesOfKind() const {
+  template <typename SpecificClause> bool hasClausesOfKind() const {
     auto Clauses = getClausesOfKind<SpecificClause>();
     return Clauses.begin() != Clauses.end();
   }
@@ -2711,7 +2710,6 @@
   static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
                                             unsigned NumClauses, EmptyShell);
 
-
   /// Returns reference to the task_reduction return variable.
   const Expr *getReductionRef() const {
     return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
@@ -4621,10 +4619,10 @@
   /// \param AssociatedStmt Statement, associated with the directive.
   /// \param Exprs Helper expressions for CodeGen.
   ///
-  static OMPDistributeParallelForSimdDirective *Create(
-      const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
-      unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
-      Stmt *AssociatedStmt, const HelperExprs &Exprs);
+  static OMPDistributeParallelForSimdDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
   /// Creates an empty directive with the place for \a NumClauses clauses.
   ///
@@ -4632,9 +4630,9 @@
   /// \param CollapsedNum Number of collapsed nested loops.
   /// \param NumClauses Number of clauses.
   ///
-  static OMPDistributeParallelForSimdDirective *CreateEmpty(
-      const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
-      EmptyShell);
+  static OMPDistributeParallelForSimdDirective *
+  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+              EmptyShell);
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass;
@@ -4831,8 +4829,7 @@
   ///
   static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
                                              unsigned NumClauses,
-                                             unsigned CollapsedNum,
-                                             EmptyShell);
+                                             unsigned CollapsedNum, EmptyShell);
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPTargetSimdDirectiveClass;
@@ -5169,11 +5166,9 @@
   /// \param Clauses List of clauses.
   /// \param AssociatedStmt Statement, associated with the directive.
   ///
-  static OMPTargetTeamsDirective *Create(const ASTContext &C,
-                                         SourceLocation StartLoc,
-                                         SourceLocation EndLoc,
-                                         ArrayRef<OMPClause *> Clauses,
-                                         Stmt *AssociatedStmt);
+  static OMPTargetTeamsDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
   /// Creates an empty directive with the place for \a NumClauses clauses.
   ///
@@ -5244,9 +5239,10 @@
   /// \param CollapsedNum Number of collapsed nested loops.
   /// \param NumClauses Number of clauses.
   ///
-  static OMPTargetTeamsDistributeDirective *
-  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
-              EmptyShell);
+  static OMPTargetTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
+                                                        unsigned NumClauses,
+                                                        unsigned CollapsedNum,
+                                                        EmptyShell);
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -499,7 +499,8 @@
   /// Process clauses with pre-initis.
   bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node);
   bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node);
-
+  bool VisitOMPWhenClause(OMPWhenClause *C);
+  
   bool PostVisitStmt(Stmt *S);
 };
 
@@ -3273,6 +3274,18 @@
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPWhenClause(OMPWhenClause *C) {
+  for (const OMPTraitSet &Set : C->getTI().Sets) {
+    for (const OMPTraitSelector &Selector : Set.Selectors) {
+      if (Selector.Kind == llvm::omp::TraitSelector::user_condition &&
+          Selector.ScoreOrCondition)
+        TRY_TO(TraverseStmt(Selector.ScoreOrCondition));
+    }
+  }
+  return true;
+}
+
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
   return true;
Index: clang/include/clang/AST/OpenMPClause.h
===================================================================
--- clang/include/clang/AST/OpenMPClause.h
+++ clang/include/clang/AST/OpenMPClause.h
@@ -8734,25 +8734,7 @@
 template<class ImplClass, typename RetTy = void>
 class ConstOMPClauseVisitor :
       public OMPClauseVisitorBase <ImplClass, const_ptr, RetTy> {};
-
-class OMPClausePrinter final : public OMPClauseVisitor<OMPClausePrinter> {
-  raw_ostream &OS;
-  const PrintingPolicy &Policy;
-
-  /// Process clauses with list of variables.
-  template <typename T> void VisitOMPClauseList(T *Node, char StartSym);
-  /// Process motion clauses.
-  template <typename T> void VisitOMPMotionClause(T *Node);
-
-public:
-  OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
-      : OS(OS), Policy(Policy) {}
-
-#define GEN_CLANG_CLAUSE_CLASS
-#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);
-#include "llvm/Frontend/OpenMP/OMP.inc"
-};
-
+         
 struct OMPTraitProperty {
   llvm::omp::TraitProperty Kind = llvm::omp::TraitProperty::invalid;
 
@@ -8993,6 +8975,98 @@
   }
 };
 
+/// This captures 'when' clause in the '#pragma omp metadirective'
+/// \code
+/// #pragma omp metadirective when(user={condition(N<100)}:parallel for)
+/// \endcode
+/// In the above example, the metadirective has a condition clause which when
+/// satisfied will use the parallel for directive with the code enclosed by the
+/// directive.
+class OMPWhenClause final : public OMPClause {
+  friend class OMPClauseReader;
+  friend class OMPExecutableDirective;
+  template <typename T> friend class OMPDeclarativeDirective;	
+
+  OMPTraitInfo *TI;
+  OpenMPDirectiveKind DKind;
+  Stmt *Directive;
+
+  /// Location of '('.
+  SourceLocation LParenLoc;
+  
+  /// Sets the location of '('.
+  ///
+  /// \param Loc Location of '('.
+  void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+public:
+  /// Build 'when' clause with argument \a A ('none' or 'shared').
+  ///
+  /// \param T TraitInfor containing information about the context selector
+  /// \param DKind The directive associated with the when clause
+  /// \param D The statement associated with the when clause
+  /// \param StartLoc Starting location of the clause.
+  /// \param LParenLoc Location of '('.
+  /// \param EndLoc Ending location of the clause.
+  OMPWhenClause(OMPTraitInfo &T, OpenMPDirectiveKind dKind, Stmt *D,
+                SourceLocation StartLoc, SourceLocation LParenLoc,
+                SourceLocation EndLoc)
+      : OMPClause(llvm::omp::OMPC_when, StartLoc, EndLoc), TI(&T), DKind(dKind),
+        Directive(D), LParenLoc(LParenLoc) {}
+
+  /// Build an empty clause.
+  OMPWhenClause()
+      : OMPClause(llvm::omp::OMPC_when, SourceLocation(), SourceLocation()) {}
+
+  /// Returns the location of '('.
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+
+  /// Returns the directive variant kind
+  OpenMPDirectiveKind getDKind() const { return DKind; }
+
+  Stmt *getDirective() const { return Directive; }
+
+  /// Returns the OMPTraitInfo
+  OMPTraitInfo &getTI() const { return *TI; }
+
+  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_when;
+  }
+};
+
+class OMPClausePrinter final : public OMPClauseVisitor<OMPClausePrinter> {
+  raw_ostream &OS;
+  const PrintingPolicy &Policy;
+
+  /// Process clauses with list of variables.
+  template <typename T> void VisitOMPClauseList(T *Node, char StartSym);
+  /// Process motion clauses.
+  template <typename T> void VisitOMPMotionClause(T *Node);
+
+public:
+  OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
+      : OS(OS), Policy(Policy) {}
+      
+  void VisitOMPWhenClause(OMPWhenClause *Node);
+  
+#define GEN_CLANG_CLAUSE_CLASS
+#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);
+#include "llvm/Frontend/OpenMP/OMP.inc"
+};
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to