Skip to content

Commit 533416b

Browse files
author
git apple-llvm automerger
committed
Merge commit '6afe56732a17' from llvm.org/main into next
2 parents 18b08bd + 6afe567 commit 533416b

File tree

17 files changed

+652
-266
lines changed

17 files changed

+652
-266
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ C++23 Feature Support
173173
C++20 Feature Support
174174
^^^^^^^^^^^^^^^^^^^^^
175175

176+
C++17 Feature Support
177+
^^^^^^^^^^^^^^^^^^^^^
178+
- The implementation of the relaxed template template argument matching rules is
179+
more complete and reliable, and should provide more accurate diagnostics.
176180

177181
Resolutions to C++ Defect Reports
178182
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -330,6 +334,10 @@ Improvements to Clang's diagnostics
330334

331335
- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391.
332336

337+
- Clang now properly explains the reason a template template argument failed to
338+
match a template template parameter, in terms of the C++17 relaxed matching rules
339+
instead of the old ones.
340+
333341
- Don't emit duplicated dangling diagnostics. (#GH93386).
334342

335343
- Improved diagnostic when trying to befriend a concept. (#GH45182).
@@ -427,6 +435,8 @@ Bug Fixes to C++ Support
427435
- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
428436
- When performing partial ordering of function templates, clang now checks that
429437
the deduction was consistent. Fixes (#GH18291).
438+
- Fixes to several issues in partial ordering of template template parameters, which
439+
were documented in the test suite.
430440
- Fixed an assertion failure about a constraint of a friend function template references to a value with greater
431441
template depth than the friend function template. (#GH98258)
432442
- Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5304,6 +5304,13 @@ def note_template_arg_refers_here_func : Note<
53045304
def err_template_arg_template_params_mismatch : Error<
53055305
"template template argument has different template parameters than its "
53065306
"corresponding template template parameter">;
5307+
def note_template_arg_template_params_mismatch : Note<
5308+
"template template argument has different template parameters than its "
5309+
"corresponding template template parameter">;
5310+
def err_non_deduced_mismatch : Error<
5311+
"could not match %diff{$ against $|types}0,1">;
5312+
def err_inconsistent_deduction : Error<
5313+
"conflicting deduction %diff{$ against $|types}0,1 for parameter">;
53075314
def err_template_arg_not_integral_or_enumeral : Error<
53085315
"non-type template argument of type %0 must have an integral or enumeration"
53095316
" type">;

clang/include/clang/Sema/Sema.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12484,8 +12484,9 @@ class Sema final : public SemaBase {
1248412484
sema::TemplateDeductionInfo &Info);
1248512485

1248612486
bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
12487-
TemplateParameterList *PParam, TemplateDecl *AArg,
12488-
const DefaultArguments &DefaultArgs, SourceLocation Loc, bool IsDeduced);
12487+
TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg,
12488+
const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
12489+
bool IsDeduced);
1248912490

1249012491
/// Mark which template parameters are used in a given expression.
1249112492
///
@@ -12794,6 +12795,9 @@ class Sema final : public SemaBase {
1279412795

1279512796
/// We are instantiating a type alias template declaration.
1279612797
TypeAliasTemplateInstantiation,
12798+
12799+
/// We are performing partial ordering for template template parameters.
12800+
PartialOrderingTTP,
1279712801
} Kind;
1279812802

1279912803
/// Was the enclosing context a non-instantiation SFINAE context?
@@ -13015,6 +13019,12 @@ class Sema final : public SemaBase {
1301513019
TemplateDecl *Entity, BuildingDeductionGuidesTag,
1301613020
SourceRange InstantiationRange = SourceRange());
1301713021

13022+
struct PartialOrderingTTP {};
13023+
/// \brief Note that we are partial ordering template template parameters.
13024+
InstantiatingTemplate(Sema &SemaRef, SourceLocation ArgLoc,
13025+
PartialOrderingTTP, TemplateDecl *PArg,
13026+
SourceRange InstantiationRange = SourceRange());
13027+
1301813028
/// Note that we have finished instantiating this template.
1301913029
void Clear();
1302013030

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
457457
return "BuildingDeductionGuides";
458458
case CodeSynthesisContext::TypeAliasTemplateInstantiation:
459459
return "TypeAliasTemplateInstantiation";
460+
case CodeSynthesisContext::PartialOrderingTTP:
461+
return "PartialOrderingTTP";
460462
}
461463
return "";
462464
}

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 38 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5502,8 +5502,7 @@ bool Sema::CheckTemplateArgumentList(
55025502
DefaultArgs && ParamIdx >= DefaultArgs.StartPos) {
55035503
// All written arguments should have been consumed by this point.
55045504
assert(ArgIdx == NumArgs && "bad default argument deduction");
5505-
// FIXME: Don't ignore parameter packs.
5506-
if (ParamIdx == DefaultArgs.StartPos && !(*Param)->isParameterPack()) {
5505+
if (ParamIdx == DefaultArgs.StartPos) {
55075506
assert(Param + DefaultArgs.Args.size() <= ParamEnd);
55085507
// Default arguments from a DeducedTemplateName are already converted.
55095508
for (const TemplateArgument &DefArg : DefaultArgs.Args) {
@@ -5728,8 +5727,9 @@ bool Sema::CheckTemplateArgumentList(
57285727
// pack expansions; they might be empty. This can happen even if
57295728
// PartialTemplateArgs is false (the list of arguments is complete but
57305729
// still dependent).
5731-
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
5732-
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
5730+
if (PartialOrderingTTP ||
5731+
(CurrentInstantiationScope &&
5732+
CurrentInstantiationScope->getPartiallySubstitutedPack())) {
57335733
while (ArgIdx < NumArgs &&
57345734
NewArgs[ArgIdx].getArgument().isPackExpansion()) {
57355735
const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument();
@@ -7327,64 +7327,46 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
73277327
<< Template;
73287328
}
73297329

7330+
if (!getLangOpts().RelaxedTemplateTemplateArgs)
7331+
return !TemplateParameterListsAreEqual(
7332+
Template->getTemplateParameters(), Params, /*Complain=*/true,
7333+
TPL_TemplateTemplateArgumentMatch, Arg.getLocation());
7334+
73307335
// C++1z [temp.arg.template]p3: (DR 150)
73317336
// A template-argument matches a template template-parameter P when P
73327337
// is at least as specialized as the template-argument A.
7333-
if (getLangOpts().RelaxedTemplateTemplateArgs) {
7334-
// Quick check for the common case:
7335-
// If P contains a parameter pack, then A [...] matches P if each of A's
7336-
// template parameters matches the corresponding template parameter in
7337-
// the template-parameter-list of P.
7338-
if (TemplateParameterListsAreEqual(
7339-
Template->getTemplateParameters(), Params, false,
7340-
TPL_TemplateTemplateArgumentMatch, Arg.getLocation()) &&
7341-
// If the argument has no associated constraints, then the parameter is
7342-
// definitely at least as specialized as the argument.
7343-
// Otherwise - we need a more thorough check.
7344-
!Template->hasAssociatedConstraints())
7345-
return false;
7346-
7347-
if (isTemplateTemplateParameterAtLeastAsSpecializedAs(
7348-
Params, Template, DefaultArgs, Arg.getLocation(), IsDeduced)) {
7349-
// P2113
7350-
// C++20[temp.func.order]p2
7351-
// [...] If both deductions succeed, the partial ordering selects the
7352-
// more constrained template (if one exists) as determined below.
7353-
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
7354-
Params->getAssociatedConstraints(ParamsAC);
7355-
// C++2a[temp.arg.template]p3
7356-
// [...] In this comparison, if P is unconstrained, the constraints on A
7357-
// are not considered.
7358-
if (ParamsAC.empty())
7359-
return false;
7338+
if (!isTemplateTemplateParameterAtLeastAsSpecializedAs(
7339+
Params, Param, Template, DefaultArgs, Arg.getLocation(), IsDeduced))
7340+
return true;
7341+
// P2113
7342+
// C++20[temp.func.order]p2
7343+
// [...] If both deductions succeed, the partial ordering selects the
7344+
// more constrained template (if one exists) as determined below.
7345+
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
7346+
Params->getAssociatedConstraints(ParamsAC);
7347+
// C++20[temp.arg.template]p3
7348+
// [...] In this comparison, if P is unconstrained, the constraints on A
7349+
// are not considered.
7350+
if (ParamsAC.empty())
7351+
return false;
73607352

7361-
Template->getAssociatedConstraints(TemplateAC);
7353+
Template->getAssociatedConstraints(TemplateAC);
73627354

7363-
bool IsParamAtLeastAsConstrained;
7364-
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
7365-
IsParamAtLeastAsConstrained))
7366-
return true;
7367-
if (!IsParamAtLeastAsConstrained) {
7368-
Diag(Arg.getLocation(),
7369-
diag::err_template_template_parameter_not_at_least_as_constrained)
7370-
<< Template << Param << Arg.getSourceRange();
7371-
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
7372-
Diag(Template->getLocation(), diag::note_entity_declared_at)
7373-
<< Template;
7374-
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
7375-
TemplateAC);
7376-
return true;
7377-
}
7378-
return false;
7379-
}
7380-
// FIXME: Produce better diagnostics for deduction failures.
7355+
bool IsParamAtLeastAsConstrained;
7356+
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
7357+
IsParamAtLeastAsConstrained))
7358+
return true;
7359+
if (!IsParamAtLeastAsConstrained) {
7360+
Diag(Arg.getLocation(),
7361+
diag::err_template_template_parameter_not_at_least_as_constrained)
7362+
<< Template << Param << Arg.getSourceRange();
7363+
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
7364+
Diag(Template->getLocation(), diag::note_entity_declared_at) << Template;
7365+
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
7366+
TemplateAC);
7367+
return true;
73817368
}
7382-
7383-
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
7384-
Params,
7385-
true,
7386-
TPL_TemplateTemplateArgumentMatch,
7387-
Arg.getLocation());
7369+
return false;
73887370
}
73897371

73907372
static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl,

0 commit comments

Comments
 (0)