133 changes: 71 additions & 62 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5179,8 +5179,7 @@ bool Sema::CheckTemplateArgument(
unsigned ArgumentPackIndex,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
CheckTemplateArgumentKind CTAK, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg) {
CheckTemplateArgumentKind CTAK) {
// Check template type parameters.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted,
Expand Down Expand Up @@ -5395,8 +5394,8 @@ bool Sema::CheckTemplateArgument(

case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (CheckTemplateTemplateArgument(TempParm, Params, Arg, PartialOrdering,
MatchedPackOnParmToNonPackOnArg))
if (CheckTemplateTemplateArgument(TempParm, Params, Arg,
/*IsDeduced=*/CTAK != CTAK_Specified))
return true;

SugaredConverted.push_back(Arg.getArgument());
Expand Down Expand Up @@ -5470,7 +5469,7 @@ bool Sema::CheckTemplateArgumentList(
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied,
bool PartialOrderingTTP, bool *MatchedPackOnParmToNonPackOnArg) {
bool PartialOrderingTTP) {

if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = false;
Expand Down Expand Up @@ -5503,7 +5502,8 @@ bool Sema::CheckTemplateArgumentList(
DefaultArgs && ParamIdx >= DefaultArgs.StartPos) {
// All written arguments should have been consumed by this point.
assert(ArgIdx == NumArgs && "bad default argument deduction");
if (ParamIdx == DefaultArgs.StartPos) {
// FIXME: Don't ignore parameter packs.
if (ParamIdx == DefaultArgs.StartPos && !(*Param)->isParameterPack()) {
assert(Param + DefaultArgs.Args.size() <= ParamEnd);
// Default arguments from a DeducedTemplateName are already converted.
for (const TemplateArgument &DefArg : DefaultArgs.Args) {
Expand Down Expand Up @@ -5549,8 +5549,7 @@ bool Sema::CheckTemplateArgumentList(
if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, TemplateLoc,
RAngleLoc, SugaredArgumentPack.size(),
SugaredConverted, CanonicalConverted,
CTAK_Specified, /*PartialOrdering=*/false,
MatchedPackOnParmToNonPackOnArg))
CTAK_Specified))
return true;

CanonicalConverted.back().setIsDefaulted(
Expand Down Expand Up @@ -5708,8 +5707,7 @@ bool Sema::CheckTemplateArgumentList(
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
SugaredConverted, CanonicalConverted,
CTAK_Specified, /*PartialOrdering=*/false,
/*MatchedPackOnParmToNonPackOnArg=*/nullptr))
CTAK_Specified))
return true;

SugaredConverted.back().setIsDefaulted(true);
Expand All @@ -5730,9 +5728,8 @@ bool Sema::CheckTemplateArgumentList(
// pack expansions; they might be empty. This can happen even if
// PartialTemplateArgs is false (the list of arguments is complete but
// still dependent).
if (PartialOrderingTTP ||
(CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack())) {
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
while (ArgIdx < NumArgs &&
NewArgs[ArgIdx].getArgument().isPackExpansion()) {
const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument();
Expand Down Expand Up @@ -7292,10 +7289,10 @@ static void DiagnoseTemplateParameterListArityMismatch(
Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);

bool Sema::CheckTemplateTemplateArgument(
TemplateTemplateParmDecl *Param, TemplateParameterList *Params,
TemplateArgumentLoc &Arg, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg) {
bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
TemplateParameterList *Params,
TemplateArgumentLoc &Arg,
bool IsDeduced) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
auto [Template, DefaultArgs] = Name.getTemplateDeclAndDefaultArgs();
if (!Template) {
Expand Down Expand Up @@ -7330,47 +7327,64 @@ bool Sema::CheckTemplateTemplateArgument(
<< Template;
}

if (!getLangOpts().RelaxedTemplateTemplateArgs)
return !TemplateParameterListsAreEqual(
Template->getTemplateParameters(), Params, /*Complain=*/true,
TPL_TemplateTemplateArgumentMatch, Arg.getLocation());

// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
if (!isTemplateTemplateParameterAtLeastAsSpecializedAs(
Params, Param, Template, DefaultArgs, Arg.getLocation(),
PartialOrdering, MatchedPackOnParmToNonPackOnArg))
return true;
// P2113
// C++20[temp.func.order]p2
// [...] If both deductions succeed, the partial ordering selects the
// more constrained template (if one exists) as determined below.
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
Params->getAssociatedConstraints(ParamsAC);
// C++20[temp.arg.template]p3
// [...] In this comparison, if P is unconstrained, the constraints on A
// are not considered.
if (ParamsAC.empty())
return false;
if (getLangOpts().RelaxedTemplateTemplateArgs) {
// Quick check for the common case:
// If P contains a parameter pack, then A [...] matches P if each of A's
// template parameters matches the corresponding template parameter in
// the template-parameter-list of P.
if (TemplateParameterListsAreEqual(
Template->getTemplateParameters(), Params, false,
TPL_TemplateTemplateArgumentMatch, Arg.getLocation()) &&
// If the argument has no associated constraints, then the parameter is
// definitely at least as specialized as the argument.
// Otherwise - we need a more thorough check.
!Template->hasAssociatedConstraints())
return false;

Template->getAssociatedConstraints(TemplateAC);
if (isTemplateTemplateParameterAtLeastAsSpecializedAs(
Params, Template, DefaultArgs, Arg.getLocation(), IsDeduced)) {
// P2113
// C++20[temp.func.order]p2
// [...] If both deductions succeed, the partial ordering selects the
// more constrained template (if one exists) as determined below.
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
Params->getAssociatedConstraints(ParamsAC);
// C++2a[temp.arg.template]p3
// [...] In this comparison, if P is unconstrained, the constraints on A
// are not considered.
if (ParamsAC.empty())
return false;

bool IsParamAtLeastAsConstrained;
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
Diag(Arg.getLocation(),
diag::err_template_template_parameter_not_at_least_as_constrained)
<< Template << Param << Arg.getSourceRange();
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at) << Template;
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
TemplateAC);
return true;
Template->getAssociatedConstraints(TemplateAC);

bool IsParamAtLeastAsConstrained;
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
Diag(Arg.getLocation(),
diag::err_template_template_parameter_not_at_least_as_constrained)
<< Template << Param << Arg.getSourceRange();
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at)
<< Template;
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
TemplateAC);
return true;
}
return false;
}
// FIXME: Produce better diagnostics for deduction failures.
}
return false;

return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Params,
true,
TPL_TemplateTemplateArgumentMatch,
Arg.getLocation());
}

