[clang] [Clang][OpenMP] Fix crash on failed type substitution in declare reduction/mapper (PR #230059)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 8 04:13:35 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akash Manna (akash-manna-sky)
<details>
<summary>Changes</summary>
Fixes #<!-- -->223366
`VisitOMPDeclareReductionDecl` passed the substituted reduction type to `ActOnOpenMPDeclareReductionType` without checking it, so a failed substitution (null type) hit `assert(ParsedType.isUsable())`. `-fms-compatibility` is not needed: `typename T::type` with `T = int` crashes too. `declare mapper` had the same bug.
Both visitors now return early when the substituted type is null. The error is already reported by `SubstType`.
I used AI tools for assistance!
---
Full diff: https://github.com/llvm/llvm-project/pull/230059.diff
5 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+2)
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+10-6)
- (modified) clang/test/OpenMP/declare_mapper_messages.cpp (+20)
- (modified) clang/test/OpenMP/declare_reduction_messages.cpp (+16)
- (added) clang/test/OpenMP/declare_reduction_ms_compat.cpp (+25)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7ec126a065ae5..a7683d7532475 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -588,6 +588,8 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when an OpenMP `copyprivate` clause names a non-static data member that is not private in the
enclosing context, which is now diagnosed, a data member inside a member function template, or a structured
binding. (#GH217893)
+- Fixed a crash when template argument substitution fails in the type of an OpenMP `declare reduction` or
+ `declare mapper` directive. (#GH223366)
- Fixed an assertion failure when a variable implicitly mapped by an OpenMP `target` directive has a class type
(such as `std::map`) whose mapper lookup instantiates a class template specialization. (#GH154704)
- Fixed a bug where repeated #imports of modular headers in non-modular compilation were translated to #pragma clang module import. (#GH216924)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5e72f05c863a0..eaa82623eb6b6 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4569,10 +4569,12 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
D->getType()->containsUnexpandedParameterPack();
QualType SubstReductionType;
if (RequiresInstantiation) {
+ QualType T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(),
+ DeclarationName());
+ if (T.isNull())
+ return nullptr;
SubstReductionType = SemaRef.OpenMP().ActOnOpenMPDeclareReductionType(
- D->getLocation(),
- ParsedType::make(SemaRef.SubstType(
- D->getType(), TemplateArgs, D->getLocation(), DeclarationName())));
+ D->getLocation(), ParsedType::make(T));
} else {
SubstReductionType = D->getType();
}
@@ -4661,10 +4663,12 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
QualType SubstMapperTy;
DeclarationName VN = D->getVarName();
if (RequiresInstantiation) {
+ QualType T =
+ SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), VN);
+ if (T.isNull())
+ return nullptr;
SubstMapperTy = SemaRef.OpenMP().ActOnOpenMPDeclareMapperType(
- D->getLocation(),
- ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs,
- D->getLocation(), VN)));
+ D->getLocation(), ParsedType::make(T));
} else {
SubstMapperTy = D->getType();
}
diff --git a/clang/test/OpenMP/declare_mapper_messages.cpp b/clang/test/OpenMP/declare_mapper_messages.cpp
index f2101786f6ce0..cf9c339bc44ae 100644
--- a/clang/test/OpenMP/declare_mapper_messages.cpp
+++ b/clang/test/OpenMP/declare_mapper_messages.cpp
@@ -121,3 +121,23 @@ int fun(int arg) {
}
return arg;
}
+
+#if __cplusplus >= 201103L
+namespace GH223366 {
+struct HasType {
+ typedef int type;
+};
+
+template <typename T> using Vec = vec;
+
+template <typename T>
+void f() {
+#pragma omp declare mapper(id : Vec<typename T::type> v) map(v.len) // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+}
+
+void g() {
+ f<HasType>();
+ f<int>(); // expected-note {{in instantiation of function template specialization 'GH223366::f<int>' requested here}}
+}
+}
+#endif
diff --git a/clang/test/OpenMP/declare_reduction_messages.cpp b/clang/test/OpenMP/declare_reduction_messages.cpp
index f91d952dfa14f..3d49a5d57cdda 100644
--- a/clang/test/OpenMP/declare_reduction_messages.cpp
+++ b/clang/test/OpenMP/declare_reduction_messages.cpp
@@ -167,3 +167,19 @@ struct S
#pragma omp declare reduction (bar : S<1> : omp_out.foo(omp_in))
#endif
+
+namespace GH223366 {
+struct HasType {
+ typedef int type;
+};
+
+template <typename T>
+void f() {
+#pragma omp declare reduction(red : typename T::type : omp_out += omp_in) // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+}
+
+void g() {
+ f<HasType>();
+ f<int>(); // expected-note {{in instantiation of function template specialization 'GH223366::f<int>' requested here}}
+}
+}
diff --git a/clang/test/OpenMP/declare_reduction_ms_compat.cpp b/clang/test/OpenMP/declare_reduction_ms_compat.cpp
new file mode 100644
index 0000000000000..96bacfa3f7aec
--- /dev/null
+++ b/clang/test/OpenMP/declare_reduction_ms_compat.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -verify -fopenmp -fms-compatibility %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fms-compatibility %s
+
+struct foo {};
+struct has_baz {
+ typedef int baz;
+};
+
+template <typename T> struct S : T {
+ virtual void bar() {
+#pragma omp declare reduction(foo : baz : omp_out)
+ // expected-warning at -1 {{use of undeclared identifier 'baz'; unqualified lookup into dependent bases of class template 'S' is a Microsoft extension}}
+ // expected-error at -2 {{no type named 'baz' in 'S<foo>'}}
+ }
+};
+
+template <typename T> struct NotInstantiated : T {
+ virtual void bar() {
+#pragma omp declare reduction(foo : baz : omp_out)
+ // expected-warning at -1 {{use of undeclared identifier 'baz'; unqualified lookup into dependent bases of class template 'NotInstantiated' is a Microsoft extension}}
+ }
+};
+
+S<foo> s; // expected-note {{in instantiation of member function 'S<foo>::bar' requested here}}
+S<has_baz> t;
``````````
</details>
https://github.com/llvm/llvm-project/pull/230059
More information about the cfe-commits
mailing list