Skip to content

[OpenMP] Patch for Support to loop bind clause : Checking Parent Region #76938

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 9, 2024

Conversation

SunilKuravinakop
Copy link
Contributor

Changes uploaded to the phabricator on Dec 16th are lost because the phabricator is down. Hence re-uploading it to the github.com.

Changes to be committed:
modified: clang/include/clang/Sema/Sema.h
modified: clang/lib/Sema/SemaOpenMP.cpp
modified: clang/test/OpenMP/generic_loop_ast_print.cpp
modified: clang/test/OpenMP/loop_bind_messages.cpp
modified: clang/test/PCH/pragma-loop.cpp

phabricator is down. Hence re-uploading it to the github.com.

  Changes to be committed:
 	modified:   clang/include/clang/Sema/Sema.h
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/generic_loop_ast_print.cpp
 	modified:   clang/test/OpenMP/loop_bind_messages.cpp
 	modified:   clang/test/PCH/pragma-loop.cpp
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang labels Jan 4, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 4, 2024

@llvm/pr-subscribers-clang

Author: None (SunilKuravinakop)

Changes

Changes uploaded to the phabricator on Dec 16th are lost because the phabricator is down. Hence re-uploading it to the github.com.

Changes to be committed:
modified: clang/include/clang/Sema/Sema.h
modified: clang/lib/Sema/SemaOpenMP.cpp
modified: clang/test/OpenMP/generic_loop_ast_print.cpp
modified: clang/test/OpenMP/loop_bind_messages.cpp
modified: clang/test/PCH/pragma-loop.cpp


Full diff: https://github.com/llvm/llvm-project/pull/76938.diff

5 Files Affected:

  • (modified) clang/include/clang/Sema/Sema.h (+6-2)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+42-20)
  • (modified) clang/test/OpenMP/generic_loop_ast_print.cpp (+2-2)
  • (modified) clang/test/OpenMP/loop_bind_messages.cpp (+170-10)
  • (modified) clang/test/PCH/pragma-loop.cpp (+6-2)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5e3b57ea33220b..3d8d94d200ac58 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11335,6 +11335,7 @@ class Sema final {
   /// on the parameter of the bind clause. In the methods for the
   /// mapped directives, check the parameters of the lastprivate clause.
   bool checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses);
+
   /// Depending on the bind clause of OMPD_loop map the directive to new
   /// directives.
   ///    1) loop bind(parallel) --> OMPD_for
@@ -11344,9 +11345,12 @@ class Sema final {
   /// rigorous semantic checking in the new mapped directives.
   bool mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
                         ArrayRef<OMPClause *> Clauses,
-                        OpenMPBindClauseKind BindKind,
+                        OpenMPBindClauseKind &BindKind,
                         OpenMPDirectiveKind &Kind,
-                        OpenMPDirectiveKind &PrevMappedDirective);
+                        OpenMPDirectiveKind &PrevMappedDirective,
+                        SourceLocation StartLoc, SourceLocation EndLoc,
+                        const DeclarationNameInfo &DirName,
+                        OpenMPDirectiveKind CancelRegion);
 
 public:
   /// The declarator \p D defines a function in the scope \p S which is nested
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index f34d2959dc6191..6e060e5b8ee268 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5072,6 +5072,18 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
         CurrentRegion != OMPD_cancellation_point &&
         CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
       return false;
