diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index b50648d5752ce5..7d83b86a007337 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5505,8 +5505,11 @@ static TemplateDeductionResult CheckDeductionConsistency( Sema::ArgumentPackSubstitutionIndexRAII PackIndex( S, ArgIdx != -1 ? ::getPackIndexForParam(S, FTD, MLTAL, ArgIdx) : -1); bool IsIncompleteSubstitution = false; - QualType InstP = S.SubstType(P, MLTAL, FTD->getLocation(), FTD->getDeclName(), - &IsIncompleteSubstitution); + // FIXME: A substitution can be incomplete on a non-structural part of the + // type. Use the canonical type for now, until the TemplateInstantiator can + // deal with that. + QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(), + FTD->getDeclName(), &IsIncompleteSubstitution); if (InstP.isNull() && !IsIncompleteSubstitution) return TemplateDeductionResult::SubstitutionFailure; if (!CheckConsistency) diff --git a/clang/test/SemaTemplate/GH18291.cpp b/clang/test/SemaTemplate/GH18291.cpp index 820564ffa6f1a0..2e9754b6561740 100644 --- a/clang/test/SemaTemplate/GH18291.cpp +++ b/clang/test/SemaTemplate/GH18291.cpp @@ -112,3 +112,12 @@ namespace static_vs_nonstatic { } } // namespace explicit_obj_param } // namespace static_vs_nonstatic + +namespace incomplete_on_sugar { + template void f(T[P]) = delete; + template void f(int[][P]); + void test() { + int array[1][8]; + f<8>(array); + } +} // namespace incomplete_on_sugar