static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl,
Expand Down Expand Up @@ -9758,14 +9772,11 @@ DeclResult Sema::ActOnExplicitInstantiation(

// Check that the template argument list is well-formed for this
// template.
bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false;
SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (CheckTemplateArgumentList(
ClassTemplate, TemplateNameLoc, TemplateArgs,
/*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true,
/*ConstraintsNotSatisfied=*/nullptr, /*PartialOrderingTTP=*/false,
&PrimaryHasMatchedPackOnParmToNonPackOnArg))
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
/*DefaultArgs=*/{}, false, SugaredConverted,
CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return true;

// Find the class template specialization declaration that
Expand Down Expand Up @@ -9886,9 +9897,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition());
if (!Def)
InstantiateClassTemplateSpecialization(
TemplateNameLoc, Specialization, TSK,
/*Complain=*/true, PrimaryHasMatchedPackOnParmToNonPackOnArg);
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
else if (TSK == TSK_ExplicitInstantiationDefinition) {
MarkVTableUsed(TemplateNameLoc, Specialization, true);
Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
Expand Down
442 changes: 133 additions & 309 deletions clang/lib/Sema/SemaTemplateDeduction.cpp

Large diffs are not rendered by default.

39 changes: 10 additions & 29 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case LambdaExpressionSubstitution:
case BuildingDeductionGuides:
case TypeAliasTemplateInstantiation:
case PartialOrderingTTP:
return false;

// This function should never be called when Kind's value is Memoization.
Expand Down Expand Up @@ -805,11 +804,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
SemaRef, CodeSynthesisContext::BuildingDeductionGuides,
PointOfInstantiation, InstantiationRange, Entity) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation ArgLoc, PartialOrderingTTP,
TemplateDecl *PArg, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
ArgLoc, InstantiationRange, PArg) {}

void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
Expand Down Expand Up @@ -1249,14 +1243,6 @@ void Sema::PrintInstantiationStack() {
<< cast<TypeAliasTemplateDecl>(Active->Entity)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::PartialOrderingTTP:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_arg_template_params_mismatch);
if (SourceLocation ParamLoc = Active->Entity->getLocation();
ParamLoc.isValid())
Diags.Report(ParamLoc, diag::note_template_prev_declaration)
<< /*isTemplateTemplateParam=*/true << Active->InstantiationRange;
break;
}
}
}
Expand Down Expand Up @@ -1299,7 +1285,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
case CodeSynthesisContext::PartialOrderingTTP:
// A default template argument instantiation and substitution into
// template parameters with arguments for prior parameters may or may
// not be a SFINAE context; look further up the stack.
Expand Down Expand Up @@ -4017,11 +4002,11 @@ bool Sema::usesPartialOrExplicitSpecialization(
/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
static ActionResult<CXXRecordDecl *>
getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg) {
TemplateSpecializationKind TSK) {
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
if (Inst.isInvalid())
return {/*Invalid=*/true};
Expand All @@ -4044,7 +4029,7 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
// specialization with the template argument lists of the partial
// specializations.
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched, ExtraMatched;
SmallVector<MatchResult, 4> Matched;
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
Expand All @@ -4061,13 +4046,11 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
MakeDeductionFailureInfo(S.Context, Result, Info));
(void)Result;
} else {
auto &List =
Info.hasMatchedPackOnParmToNonPackOnArg() ? ExtraMatched : Matched;
List.push_back(MatchResult{Partial, Info.takeCanonical()});
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
Matched.back().Args = Info.takeCanonical();
}
}
if (Matched.empty() && PrimaryHasMatchedPackOnParmToNonPackOnArg)
Matched = std::move(ExtraMatched);

