Author: Akash Manna Date: 2026-10-31T04:02:06Z New Revision: 3c6f58a02d1594adaa9144f7553331f2fb78872f
URL: https://github.com/llvm/llvm-project/commit/3c6f58a02d1594adaa9144f7553331f2fb78872f DIFF: https://github.com/llvm/llvm-project/commit/3c6f58a02d1594adaa9144f7553331f2fb78872f.diff LOG: [Clang][OpenMP] Fix crash on failed type substitution in declare reduction/mapper (#230059) 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! Added: clang/test/OpenMP/declare_reduction_ms_compat.cpp Modified: clang/docs/ReleaseNotes.md clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/OpenMP/declare_mapper_messages.cpp clang/test/OpenMP/declare_reduction_messages.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index f2cc86bf9ccc23..54a4f6fde79d27 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -799,6 +799,8 @@ documentation](CIR/index.md) for more information regarding ClangIR's status and - 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 ea154b2bbf4507..65c011024ce802 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4600,10 +4600,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(); } @@ -4692,10 +4694,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 f2101786f6ce02..cf9c339bc44ae7 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 f91d952dfa14fb..3d49a5d57cddae 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 00000000000000..96bacfa3f7aec7 --- /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@-1 {{use of undeclared identifier 'baz'; unqualified lookup into dependent bases of class template 'S' is a Microsoft extension}} + // expected-error@-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@-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; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
