diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -161,10 +161,9 @@ if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) break; - } else if (FunctionTemplateDecl *FunTmpl - = Function->getDescribedFunctionTemplate()) { - // Add the "injected" template arguments. - Result.addOuterTemplateArguments(FunTmpl->getInjectedTemplateArgs()); + } else if (Function->getDescribedFunctionTemplate()) { + assert(Result.getNumSubstitutedLevels() == 0 && + "Outer template not instantiated?"); } // If this is a friend declaration and it declares an entity at @@ -180,11 +179,8 @@ } } else if (CXXRecordDecl *Rec = dyn_cast(Ctx)) { if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { - QualType T = ClassTemplate->getInjectedClassNameSpecialization(); - const TemplateSpecializationType *TST = - cast(Context.getCanonicalType(T)); - Result.addOuterTemplateArguments( - llvm::makeArrayRef(TST->getArgs(), TST->getNumArgs())); + assert(Result.getNumSubstitutedLevels() == 0 && + "Outer template not instantiated?"); if (ClassTemplate->isMemberSpecialization()) break; } diff --git a/clang/test/SemaTemplate/generic-lambda.cpp b/clang/test/SemaTemplate/generic-lambda.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaTemplate/generic-lambda.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// expected-no-diagnostics + +template constexpr bool is_same_v = false; +template constexpr bool is_same_v = true; +template +concept is_same = is_same_v; + +template struct X {}; +template +concept C1 = is_same>; + +template X>> t1() { + return [](T2) -> X> { + struct S { + static X> f() { + return [](T3) -> X { + static_assert(is_same>); + static_assert(is_same>); + return X(); + }(X()); + } + }; + return S::f(); + }(X()); +}; +template X>> t1(); + +#if 0 // FIXME: crashes +template auto t2() { + return [](T2) { + struct S { + static auto f() { + return [](T3) { + static_assert(is_same>); + static_assert(is_same>); + return X(); + }(X()); + } + }; + return S::f(); + }(X()); +}; +template auto t2(); +static_assert(is_same()), X>>>); + +template C1>> auto t3() { + return [] T2>(T2) -> C1> auto { + struct S { + static auto f() { + return [] T3>(T3) -> C1 auto { + return X(); + }(X()); + } + }; + return S::f(); + }(X()); +}; +template C1>> auto t3(); +static_assert(is_same()), X>>>); +#endif