// If we're dealing with a member template where the template parameters
// have been instantiated, this provides the original template parameters
Expand Down Expand Up @@ -4170,18 +4153,16 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
bool Sema::InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg) {
TemplateSpecializationKind TSK, bool Complain) {
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
if (ClassTemplateSpec->isInvalidDecl())
return true;

ActionResult<CXXRecordDecl *> Pattern =
getPatternForClassTemplateSpecialization(
*this, PointOfInstantiation, ClassTemplateSpec, TSK,
PrimaryHasMatchedPackOnParmToNonPackOnArg);
getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
ClassTemplateSpec, TSK);
if (!Pattern.isUsable())
return Pattern.isInvalid();

Expand Down
31 changes: 13 additions & 18 deletions clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

template <class T> struct eval; // expected-note 3{{template is declared here}}

template <template <class, class...> class TT, class T1, class... Rest>
template <template <class, class...> class TT, class T1, class... Rest>
struct eval<TT<T1, Rest...>> { };

template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1, class T2, int N = 17> struct E;

eval<A<int>> eA;
Expand All @@ -17,32 +17,27 @@ eval<C<17>> eC; // expected-error{{implicit instantiation of undefined template
eval<D<int, 17>> eD; // expected-error{{implicit instantiation of undefined template 'eval<D<int, 17>>'}}
eval<E<int, float>> eE; // expected-error{{implicit instantiation of undefined template 'eval<E<int, float>>}}

template<
template <int ...N> // expected-error{{deduced non-type template argument does not have the same type as the corresponding template parameter ('int' vs 'long')}}
class TT // expected-note {{previous template template parameter is here}}
> struct X0 { };

template<template <int ...N> class TT> struct X0 { }; // expected-note{{previous non-type template parameter with type 'int' is here}}
template<int I, int J, int ...Rest> struct X0a;
template<int ...Rest> struct X0b;
template<int I, long J> struct X0c; // expected-note{{template parameter is declared here}}
template<int I, long J> struct X0c; // expected-note{{template non-type parameter has a different type 'long' in template argument}}

X0<X0a> inst_x0a;
X0<X0b> inst_x0b;
X0<X0c> inst_x0c; // expected-note{{template template argument has different template parameters than its corresponding template template parameter}}
X0<X0c> inst_x0c; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}

template<typename T,
template <T ...N> // expected-error{{deduced non-type template argument does not have the same type as the corresponding template parameter ('short' vs 'long')}}
class TT // expected-note {{previous template template parameter is here}}
> struct X1 { };
template<typename T,
template <T ...N> class TT> // expected-note{{previous non-type template parameter with type 'short' is here}}
struct X1 { };
template<int I, int J, int ...Rest> struct X1a;
template<long I, long ...Rest> struct X1b;
template<short I, short J> struct X1c;
template<short I, long J> struct X1d; // expected-note{{template parameter is declared here}}
template<short I, long J> struct X1d; // expected-note{{template non-type parameter has a different type 'long' in template argument}}

X1<int, X1a> inst_x1a;
X1<long, X1b> inst_x1b;
X1<short, X1c> inst_x1c;
X1<short, X1d> inst_x1d; // expected-note{{template template argument has different template parameters than its corresponding template template parameter}}
X1<short, X1d> inst_x1d; // expected-error{{template template argument has different template parameters than its corresponding template template paramete}}

template <int> class X2; // expected-note{{template is declared here}} \
// expected-note{{template is declared here}}
Expand Down
21 changes: 10 additions & 11 deletions clang/test/CXX/temp/temp.param/p12.cpp
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename> struct Y1; // expected-note{{template is declared here}}
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}}
template<typename, int> struct Y2;

// C++ [temp.param]p12:
template<class T1,
template<class T1,
class T2 = int> // expected-note{{previous default template argument defined here}}
class B3;
template<class T1, typename T2> class B3;
template<class T1,
template<class T1,
typename T2 = float> // expected-error{{template parameter redefines default argument}}
class B3;

template<template<class, int> class,
template<template<class, int> class,
template<class> class = Y1> // expected-note{{previous default template argument defined here}}
class B3t;

template<template<class, int> class, template<class> class> class B3t;

template<template<class, int> class,
template<template<class, int> class,
template<class> class = Y1> // expected-error{{template parameter redefines default argument}}
class B3t;

template<int N,
template<int N,
int M = 5> // expected-note{{previous default template argument defined here}}
class B3n;

template<int N, int M> class B3n;

template<int N,
template<int N,
int M = 7> // expected-error{{template parameter redefines default argument}}
class B3n;