+    // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
+    // for a detailed explanation
+    if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
+        ((BindKind == OMPC_BIND_parallel) || (BindKind == OMPC_BIND_teams)) &&
+        (isOpenMPWorksharingDirective(ParentRegion) ||
+         ParentRegion == OMPD_loop)) {
+      int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
+      SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
+          << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
+          << getOpenMPDirectiveName(CurrentRegion);
+      return true;
+    }
     if (CurrentRegion == OMPD_cancellation_point ||
         CurrentRegion == OMPD_cancel) {
       // OpenMP [2.16, Nesting of Regions]
@@ -6124,35 +6136,36 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
 
 bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
                             ArrayRef<OMPClause *> Clauses,
-                            OpenMPBindClauseKind BindKind,
+                            OpenMPBindClauseKind &BindKind,
                             OpenMPDirectiveKind &Kind,
-                            OpenMPDirectiveKind &PrevMappedDirective) {
+                            OpenMPDirectiveKind &PrevMappedDirective,
+                            SourceLocation StartLoc, SourceLocation EndLoc,
+                            const DeclarationNameInfo &DirName,
+                            OpenMPDirectiveKind CancelRegion) {
 
   bool UseClausesWithoutBind = false;
 
   // Restricting to "#pragma omp loop bind"
   if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
+
+    const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
+
     if (BindKind == OMPC_BIND_unknown) {
       // Setting the enclosing teams or parallel construct for the loop
       // directive without bind clause.
       BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
 
-      const OpenMPDirectiveKind ParentDirective =
-          DSAStack->getParentDirective();
       if (ParentDirective == OMPD_unknown) {
         Diag(DSAStack->getDefaultDSALocation(),
              diag::err_omp_bind_required_on_loop);
       } else if (ParentDirective == OMPD_parallel ||
-                 ParentDirective == OMPD_target_parallel) {
+                 ParentDirective == OMPD_target_parallel)
         BindKind = OMPC_BIND_parallel;
-      } else if (ParentDirective == OMPD_teams ||
-                 ParentDirective == OMPD_target_teams) {
-        BindKind = OMPC_BIND_teams;
-      }
     } else {
-      // bind clause is present, so we should set flag indicating to only
-      // use the clauses that aren't the bind clause for the new directive that
-      // loop is lowered to.
+      // bind clause is present in loop directive. When the loop directive is
+      // changed to a new directive the bind clause is not used. So, we should
+      // set flag indicating to only use the clauses that aren't the
+      // bind clause.
       UseClausesWithoutBind = true;
     }
 
@@ -6213,26 +6226,35 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
     OpenMPDirectiveKind PrevMappedDirective) {
   StmtResult Res = StmtError();
   OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
+  llvm::SmallVector<OMPClause *> ClausesWithoutBind;
+  bool UseClausesWithoutBind = false;
+
   if (const OMPBindClause *BC =
           OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
     BindKind = BC->getBindKind();
+
+  // Variable used to note down the DirectiveKind because mapLoopConstruct may
+  // change "Kind" variable, due to mapping of "omp loop" to other directives.
+  OpenMPDirectiveKind DK = Kind;
+  if ((Kind == OMPD_loop) || (PrevMappedDirective == OMPD_loop)) {
+    UseClausesWithoutBind = mapLoopConstruct(
+        ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
+        StartLoc, EndLoc, DirName, CancelRegion);
+    DK = OMPD_loop;
+  }
+
   // First check CancelRegion which is then used in checkNestingOfRegions.
   if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
-      checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
-                            BindKind, StartLoc))
+      checkNestingOfRegions(*this, DSAStack, DK, DirName, CancelRegion,
+                            BindKind, StartLoc)) {
     return StmtError();
+  }
 
   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
   if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
                             isOpenMPTargetDataManagementDirective(Kind)))
     Diag(StartLoc, diag::warn_hip_omp_target_directives);
 
-  llvm::SmallVector<OMPClause *> ClausesWithoutBind;
-  bool UseClausesWithoutBind = false;
-
-  UseClausesWithoutBind = mapLoopConstruct(ClausesWithoutBind, Clauses,
-                                           BindKind, Kind, PrevMappedDirective);
-
   llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
   VarsWithInheritedDSAType VarsWithInheritedDSA;
   bool ErrorFound = false;
diff --git a/clang/test/OpenMP/generic_loop_ast_print.cpp b/clang/test/OpenMP/generic_loop_ast_print.cpp
index df806405571cf7..30ade214289188 100644
--- a/clang/test/OpenMP/generic_loop_ast_print.cpp
+++ b/clang/test/OpenMP/generic_loop_ast_print.cpp
@@ -95,11 +95,11 @@ void test() {
   }
 
   //PRINT: #pragma omp target teams
-  //PRINT: #pragma omp distribute
+  //PRINT: #pragma omp simd
   //DUMP: OMPTargetTeamsDirective
   //DUMP: CapturedStmt
   //DUMP: ForStmt
