diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 715d15325719..3617786f0959 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -321,6 +321,7 @@ Bug Fixes in This Version - Fixed an assertion failure caused by error recovery while extending a nested name specifier with results from ordinary lookup. (#GH181470) - Fixed a crash when parsing ``#pragma clang attribute`` arguments for attributes that forbid arguments. (#GH182122) - Fixed a bug with multiple-include optimization (MIOpt) state not being preserved in some cases during lexing, which could suppress header-guard mismatch diagnostics and interfere with include-guard optimization. (#GH180155) +- Fixed a crash when normalizing constraints involving concept template parameters whose index coincided with non-concept template parameters in the same parameter mapping. Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a60d11d8eb36..34ed5dffa11b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4529,11 +4529,40 @@ ExprResult Sema::SubstConceptTemplateArguments( ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, bool IsAddressOfOperand = false) { - if (E->isConceptReference()) { - ExprResult Res = SemaRef.SubstExpr(E, MLTAL); - return Res; - } - return E; + if (!E->isConceptReference()) + return E; + + assert(E->getNumDecls() == 1 && + "ConceptReference must have single declaration"); + NamedDecl *D = *E->decls_begin(); + ConceptDecl *ResolvedConcept = nullptr; + + if (auto *TTP = dyn_cast(D)) { + unsigned Depth = TTP->getDepth(); + unsigned Pos = TTP->getPosition(); + if (Depth < MLTAL.getNumLevels() && + MLTAL.hasTemplateArgument(Depth, Pos)) { + TemplateArgument Arg = MLTAL(Depth, Pos); + assert(Arg.getKind() == TemplateArgument::Template); + ResolvedConcept = + dyn_cast(Arg.getAsTemplate().getAsTemplateDecl()); + } + if (ResolvedConcept == nullptr) + return E; + } else + ResolvedConcept = cast(D); + + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); + if (TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), TransArgs)) + return ExprError(); + + CXXScopeSpec SS; + DeclarationNameInfo NameInfo(ResolvedConcept->getDeclName(), + E->getNameLoc()); + return SemaRef.CheckConceptTemplateId(SS, SourceLocation(), NameInfo, + ResolvedConcept, ResolvedConcept, + &TransArgs, false); } }; diff --git a/clang/test/SemaCXX/cxx2c-template-template-param.cpp b/clang/test/SemaCXX/cxx2c-template-template-param.cpp index 704df3112277..6214e9690540 100644 --- a/clang/test/SemaCXX/cxx2c-template-template-param.cpp +++ b/clang/test/SemaCXX/cxx2c-template-template-param.cpp @@ -432,5 +432,41 @@ template concept C1> concept TestBinary = T::a || C1; static_assert(TestBinary); +} + +namespace concept_template_parameter_as_second_parameter { + +template +concept Any = true; + +template concept C> +concept Wrap = C; + +template U> +void f(T&&, U&&) {} + +void test() { + f(0, 1); +} + +} + +namespace multi_level_concept_template_parameter { + +template +concept Any = true; + +template concept C0, template concept C1> +concept Both = C0 && C1; + +template concept C> +concept Wrap = Both; + +template U> +void f(T&&, U&&) {} + +void test() { + f(0, 1); +} }