Skip to content

Commit 98fdfb9

Browse files
committed
[clang] Allow pack expansions when partial ordering against template template parameters
When partial ordering alias templates against template template parameters, allow pack expansions when the alias has a fixed-size parameter list. These expansions were generally disallowed by proposed resolution for CWG1430. By previously diagnosing these when checking template template parameters, we would be too strict in trying to prevent any potential invalid use. This flows against the more general idea that template template parameters are weakly typed, that we would rather allow an argument that might be possibly misused, and only diagnose the actual misuses during instantiation. Since this interaction between P0522R0 and CWG1430 is also a backwards-compat breaking change, we implement provisional wording to allow these. Fixes #62529
1 parent 504cf55 commit 98fdfb9

File tree

5 files changed

+30
-7
lines changed

5 files changed

+30
-7
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ Bug Fixes to C++ Support
707707
initialized, rather than evaluating them as a part of the larger manifestly constant evaluated
708708
expression.
709709
- Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361).
710+
- When partial ordering alias templates against template template parameters, allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529).
710711

711712
Bug Fixes to AST Handling
712713
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9216,14 +9216,20 @@ class Sema final : public SemaBase {
92169216
/// receive true if the cause for the error is the associated constraints of
92179217
/// the template not being satisfied by the template arguments.
92189218
///
9219+
/// \param PartialOrderTTP If true, assume these template arguments are
9220+
/// the injected template arguments for a template template parameter.
9221+
/// This will relax the requirement that all it's possible uses are valid.
9222+
/// TTP checking is loose, and assumes that invalid uses will be diagnosed
9223+
/// during instantiation.
9224+
///
92199225
/// \returns true if an error occurred, false otherwise.
92209226
bool CheckTemplateArgumentList(
92219227
TemplateDecl *Template, SourceLocation TemplateLoc,
92229228
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
92239229
SmallVectorImpl<TemplateArgument> &SugaredConverted,
92249230
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
92259231
bool UpdateArgsWithConversions = true,
9226-
bool *ConstraintsNotSatisfied = nullptr);
9232+
bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderTTP = false);
92279233

92289234
bool CheckTemplateTypeArgument(
92299235
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6436,7 +6436,8 @@ bool Sema::CheckTemplateArgumentList(
64366436
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
64376437
SmallVectorImpl<TemplateArgument> &SugaredConverted,
64386438
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
6439-
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
6439+
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied,
6440+
bool PartialOrderTTP) {
64406441

64416442
if (ConstraintsNotSatisfied)
64426443
*ConstraintsNotSatisfied = false;
@@ -6507,8 +6508,13 @@ bool Sema::CheckTemplateArgumentList(
65076508
bool PackExpansionIntoNonPack =
65086509
NewArgs[ArgIdx].getArgument().isPackExpansion() &&
65096510
(!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
6510-
if (PackExpansionIntoNonPack && (isa<TypeAliasTemplateDecl>(Template) ||
6511-
isa<ConceptDecl>(Template))) {
6511+
// Core issue 1430: Don't diagnose this pack expansion when partial
6512+
// ordering template template parameters. Some uses of the template could
6513+
// be valid, and invalid uses will be diagnosed later during
6514+
// instantiation.
6515+
if (PackExpansionIntoNonPack && !PartialOrderTTP &&
6516+
(isa<TypeAliasTemplateDecl>(Template) ||
6517+
isa<ConceptDecl>(Template))) {
65126518
// Core issue 1430: we have a pack expansion as an argument to an
65136519
// alias template, and it's not part of a parameter pack. This
65146520
// can't be canonicalized, so reject it now.

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6243,7 +6243,9 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
62436243
// specialized as A.
62446244
SmallVector<TemplateArgument, 4> SugaredPArgs;
62456245
if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, SugaredPArgs,
6246-
PArgs) ||
6246+
PArgs, /*UpdateArgsWithConversions=*/true,
6247+
/*ConstraintsNotSatisfied=*/nullptr,
6248+
/*PartialOrderTTP=*/true) ||
62476249
Trap.hasErrorOccurred())
62486250
return false;
62496251
}

clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp renamed to clang/test/SemaTemplate/temp_arg_template_p0522.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
22

3-
// expected-note@temp_arg_template_cxx1z.cpp:* 1+{{}}
3+
// expected-note@temp_arg_template_p0522.cpp:* 1+{{}}
44

55
template<template<int> typename> struct Ti;
66
template<template<int...> typename> struct TPi;
@@ -118,3 +118,11 @@ namespace Auto {
118118
TInt<SubstFailure> isf; // FIXME: this should be ill-formed
119119
TIntPtr<SubstFailure> ipsf;
120120
}
121+
122+
namespace GH62529 {
123+
// Note: the constraint here is just for bypassing a fast-path.
124+
template<class T1> requires(true) using A = int;
125+
template<template<class ...T2s> class TT1, class T3> struct B {};
126+
template<class T4> B<A, T4> f();
127+
auto t = f<int>();
128+
} // namespace GH62529

0 commit comments

Comments
 (0)