-  //DUMP: OMPDistributeDirective
+  //DUMP: OMPSimdDirective
   #pragma omp target teams
   for (int i=0; i<1000; ++i) {
     #pragma omp loop
diff --git a/clang/test/OpenMP/loop_bind_messages.cpp b/clang/test/OpenMP/loop_bind_messages.cpp
index f7fdf289714328..9492a29ba69498 100644
--- a/clang/test/OpenMP/loop_bind_messages.cpp
+++ b/clang/test/OpenMP/loop_bind_messages.cpp
@@ -4,6 +4,7 @@
 
 #define NNN 50
 int aaa[NNN];
+int aaa2[NNN][NNN];
 
 void parallel_loop() {
   #pragma omp parallel
@@ -15,6 +16,91 @@ void parallel_loop() {
    }
 }
 
+void parallel_for_AND_loop_bind() {
+  #pragma omp parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_nowait() {
+  #pragma omp parallel
+  #pragma omp for nowait
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_for_with_nothing() {
+  #pragma omp parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp nothing
+    #pragma omp loop
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_targetfor_with_loop_bind() {
+  #pragma omp target teams distribute parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_targetparallel_with_loop() {
+  #pragma omp target parallel
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(parallel)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void loop_bind_AND_loop_bind() {
+  #pragma omp parallel for
+  for (int i = 0; i < 100; ++i) {
+    #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+    for (int i = 0 ; i < NNN ; i++) {
+      #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+      for (int j = 0 ; j < NNN ; j++) {
+        aaa[j] = j*NNN;
+      }
+    }
+  }
+}
+
+void parallel_with_sections_loop() {
+  #pragma omp parallel
+  {
+     #pragma omp sections
+     {
+        for (int i = 0 ; i < NNN ; i++) {
+          #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}}
+          for (int j = 0 ; j < NNN ; j++) {
+            aaa2[i][j] = i+j;
+          }
+        }
+
+        #pragma omp section
+	{
+          aaa[NNN-1] = NNN;
+        }
+     }
+  }
+}
+
 void teams_loop() {
   int var1, var2;
 
@@ -34,17 +120,23 @@ void teams_loop() {
    }
 }
 
-void orphan_loop_with_bind() {
-  #pragma omp loop bind(parallel) 
-  for (int j = 0 ; j < NNN ; j++) {
-    aaa[j] = j*NNN;
+void teams_targetteams_with_loop() {
+  #pragma omp target teams
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(teams)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
   }
 }
 
-void orphan_loop_no_bind() {
-  #pragma omp loop  // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}}
-  for (int j = 0 ; j < NNN ; j++) {
-    aaa[j] = j*NNN;
+void teams_targetfor_with_loop_bind() {
+  #pragma omp target teams distribute parallel for
+  for (int i = 0 ; i < NNN ; i++) {
+    #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa2[i][j] = i+j;
+    }
   }
 }
 
@@ -65,12 +157,80 @@ void teams_loop_reduction() {
    }
 }
 
+void teams_loop_distribute() {
+  int total = 0;
+
+  #pragma omp teams num_teams(8) thread_limit(256)
+  #pragma omp distribute parallel for dist_schedule(static, 1024) \
+                                      schedule(static, 64)
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(teams) // expected-error{{'distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0; j < NNN; j++) {
+      aaa2[i][j] = i+j;
+    }
+  }
+}
+
+void parallel_for_with_loop_teams_bind(){
+  #pragma omp parallel for
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}}
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa[i] = i+i*NNN;
+    }
+  }
+}
+
+void teams_with_loop_thread_bind(){
+  #pragma omp teams
+  for (int i = 0; i < NNN; i++) {
+    #pragma omp loop bind(thread)
+    for (int j = 0 ; j < NNN ; j++) {
+      aaa[i] = i+i*NNN;
+    }
+  }
+}
+
+void orphan_loop_no_bind() {
+  #pragma omp loop  // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}}
+  for (int j = 0 ; j < NNN ; j++) {
+    aaa[j] = j*NNN;
+  }
+}
+
+void orphan_loop_parallel_bind() {
+  #pragma omp loop bind(parallel)
+  for (int j = 0 ; j < NNN ; j++) {
+    aaa[j] = j*NNN;
+  }
+}
+
+void orphan_loop_teams_bind(){
+  #pragma omp loop bind(teams)
+  for (int i = 0; i < NNN; i++) {
+    aaa[i] = i+i*NNN;
+  }
+}
+
 int main(int argc, char *argv[]) {
   parallel_loop();
+  parallel_for_AND_loop_bind();
+  parallel_nowait();
+  parallel_for_with_nothing();
+  parallel_targetfor_with_loop_bind();
+  parallel_targetparallel_with_loop();
+  loop_bind_AND_loop_bind();
+  parallel_with_sections_loop();
   teams_loop();
-  orphan_loop_with_bind();
-  orphan_loop_no_bind();
+  teams_targetteams_with_loop();
+  teams_targetfor_with_loop_bind();
   teams_loop_reduction();
+  teams_loop_distribute();
+  parallel_for_with_loop_teams_bind();
+  teams_with_loop_thread_bind();
+  orphan_loop_no_bind();
+  orphan_loop_parallel_bind();
+  orphan_loop_teams_bind();
 }
 
 #endif
