[Clang] Remove the wrong assumption when rebuilding SizeOfPackExprs for constraint normalization (#115120)
In 463a4f150, we assumed that all the template argument packs are of size 1 when normalizing a constraint expression because I mistakenly thought those packs were obtained from their injected template parameters. This was wrong because we might be checking constraints when instantiating a friend declaration within a class template specialization, where the parent class template is specialized with non-dependent template arguments. In that sense, we shouldn't assume any pack size nor expand anything in such a scenario. Moreover, there are no intermediate (substituted but unexpanded) AST nodes for template template parameters, so we have to special-case their transformations by looking into the instantiation scope instead of extracting anything from template arguments. Fixes #115098
This commit is contained in:
parent
2f40e3e713
commit
37b4df434d
@ -4326,6 +4326,8 @@ public:
|
||||
/// Retrieve the parameter pack.
|
||||
NamedDecl *getPack() const { return Pack; }
|
||||
|
||||
void setPack(NamedDecl *NewPack) { Pack = NewPack; }
|
||||
|
||||
/// Retrieve the length of the parameter pack.
|
||||
///
|
||||
/// This routine may only be invoked when the expression is not
|
||||
|
@ -1749,31 +1749,21 @@ namespace {
|
||||
return inherited::TransformLambdaBody(E, Body);
|
||||
}
|
||||
|
||||
ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
|
||||
NamedDecl *Pack, SourceLocation PackLoc,
|
||||
SourceLocation RParenLoc,
|
||||
std::optional<unsigned> Length,
|
||||
ArrayRef<TemplateArgument> PartialArgs) {
|
||||
if (SemaRef.CodeSynthesisContexts.back().Kind !=
|
||||
Sema::CodeSynthesisContext::ConstraintNormalization)
|
||||
return inherited::RebuildSizeOfPackExpr(OperatorLoc, Pack, PackLoc,
|
||||
RParenLoc, Length, PartialArgs);
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (auto *Iter = TemplateArgs.begin(); Iter != TemplateArgs.end();
|
||||
++Iter)
|
||||
for (const TemplateArgument &TA : Iter->Args)
|
||||
assert(TA.getKind() != TemplateArgument::Pack || TA.pack_size() == 1);
|
||||
#endif
|
||||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(
|
||||
SemaRef, /*NewSubstitutionIndex=*/0);
|
||||
Decl *NewPack = TransformDecl(PackLoc, Pack);
|
||||
if (!NewPack)
|
||||
return ExprError();
|
||||
|
||||
return inherited::RebuildSizeOfPackExpr(OperatorLoc,
|
||||
cast<NamedDecl>(NewPack), PackLoc,
|
||||
RParenLoc, Length, PartialArgs);
|
||||
ExprResult TransformSizeOfPackExpr(SizeOfPackExpr *E) {
|
||||
ExprResult Transformed = inherited::TransformSizeOfPackExpr(E);
|
||||
if (!Transformed.isUsable())
|
||||
return Transformed;
|
||||
auto *TransformedExpr = cast<SizeOfPackExpr>(Transformed.get());
|
||||
if (SemaRef.CodeSynthesisContexts.back().Kind ==
|
||||
Sema::CodeSynthesisContext::ConstraintNormalization &&
|
||||
TransformedExpr->getPack() == E->getPack()) {
|
||||
Decl *NewPack =
|
||||
TransformDecl(E->getPackLoc(), TransformedExpr->getPack());
|
||||
if (!NewPack)
|
||||
return ExprError();
|
||||
TransformedExpr->setPack(cast<NamedDecl>(NewPack));
|
||||
}
|
||||
return TransformedExpr;
|
||||
}
|
||||
|
||||
ExprResult TransformRequiresExpr(RequiresExpr *E) {
|
||||
@ -1899,6 +1889,15 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
|
||||
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
|
||||
|
||||
if (TTP->isParameterPack()) {
|
||||
// We might not have an index for pack expansion when normalizing
|
||||
// constraint expressions. In that case, resort to instantiation scopes
|
||||
// for the transformed declarations.
|
||||
if (SemaRef.ArgumentPackSubstitutionIndex == -1 &&
|
||||
SemaRef.CodeSynthesisContexts.back().Kind ==
|
||||
Sema::CodeSynthesisContext::ConstraintNormalization) {
|
||||
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D),
|
||||
TemplateArgs);
|
||||
}
|
||||
assert(Arg.getKind() == TemplateArgument::Pack &&
|
||||
"Missing argument pack");
|
||||
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
||||
|
@ -703,6 +703,25 @@ C v;
|
||||
|
||||
} // namespace GH93099
|
||||
|
||||
namespace GH115098 {
|
||||
|
||||
template <typename... Ts> struct c {
|
||||
template <typename T>
|
||||
requires(sizeof...(Ts) > 0)
|
||||
friend bool operator==(c, c);
|
||||
};
|
||||
|
||||
template <typename... Ts> struct d {
|
||||
template <typename T>
|
||||
requires(sizeof...(Ts) > 0)
|
||||
friend bool operator==(d, d);
|
||||
};
|
||||
|
||||
template struct c<int>;
|
||||
template struct d<int, int>;
|
||||
|
||||
} // namespace GH115098
|
||||
|
||||
namespace GH114685 {
|
||||
|
||||
template <typename T> struct ptr {
|
||||
|
Loading…
x
Reference in New Issue
Block a user