// Check validity of default arguments
template<template<class, int> class =// expected-note {{previous template template parameter is here}}
Y1> // expected-error{{too many template arguments for class template 'Y1'}}
// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}}
template<template<class, int> class // expected-note{{previous template template parameter is here}}
= Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
class C1 {};

C1<> c1; // expected-note{{while checking a default template argument}}
15 changes: 12 additions & 3 deletions clang/test/Modules/cxx-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,23 @@ void g() {

template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
template_param_kinds_2<Tmpl_T_C>(); // ok, from cxx-templates-b.h

template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function}}
// expected-note@Inputs/cxx-templates-a.h:11 {{invalid explicitly-specified argument}}
// expected-note@Inputs/cxx-templates-b.h:11 {{invalid explicitly-specified argument}}

template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}

template_param_kinds_3<Tmpl_T_T_A>();
template_param_kinds_3<Tmpl_T_T_B>();
// FIXME: This should be valid, but we incorrectly match the template template
// argument against both template template parameters.
template_param_kinds_3<Tmpl_T_T_A>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:12 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:12 {{candidate}}
template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:12 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:12 {{candidate}}

// Trigger the instantiation of a template in 'a' that uses a type defined in
// 'common'. That type is not visible here.
Expand Down
5 changes: 3 additions & 2 deletions clang/test/SemaCXX/make_integer_seq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ using illformed2 = ErrorSeq<int, -5>; // expected-note{{in instantiation}}
template <typename T, T N> void f() {}
__make_integer_seq<f, int, 0> x; // expected-error{{template template parameter must be a class template or type alias template}}

__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-note{{different template parameters}}
// expected-error@make_integer_seq.cpp:* {{template argument for template template parameter must be a class template or type alias template}}
__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-error{{different template parameters}}
// expected-note@make_integer_seq.cpp:* {{template parameter has a different kind}}
// expected-note@make_integer_seq.cpp:* {{previous template template parameter is here}}
243 changes: 7 additions & 236 deletions clang/test/SemaTemplate/cwg2398.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ namespace type_pack3 {
template<class T3> struct B;

template<template<class T4 > class TT1, class T5 > struct B<TT1<T5 >>;

template<template<class T6, class ...T7s> class TT2, class T8, class ...T9s> struct B<TT2<T8, T9s...>> {};
// new-note@-1 {{template is declared here}}
template<template<class T6, class ...T7s> class TT2, class T8, class ...T9s> struct B<TT2<T8, T9s...>>;
// old-note@-1 {{template is declared here}}

template struct B<A<int>>;
// expected-error@-1 {{explicit instantiation of undefined template}}
} // namespace type_pack3