diff --git a/clang/test/PCH/pragma-loop.cpp b/clang/test/PCH/pragma-loop.cpp
index f5de630ffc9120..a3c6871041c0ee 100644
--- a/clang/test/PCH/pragma-loop.cpp
+++ b/clang/test/PCH/pragma-loop.cpp
@@ -116,9 +116,13 @@ class pragma_test {
 
   inline void run10(int *List, int Length) {
     int i = 0;
-#pragma omp loop bind(teams)
+    int j = 0;
+    #pragma omp teams
     for (int i = 0; i < Length; i++) {
-      List[i] = i;
+      #pragma omp loop bind(teams)
+      for (int j = 0; j < Length; j++) {
+        List[i] = i+j;
+      }
     }
   }
 

@SunilKuravinakop SunilKuravinakop changed the title loop bind : bug in checking Parent region loop bind : correction for bug in checking Parent region Jan 4, 2024
@SunilKuravinakop SunilKuravinakop changed the title loop bind : correction for bug in checking Parent region loop bind : patch correction for bug in checking Parent region Jan 4, 2024
@SunilKuravinakop SunilKuravinakop changed the title loop bind : patch correction for bug in checking Parent region [OpenMP] Patch for Support to loop bind clause : Checking Parent Region Jan 4, 2024
// Checks needed for mapping "loop" construct. Please check mapLoopConstruct
// for a detailed explanation
if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
((BindKind == OMPC_BIND_parallel) || (BindKind == OMPC_BIND_teams)) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop extra parens

@@ -11335,6 +11335,7 @@ class Sema final {
/// on the parameter of the bind clause. In the methods for the
/// mapped directives, check the parameters of the lastprivate clause.
bool checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change, drop it, make it in a separate NFC patch

// Variable used to note down the DirectiveKind because mapLoopConstruct may
// change "Kind" variable, due to mapping of "omp loop" to other directives.
OpenMPDirectiveKind DK = Kind;
if ((Kind == OMPD_loop) || (PrevMappedDirective == OMPD_loop)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra parens

Sunil Kuravinakop added 2 commits January 4, 2024 10:53
Removing an empty line which was added to seperate a function from
another. This was the only change in the file and hence will be adding
it as a separate NFC patch as suggested by Alexey.

 Changes to be committed:
	modified:   clang/include/clang/Sema/Sema.h
	modified:   clang/lib/Sema/SemaOpenMP.cpp
Comment on lines 6148 to 6151
} else if (ParentDirective == OMPD_teams ||
ParentDirective == OMPD_target_teams) {
BindKind = OMPC_BIND_teams;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you removed this? Remind me if we discussed it before.

Sunil Kuravinakop added 3 commits January 8, 2024 04:36
…eams" or "target teams", I had modified the if condition to use "isOpenMPTeamsDirective()" for the checks. However, this proved too restrictive and hence removed the check. Now, on Alexey pointing out the error, re-introduced the check to use "teams" or "target teams".

In the test case loop_bind_messages.cpp, Combined multiple tests into fewer functions.

  Changes to be committed:
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/loop_bind_messages.cpp
Comment on lines 6162 to 6166
ParentDirective == OMPD_target_parallel)
BindKind = OMPC_BIND_parallel;
} else if (ParentDirective == OMPD_teams ||
ParentDirective == OMPD_target_teams) {
BindKind = OMPC_BIND_teams;
}
} else if (ParentDirective == OMPD_teams ||
ParentDirective == OMPD_target_teams) {
BindKind = OMPC_BIND_teams;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please restore original code here

Sunil Kuravinakop added 2 commits January 8, 2024 12:22
Changes to testcase to reflect the changed code.

  Changes to be committed:
	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/generic_loop_ast_print.cpp
Copy link
Member

@alexey-bataev alexey-bataev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

@sandeepkosuri sandeepkosuri merged commit 782c525 into llvm:main Jan 9, 2024
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
…on (llvm#76938)

Changes uploaded to the phabricator on Dec 16th are lost because the
phabricator is down. Hence re-uploading it to the github.com.

  Changes to be committed:
 	modified:   clang/include/clang/Sema/Sema.h
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   clang/test/OpenMP/generic_loop_ast_print.cpp
 	modified:   clang/test/OpenMP/loop_bind_messages.cpp
 	modified:   clang/test/PCH/pragma-loop.cpp

---------

Co-authored-by: Sunil Kuravinakop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants