llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Akash Manna (akash-manna-sky)

<details>
<summary>Changes</summary>

Fixes #<!-- -->144302

`lastprivate(i)` on a data member inside a member function template of a 
non-template class crashed in `EndOpenMPDSABlock`. In a dependent context the 
clause keeps the member as the `this-&gt;i` expression, but the finalizer cast 
every non-dependent item to `DeclRefExpr`.

Skip the member there and leave its private copy to be built when the template 
is instantiated, where the member gets captured as usual.

LLM Aided


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


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+2) 
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+7) 
- (added) clang/test/OpenMP/GH144302.cpp (+42) 
- (modified) clang/test/OpenMP/sections_ast_print.cpp (+20) 
- (modified) clang/test/OpenMP/sections_lastprivate_messages.cpp (+61) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index e6b71ba2a0b565..8abb2737fbb98d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1388,6 +1388,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was 
renamed to `alpha.core.Use
   the clause was parsed but its condition was discarded without effect.
 - Fixed a crash when the loop variable or a loop bound of an OpenMP loop has a
   `_BitInt` type wider than any standard integer type. (#GH140074)
+- Fixed a crash when a non-static data member appears in a `lastprivate` clause
+  inside a member function template of a non-template class. (#GH144302)
 - Loop-transforming constructs such as `tile` and `unroll` are now allowed
   inside a `simd` region for OpenMP 6.0 or later, which classifies them as
   simdizable.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 855c2fe8f41a06..baec4a77e2fe69 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3021,6 +3021,13 @@ void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
         PrivateCopies.push_back(nullptr);
         continue;
       }
+      // Data members are captured, and get private copies, on instantiation.
+      if (isa<MemberExpr>(DE->IgnoreParens())) {
+        assert(SemaRef.CurContext->isDependentContext() &&
+               "uncaptured data member in a non-dependent context");
+        PrivateCopies.push_back(nullptr);
+        continue;
+      }
       auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
       auto *D = DRE->getDecl();
       if (auto *BD = dyn_cast<BindingDecl>(D)) {
diff --git a/clang/test/OpenMP/GH144302.cpp b/clang/test/OpenMP/GH144302.cpp
new file mode 100644
index 00000000000000..d3200541007d75
--- /dev/null
+++ b/clang/test/OpenMP/GH144302.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -verify -fopenmp -fsyntax-only %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fsyntax-only %s
+// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu 
-emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+// The data member is not captured until the template is instantiated.
+struct B
+{
+  int i;
+  template<typename T>
+void foo();
+};
+
+template<typename T>
+void B::foo()
+{
+#pragma omp parallel
+  {
+  #pragma omp sections lastprivate (i)
+    {
+      i = 0;
+    }
+  }
+}
+
+template void B::foo<int>();
+
+int main() {
+  B b;
+  b.foo<int>();
+  return b.i;
+}
+
+// CHECK-LABEL: define {{.*}}void @_ZN1B3fooIiEEvv(
+// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @{{.+}}, i32 1, 
ptr @[[OUTLINED:_ZN1B3fooIiEEvv.omp_outlined]], ptr %{{.+}})
+
+// CHECK: define internal void @[[OUTLINED]](
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void @__kmpc_for_static_fini(
+// CHECK: .omp.lastprivate.then:
+// CHECK: .omp.lastprivate.done:
+// CHECK: call void @__kmpc_barrier(
diff --git a/clang/test/OpenMP/sections_ast_print.cpp 
b/clang/test/OpenMP/sections_ast_print.cpp
index 26bd47685ea7c2..84eb60f2e0b99f 100644
--- a/clang/test/OpenMP/sections_ast_print.cpp
+++ b/clang/test/OpenMP/sections_ast_print.cpp
@@ -30,6 +30,26 @@ T tmain(T argc) {
   return T();
 }
 
+struct S {
+  int a;
+  template <class T> void foo();
+};
+
+template <class T> void S::foo() {
+#pragma omp parallel
+#pragma omp sections firstprivate(a) lastprivate(this->a)
+  {
+    a = 0;
+  }
+}
+// CHECK: template <class T> void S::foo() {
+// CHECK-NEXT: #pragma omp parallel
+// CHECK-NEXT: #pragma omp sections firstprivate(this->a) 
lastprivate(this->a){{$}}
+// CHECK-NEXT: {
+// CHECK-NEXT: this->a = 0;
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
 int main(int argc, char **argv) {
 // CHECK: int main(int argc, char **argv) {
   int b = argc, c, d, e, f, g;
diff --git a/clang/test/OpenMP/sections_lastprivate_messages.cpp 
b/clang/test/OpenMP/sections_lastprivate_messages.cpp
index c182b4e71ae9ea..2898486b9a91a1 100644
--- a/clang/test/OpenMP/sections_lastprivate_messages.cpp
+++ b/clang/test/OpenMP/sections_lastprivate_messages.cpp
@@ -66,6 +66,67 @@ class S6 {
 S3 h;
 #pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or 
thread local}}
 
+// GH144302: data members in a member template of a non-template class.
+struct GH144302 {
+  int i;
+  const int c = 0; // expected-note {{'c' declared here}}
+  template <typename T> void foo();
+  template <typename T> void bar() {
+#pragma omp parallel
+#pragma omp sections lastprivate(c) // expected-error {{const-qualified 
variable cannot be lastprivate}}
+    {
+      foo<T>();
+    }
+  }
+};
+template <class U> struct GH144302T {
+  int i;
+  template <typename T> void foo() {
+#pragma omp parallel
+#pragma omp sections lastprivate(i)
+    {
+      i = 0;
+    }
+  }
+};
+int GH144302g;
+template <typename T> void GH144302::foo() {
+  int x = 0;
+#pragma omp parallel
+  {
+#pragma omp sections lastprivate(i)
+    {
+      i = 0;
+    }
+  }
+#pragma omp parallel
+#pragma omp sections lastprivate(this->i)
+  {
+    i = 0;
+  }
+#pragma omp parallel
+#pragma omp sections firstprivate(i) lastprivate(i)
+  {
+    i = 0;
+  }
+#pragma omp parallel for lastprivate(i)
+  for (int k = 0; k < 10; ++k)
+    i = k;
+#pragma omp parallel
+#pragma omp sections private(i)
+  {
+    i = 0;
+  }
+#pragma omp parallel
+#pragma omp sections lastprivate(x, GH144302g)
+  {
+    x = GH144302g = 0;
+  }
+  GH144302T<int> t;
+  t.foo<T>();
+}
+template void GH144302::foo<int>();
+
 template <class I, class C>
 int foomain(int argc, char **argv) {
   I e(4);

``````````

</details>


https://github.com/llvm/llvm-project/pull/237575
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to