namespace gcc_issue {
Expand Down Expand Up @@ -156,14 +158,16 @@ namespace ttp_defaults {
namespace ttp_only {
template <template <class... > class TT1> struct A { static constexpr int V = 0; };
template <template <class > class TT2> struct A<TT2> { static constexpr int V = 1; };
// new-note@-1 {{partial specialization matches}}
template <template <class, class> class TT3> struct A<TT3> { static constexpr int V = 2; };
// new-note@-1 {{partial specialization matches}}

template <class ... > struct B;
template <class > struct C;
template <class, class > struct D;
template <class, class, class> struct E;

static_assert(A<B>::V == 0);
static_assert(A<B>::V == 0); // new-error {{ambiguous partial specializations}}
static_assert(A<C>::V == 1);
static_assert(A<D>::V == 2);
static_assert(A<E>::V == 0);
Expand Down Expand Up @@ -360,152 +364,6 @@ namespace classes {
} // namespace defaulted
} // namespace classes

namespace packs {
namespace t1 {
// FIXME: This should be rejected
template<template<int, int...> class> struct A {};
// old-note@-1 {{previous non-type template parameter with type 'int' is here}}

template<char> struct B;
// old-note@-1 {{template non-type parameter has a different type 'char' in template argument}}

template struct A<B>;
// old-error@-1 {{has different template parameters}}
} // namespace t1
namespace t2 {
template<template<char, int...> class> struct A {};
// old-note@-1 {{previous non-type template parameter with type 'char' is here}}

template<int> struct B;
// old-note@-1 {{template non-type parameter has a different type 'int' in template argument}}

template struct A<B>;
// old-error@-1 {{has different template parameters}}
} // namespace t2
namespace t3 {
// FIXME: This should be rejected
template<template<int...> class> struct A {};
// old-note@-1 {{previous non-type template parameter with type 'int' is here}}

template<char> struct B;
// old-note@-1 {{template non-type parameter has a different type 'char' in template argument}}

template struct A<B>;
// old-error@-1 {{has different template parameters}}
} // namespace t3
namespace t4 {
template<template<char...> class> struct A {};
// old-note@-1 {{previous non-type template parameter with type 'char' is here}}

template<int> struct B;
// old-note@-1 {{template non-type parameter has a different type 'int' in template argument}}

template struct A<B>;
// old-error@-1 {{has different template parameters}}
} // namespace t4
} // namespace packs

namespace fun_tmpl_call {
namespace match_func {
template <template <class> class TT> void f(TT<int>) {};
// old-note@-1 {{has different template parameters}}
template <class...> struct A {};
void test() { f(A<int>()); }
// old-error@-1 {{no matching function for call to 'f'}}
} // namespace match_func
namespace order_func_nonpack {
template <template <class> class TT> void f(TT<int>) {}
template <template <class...> class TT> void f(TT<int>) = delete;

template <class> struct A {};
void test() { f(A<int>()); }
} // namespace order_func_nonpack
namespace order_func_pack {
template <template <class> class TT> void f(TT<int>) = delete;
template <template <class...> class TT> void f(TT<int>) {}

template <class...> struct A {};
void test() { f(A<int>()); }
} // namespace order_func_pack
namespace match_method {
struct A {
template <template <class> class TT> void f(TT<int>) {};
// old-note@-1 {{has different template parameters}}
};
template <class...> struct B {};
void test() { A().f(B<int>()); }
// old-error@-1 {{no matching member function for call to 'f'}}
} // namespace t2
namespace order_method_nonpack {
struct A {
template <template <class> class TT> void f(TT<int>) {}
template <template <class...> class TT> void f(TT<int>) = delete;
};
template <class> struct B {};
void test() { A().f(B<int>()); }
} // namespace order_method_nonpack
namespace order_method_pack {
struct A {
template <template <class> class TT> void f(TT<int>) = delete;
template <template <class...> class TT> void f(TT<int>) {}
};
template <class...> struct B {};
void test() { A().f(B<int>()); }
} // namespace order_method_pack
namespace match_conv {
struct A {
template <template <class> class TT> operator TT<int>() { return {}; }
// old-note@-1 {{different template parameters}}
};
template <class...> struct B {};
// old-note@-1 2{{not viable}}
void test() { B<int> b = A(); }
// old-error@-1 {{no viable conversion from 'A' to 'B<int>'}}
} // namespace match_conv
namespace order_conv_nonpack {
struct A {
template <template <class> class TT> operator TT<int>() { return {}; };
template <template <class...> class TT> operator TT<int>() = delete;
};
template <class> struct B {};
void test() { B<int> b = A(); }
} // namespace order_conv_nonpack
namespace order_conv_pack {
struct A {
template <template <class> class TT> operator TT<int>() = delete;
template <template <class...> class TT> operator TT<int>() { return {}; }
};
template <class...> struct B {};
void test() { B<int> b = A(); }
} // namespace order_conv_pack
namespace regression1 {
template <template <class, class...> class TT, class T1, class... T2s>
void f(TT<T1, T2s...>) {}
template <class> struct A {};
void test() { f(A<int>()); }
} // namespace regression1
} // namespace fun_tmpl_packs

namespace partial {
namespace t1 {
template<template<class... T1s> class TT1> struct A {};

template<template<class T2> class TT2> struct A<TT2>;

template<class... T3s> struct B;
template struct A<B>;
} // namespace t1
namespace t2 {
template<template<class... T1s> class TT1> struct A;

template<template<class T2> class TT2> struct A<TT2> {};

template<class T3> struct B;
template struct A<B>;
} // namespace t1

} // namespace partial

namespace regression1 {
template <typename T, typename Y> struct map {};
template <typename T> class foo {};
Expand All @@ -522,93 +380,6 @@ namespace regression1 {
}
} // namespace regression1

namespace constraints {
template <class T> concept C1 = true;
// new-note@-1 {{similar constraint expression here}}
// new-note@-2 2{{similar constraint expressions not considered equivalent}}

template <class T> concept C2 = C1<T> && true;
// new-note@-1 2{{similar constraint expression here}}

template <class T> concept D1 = true;
// new-note@-1 {{similar constraint expressions not considered equivalent}}

namespace t1 {
template<template<C1, class... T1s> class TT1> // new-note {{TT1' declared here}}
struct A {};
template<D1, class T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t1
namespace t2 {
template<template<C2, class... T1s> class TT1> struct A {};
template<C1, class T2> struct B {};
template struct A<B>;
} // namespace t2
namespace t3 {
template<template<C1, class... T1s> class TT1> // new-note {{'TT1' declared here}}
struct A {};
template<C2, class T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t2
namespace t4 {
// FIXME: This should be accepted.
template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}}
struct A {};
template<C1 T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t4
namespace t5 {
// FIXME: This should be accepted
template<template<C2... T1s> class TT1> // new-note {{'TT1' declared here}}
struct A {};
template<C1 T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t5
namespace t6 {
template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}}
struct A {};
template<C2 T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t6
namespace t7 {
template<template<class... T1s> class TT1>
struct A {};
template<C1 T2> struct B {};
template struct A<B>;
} // namespace t7
namespace t8 {
template<template<C1... T1s> class TT1>
struct A {};
template<class T2> struct B {};
template struct A<B>;
} // namespace t8
namespace t9 {
template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}}
struct A {};
template<D1 T2> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t9
namespace t10 {
template<template<class...> requires C1<int> class TT1> // new-note {{'TT1' declared here}}
struct A {};

template<class> requires C2<int> struct B {}; // new-note {{'B' declared here}}
template struct A<B>;
// new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
} // namespace t10
namespace t11 {
template<template<class...> requires C2<int> class TT1> struct A {};
template<class> requires C1<int> struct B {};
template struct A<B>;
} // namespace t11
} // namespace constraints

namespace regression2 {
template <class> struct D {};

Expand Down
26 changes: 8 additions & 18 deletions clang/test/SemaTemplate/temp_arg_nontype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,12 @@ namespace PR17696 {

namespace partial_order_different_types {
template<int, int, typename T, typename, T> struct A;
// expected-note@-1 {{template is declared here}}
template<int N, typename T, typename U, T V> struct A<0, N, T, U, V> {};
template<int N, typename T, typename U, U V> struct A<0, N, T, U, V>;
// expected-error@-1 {{class template partial specialization is not more specialized than the primary template}}
A<0, 0, int, int, 0> a;
template<int N, typename T, typename U, T V> struct A<0, N, T, U, V>; // expected-note {{matches}}
// FIXME: It appears that this partial specialization should be ill-formed as
// it is not more specialized than the primary template. V is not deducible
// because it does not have the same type as the corresponding parameter.
template<int N, typename T, typename U, U V> struct A<0, N, T, U, V> {}; // expected-note {{matches}}
A<0, 0, int, int, 0> a; // expected-error {{ambiguous}}
}

namespace partial_order_references {
Expand Down Expand Up @@ -457,24 +458,13 @@ namespace dependent_nested_partial_specialization {
namespace nondependent_default_arg_ordering {
int n, m;
template<typename A, A B = &n> struct X {};

template<typename A> void f(X<A>);
// expected-note@-1 {{candidate function}}
template<typename A> void f(X<A, &m>);
// expected-note@-1 {{candidate function}}
template<typename A, A B> void f(X<A, B>);
// expected-note@-1 2{{candidate function}}
template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>);
// expected-note@-1 2{{candidate function}}

// FIXME: When partial ordering, we get an inconsistent deduction between
// `A` (type-parameter-0-0) and `int *`, when deducing the first parameter.
// The deduction mechanism needs to be extended to be able to correctly
// handle these cases where the argument's template parameters appear in
// the result.
void g() {
X<int *, &n> x; f(x); // expected-error {{call to 'f' is ambiguous}}
X<int *, &m> y; f(y); // expected-error {{call to 'f' is ambiguous}}
X<int *, &n> x; f(x);
X<int *, &m> y; f(y);
}
}

Expand Down
38 changes: 15 additions & 23 deletions clang/test/SemaTemplate/temp_arg_template.cpp
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx17 %std_cxx98-14 %s
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 -std=c++17 %s

template<template<typename T> class X> struct A; // #A
// expected-note@-1 2{{previous template template parameter is here}}
template<template<typename T> class X> struct A; // expected-note 2{{previous template template parameter is here}}

template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}

template<template<int I> class X> struct C;
// precxx17-error@-1 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('int' vs 'const int &')}}
// cxx17-error@-2 {{conversion from 'int' to 'const int &' in converted constant expression would bind reference to a temporary}}
// expected-note@-3 {{previous template template parameter is here}}
template<template<int I> class X> struct C; // expected-note {{previous non-type template parameter with type 'int' is here}}

template<class> struct X; // expected-note {{template is declared here}}
template<int N> struct Y; // expected-note {{template parameter is declared here}}
template<class> struct X; // expected-note{{too few template parameters in template template argument}}
template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}}
template<long N> struct Ylong;
template<const int &N> struct Yref; // precxx17-note {{template parameter is declared here}}
template<const int &N> struct Yref; // expected-note{{template non-type parameter has a different type 'const int &' in template argument}}

namespace N {
template<class> struct Z;
}
template<class, class> struct TooMany; // expected-note{{template is declared here}}
template<class, class> struct TooMany; // expected-note{{too many template parameters in template template argument}}


A<X> *a1;
A<N::Z> *a2;
A< ::N::Z> *a3;

A<Y> *a4; // expected-error@#A {{template argument for non-type template parameter must be an expression}}
// expected-note@-1 {{different template parameters}}
A<TooMany> *a5; // expected-error {{too few template arguments for class template 'TooMany'}}
// expected-note@-1 {{different template parameters}}
B<X> *a6; // expected-error {{too many template arguments for class template 'X'}}
// expected-note@-1 {{different template parameters}}
A<Y> *a4; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
A<TooMany> *a5; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
C<Y> *a7;
C<Ylong> *a8;
C<Yref> *a9; // expected-note {{different template parameters}}
C<Yref> *a9; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}

template<typename T> void f(int);

Expand Down Expand Up @@ -110,9 +103,9 @@ void foo() {

namespace CheckDependentNonTypeParamTypes {
template<template<typename T, typename U, T v> class X> struct A {
// expected-note@-1 {{previous template template parameter is here}}
void f() {
X<int, void*, 3> x;
X<int, void*, 3> x; // precxx17-error {{does not refer to any declaration}} \
cxx17-error {{value of type 'int' is not implicitly convertible to 'void *'}}
}
void g() {
X<int, long, 3> x;
Expand All @@ -131,16 +124,15 @@ namespace CheckDependentNonTypeParamTypes {
}
};

template<typename T, typename U, U v> struct B {
// expected-error@-1 {{conflicting deduction 'U' against 'T' for parameter}}
template<typename T, typename U, U v> struct B { // precxx17-note {{parameter}}
static const U value = v;
};

// FIXME: This should probably be rejected, but the rules are at best unclear.
A<B> ab; // expected-note {{different template parameters}}
A<B> ab;

void use() {
ab.f();
ab.f(); // expected-note {{instantiation of}}
ab.g();
ab.h();
}
Expand Down
82 changes: 30 additions & 52 deletions clang/test/SemaTemplate/temp_arg_template_p0522.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s

// expected-note@temp_arg_template_p0522.cpp:* 1+{{template is declared here}}
// expected-note@temp_arg_template_p0522.cpp:* 1+{{template parameter is declared here}}
// expected-note@temp_arg_template_p0522.cpp:* 1+{{previous template template parameter is here}}
// expected-note@temp_arg_template_p0522.cpp:* 1+{{}}

template<template<int> typename> struct Ti; // #Ti
template<template<int...> typename> struct TPi; // #TPi
template<template<int> typename> struct Ti;
template<template<int...> typename> struct TPi;
template<template<int, int...> typename> struct TiPi;
template<template<int..., int...> typename> struct TPiPi; // FIXME: Why is this not ill-formed?

template<typename T, template<T> typename> struct tT0; // #tT0
template<template<typename T, T> typename> struct Tt0; // #Tt0
template<typename T, template<T> typename> struct tT0;
template<template<typename T, T> typename> struct Tt0;

template<template<typename> typename> struct Tt;
template<template<typename, typename...> typename> struct TtPt;
Expand All @@ -21,8 +19,8 @@ template<int, int> struct ii;
template<int...> struct Pi;
template<int, int, int...> struct iiPi;

template<int, typename = int> struct iDt; // #iDt
template<int, typename> struct it; // #it
template<int, typename = int> struct iDt;
template<int, typename> struct it;

template<typename T, T v> struct t0;

Expand All @@ -33,27 +31,20 @@ namespace IntParam {
Ti<iDi>,
Ti<Pi>,
Ti<iDt>>;
using err1 = Ti<ii>; // expected-error {{too few template arguments for class template 'ii'}}
// expected-note@-1 {{different template parameters}}
using err2 = Ti<iiPi>; // expected-error {{too few template arguments for class template 'iiPi'}}
// expected-note@-1 {{different template parameters}}
using err3 = Ti<t0>; // expected-error@#Ti {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err4 = Ti<it>; // expected-error {{too few template arguments for class template 'it'}}
// expected-note@-1 {{different template parameters}}
using err1 = Ti<ii>; // expected-error {{different template parameters}}
using err2 = Ti<iiPi>; // expected-error {{different template parameters}}
using err3 = Ti<t0>; // expected-error {{different template parameters}}
using err4 = Ti<it>; // expected-error {{different template parameters}}
}

// These are accepted by the backwards-compatibility "parameter pack in
// parameter matches any number of parameters in arguments" rule.
namespace IntPackParam {
using ok = TPi<Pi>;
using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;
using err1 = TPi<t0>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err2 = TPi<iDt>; // expected-error@#iDt {{could not match 'type-parameter-0-1' against}}
// expected-note@-1 {{different template parameters}}
using err3 = TPi<it>; // expected-error@#it {{could not match 'type-parameter-0-1' against}}
// expected-note@-1 {{different template parameters}}
using err1 = TPi<t0>; // expected-error {{different template parameters}}
using err2 = TPi<iDt>; // expected-error {{different template parameters}}
using err3 = TPi<it>; // expected-error {{different template parameters}}
}

namespace IntAndPackParam {
Expand All @@ -64,50 +55,42 @@ namespace IntAndPackParam {

namespace DependentType {
using ok = Pt<tT0<int, i>, tT0<int, iDi>>;
using err1 = tT0<int, ii>; // expected-error {{too few template arguments for class template 'ii'}}
// expected-note@-1 {{different template parameters}}
using err1 = tT0<int, ii>; // expected-error {{different template parameters}}
using err2 = tT0<short, i>; // FIXME: should this be OK?
using err2a = tT0<long long, i>; // FIXME: should this be OK (if long long is larger than int)?
using err2b = tT0<void*, i>; // expected-error@#tT0 {{value of type 'void *' is not implicitly convertible to 'int'}}
// expected-note@-1 {{different template parameters}}
using err3 = tT0<short, t0>; // expected-error@#tT0 {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err2b = tT0<void*, i>; // expected-error {{different template parameters}}
using err3 = tT0<short, t0>; // expected-error {{different template parameters}}

using ok2 = Tt0<t0>;
using err4 = Tt0<it>; // expected-error@#Tt0 {{template argument for non-type template parameter must be an expression}}
// expected-note@-1 {{different template parameters}}
using err4 = Tt0<it>; // expected-error {{different template parameters}}
}

namespace Auto {
template<template<int> typename T> struct TInt {}; // #TInt
template<template<int*> typename T> struct TIntPtr {}; // #TIntPtr
template<template<int> typename T> struct TInt {};
template<template<int*> typename T> struct TIntPtr {};
template<template<auto> typename T> struct TAuto {};
template<template<auto*> typename T> struct TAutoPtr {};
template<template<decltype(auto)> typename T> struct TDecltypeAuto {};
template<auto> struct Auto;
template<auto*> struct AutoPtr; // #AutoPtr
template<auto*> struct AutoPtr;
template<decltype(auto)> struct DecltypeAuto;
template<int> struct Int;
template<int*> struct IntPtr;

TInt<Auto> ia;
TInt<AutoPtr> iap; // expected-error@#TInt {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'int'}}
// expected-note@-1 {{different template parameters}}
TInt<AutoPtr> iap; // FIXME: ill-formed (?)
TInt<DecltypeAuto> ida;
TInt<Int> ii;
TInt<IntPtr> iip; // expected-error@#TInt {{conversion from 'int' to 'int *' is not allowed in a converted constant expression}}
// expected-note@-1 {{different template parameters}}
TInt<IntPtr> iip; // expected-error {{different template parameters}}

TIntPtr<Auto> ipa;
TIntPtr<AutoPtr> ipap;
TIntPtr<DecltypeAuto> ipda;
TIntPtr<Int> ipi; // expected-error@#TIntPtr {{value of type 'int *' is not implicitly convertible to 'int'}}
// expected-note@-1 {{different template parameters}}
TIntPtr<Int> ipi; // expected-error {{different template parameters}}
TIntPtr<IntPtr> ipip;

TAuto<Auto> aa;
TAuto<AutoPtr> aap; // expected-error@#AutoPtr {{could not match 'auto *' against 'auto'}}
// expected-note@-1 {{different template parameters}}
TAuto<AutoPtr> aap; // FIXME: ill-formed (?)
TAuto<Int> ai; // FIXME: ill-formed (?)
TAuto<IntPtr> aip; // FIXME: ill-formed (?)

Expand All @@ -128,8 +111,7 @@ namespace Auto {
// parameters (such as 'user-defined-type &') that are not valid 'auto'
// parameters.
TDecltypeAuto<Auto> daa;
TDecltypeAuto<AutoPtr> daap; // expected-error@#AutoPtr {{could not match 'auto *' against 'decltype(auto)'}}
// expected-note@-1 {{different template parameters}}
TDecltypeAuto<AutoPtr> daap; // FIXME: should probably be ill-formed

int n;
template<auto A, decltype(A) B = &n> struct SubstFailure;
Expand All @@ -146,7 +128,7 @@ namespace GH62529 {
} // namespace GH62529

namespace GH101394 {
struct X {}; // #X
struct X {};
struct Y {
constexpr Y(const X &) {}
};
Expand All @@ -157,12 +139,8 @@ namespace GH101394 {
template struct A<B>;
} // namespace t1
namespace t2 {
template<template<Y> class> struct A {}; // #A
template<X> struct B; // #B
template struct A<B>;
// expected-error@#A {{no viable conversion from 'const Y' to 'X'}}
// expected-note@-2 {{different template parameters}}
// expected-note@#X 2{{not viable}}
// expected-note@#B {{passing argument to parameter here}}
template<template<Y> class> struct A {};
template<X> struct B;
template struct A<B>; // expected-error {{different template parameters}}
} // namespace t2
} // namespace GH101394
12 changes: 0 additions & 12 deletions clang/test/Templight/templight-empty-entries-fix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,18 +314,6 @@ void foo() {
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
// CHECK: {{^poi:[ ]+''$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
Expand Down
33 changes: 10 additions & 23 deletions clang/test/Templight/templight-prior-template-arg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,76 +10,63 @@ class B {};
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:1'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B::Outer'$}}
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:1'$}}
//
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B::Outer'$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B::Outer'$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:5:40'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:3'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:1'$}}
//
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
//
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
//
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
//
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'B<A>'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-prior-template-arg.cpp:6:7'}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:85:6'$}}
// CHECK: {{^poi:[ ]+'.*templight-prior-template-arg.cpp:72:6'$}}
B<A> b;