summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2023-03-08 12:12:33 -0800
committerTom Stellard <tstellar@redhat.com>2023-03-09 20:37:39 -0800
commit9a6f0c20fd2294830acdde714e6cddb2793c504b (patch)
tree6f157b1bdc12a851a9db42f86faa83272b913227
parent633c6c013ed7368e6ab644de2e9dab9d9e175fcc (diff)
downloadllvm-9a6f0c20fd2294830acdde714e6cddb2793c504b.tar.gz
Revert two patches to fix GH58452 regression
GH58452 is a regression in the 16.0 release branch caused by both: b8a1b698afb2fc84819c7596090aabf4d826b436 and 3a0309c53674be56b5cfce038d78a0c2c6e2a98c This patch reverts both of those to make the 'valid' code stop diagnosing at the expense of crashes on invalid + unclear diagnostics. This patch also adds the tests from GH58452 to prevent any re-application from breaking this again. Revert "[clang] Improve diagnostics for expansion length mismatch" This reverts commit 3a0309c53674be56b5cfce038d78a0c2c6e2a98c. Revert "[clang] fix missing initialization of original number of expansions" This reverts commit b8a1b698afb2fc84819c7596090aabf4d826b436. Differential Revision: https://reviews.llvm.org/D145605 (cherry picked from commit acecf68c8b7c3c625cfa00f00f8ddc8f15baae44)
-rw-r--r--clang/include/clang/Sema/Sema.h8
-rw-r--r--clang/include/clang/Sema/SemaInternal.h4
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp7
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp234
-rw-r--r--clang/lib/Sema/TreeTransform.h1
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp72
-rw-r--r--clang/test/SemaTemplate/cxx1z-fold-expressions.cpp2
-rw-r--r--clang/test/SemaTemplate/pack-deduction.cpp6
8 files changed, 158 insertions, 176 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 66b018d8fba1..d40dacb5aa0f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -238,11 +238,9 @@ namespace threadSafety {
// FIXME: No way to easily map from TemplateTypeParmTypes to
// TemplateTypeParmDecls, so we have this horrible PointerUnion.
-using UnexpandedParameterPack = std::pair<
- llvm::PointerUnion<
- const TemplateTypeParmType *, const SubstTemplateTypeParmPackType *,
- const SubstNonTypeTemplateParmPackExpr *, const NamedDecl *>,
- SourceLocation>;
+typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>,
+ SourceLocation>
+ UnexpandedParameterPack;
/// Describes whether we've seen any nullability information for the given
/// file.
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 4eca50919dc7..842eec099540 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -62,7 +62,7 @@ inline InheritableAttr *getDLLAttr(Decl *D) {
}
/// Retrieve the depth and index of a template parameter.
-inline std::pair<unsigned, unsigned> getDepthAndIndex(const NamedDecl *ND) {
+inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
@@ -79,7 +79,7 @@ getDepthAndIndex(UnexpandedParameterPack UPP) {
if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
return std::make_pair(TTP->getDepth(), TTP->getIndex());
- return getDepthAndIndex(UPP.first.get<const NamedDecl *>());
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
}
class TypoCorrectionConsumer : public VisibleDeclConsumer {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 9e48a2a35a34..1fe2d3fac685 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -756,11 +756,8 @@ private:
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
- UnexpandedParameterPack U = Unexpanded[I];
- if (U.first.is<const SubstTemplateTypeParmPackType *>() ||
- U.first.is<const SubstNonTypeTemplateParmPackExpr *>())
- continue;
- auto [Depth, Index] = getDepthAndIndex(U);
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == Info.getDeducedDepth())
AddPack(Index);
}
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 01a435668d88..86268b504cbb 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -89,23 +89,6 @@ namespace {
return true;
}
- bool
- VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc TL) {
- Unexpanded.push_back({TL.getTypePtr(), TL.getNameLoc()});
- return true;
- }
-
- bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *T) {
- Unexpanded.push_back({T, SourceLocation()});
- return true;
- }
-
- bool
- VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E) {
- Unexpanded.push_back({E, E->getParameterPackLocation()});
- return true;
- }
-
/// Record occurrences of function and non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
@@ -324,8 +307,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack);
return TTPD && TTPD->getTypeForDecl() == TTPT;
}
- return declaresSameEntity(Pack.first.get<const NamedDecl *>(),
- LocalPack);
+ return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack);
};
if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack))
LambdaParamPackReferences.push_back(Pack);
@@ -377,7 +359,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getIdentifier();
else
- Name = Unexpanded[I].first.get<const NamedDecl *>()->getIdentifier();
+ Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
if (Name && NamesKnown.insert(Name).second)
Names.push_back(Name);
@@ -440,7 +422,7 @@ bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end());
SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
for (auto Parm : Unexpanded)
- if (ParmSet.contains(Parm.first.dyn_cast<const NamedDecl *>()))
+ if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>()))
UnexpandedParms.push_back(Parm);
if (UnexpandedParms.empty())
return false;
@@ -692,95 +674,109 @@ bool Sema::CheckParameterPacksForExpansion(
bool &RetainExpansion, std::optional<unsigned> &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
- std::pair<const IdentifierInfo *, SourceLocation> FirstPack;
- std::optional<std::pair<unsigned, SourceLocation>> PartialExpansion;
- std::optional<unsigned> CurNumExpansions;
+ std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+ bool HaveFirstPack = false;
+ std::optional<unsigned> NumPartialExpansions;
+ SourceLocation PartiallySubstitutedPackLoc;
- for (auto [P, Loc] : Unexpanded) {
+ for (UnexpandedParameterPack ParmPack : Unexpanded) {
// Compute the depth and index for this parameter pack.
- std::optional<std::pair<unsigned, unsigned>> Pos;
+ unsigned Depth = 0, Index = 0;
+ IdentifierInfo *Name;
+ bool IsVarDeclPack = false;
+
+ if (const TemplateTypeParmType *TTP =
+ ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ Name = TTP->getIdentifier();
+ } else {
+ NamedDecl *ND = ParmPack.first.get<NamedDecl *>();
+ if (isa<VarDecl>(ND))
+ IsVarDeclPack = true;
+ else
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
+
+ Name = ND->getIdentifier();
+ }
+
+ // Determine the size of this argument pack.
unsigned NewPackSize;
- const auto *ND = P.dyn_cast<const NamedDecl *>();
- if (ND && isa<VarDecl>(ND)) {
- const auto *DAP =
- CurrentInstantiationScope->findInstantiationOf(ND)
- ->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
- if (!DAP) {
+ if (IsVarDeclPack) {
+ // Figure out whether we're instantiating to an argument pack or not.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
+ CurrentInstantiationScope->findInstantiationOf(
+ ParmPack.first.get<NamedDecl *>());
+ if (Instantiation->is<DeclArgumentPack *>()) {
+ // We could expand this function parameter pack.
+ NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
+ } else {
// We can't expand this function parameter pack, so we can't expand
// the pack expansion.
ShouldExpand = false;
continue;
}
- NewPackSize = DAP->size();
- } else if (ND) {
- Pos = getDepthAndIndex(ND);
- } else if (const auto *TTP = P.dyn_cast<const TemplateTypeParmType *>()) {
- Pos = {TTP->getDepth(), TTP->getIndex()};
- ND = TTP->getDecl();
- // FIXME: We either should have some fallback for canonical TTP, or
- // never have canonical TTP here.
- } else if (const auto *STP =
- P.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
- NewPackSize = STP->getNumArgs();
- ND = STP->getReplacedParameter();
} else {
- const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>();
- NewPackSize = SEP->getArgumentPack().pack_size();
- ND = SEP->getParameterPack();
- }
-
- if (Pos) {
// If we don't have a template argument at this depth/index, then we
// cannot expand the pack expansion. Make a note of this, but we still
// want to check any parameter packs we *do* have arguments for.
- if (Pos->first >= TemplateArgs.getNumLevels() ||
- !TemplateArgs.hasTemplateArgument(Pos->first, Pos->second)) {
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index)) {
ShouldExpand = false;
continue;
}
+
// Determine the size of the argument pack.
- NewPackSize = TemplateArgs(Pos->first, Pos->second).pack_size();
- // C++0x [temp.arg.explicit]p9:
- // Template argument deduction can extend the sequence of template
- // arguments corresponding to a template parameter pack, even when the
- // sequence contains explicitly specified template arguments.
- if (CurrentInstantiationScope)
- if (const NamedDecl *PartialPack =
- CurrentInstantiationScope->getPartiallySubstitutedPack();
- PartialPack && getDepthAndIndex(PartialPack) == *Pos) {
+ NewPackSize = TemplateArgs(Depth, Index).pack_size();
+ }
+
+ // C++0x [temp.arg.explicit]p9:
+ // Template argument deduction can extend the sequence of template
+ // arguments corresponding to a template parameter pack, even when the
+ // sequence contains explicitly specified template arguments.
+ if (!IsVarDeclPack && CurrentInstantiationScope) {
+ if (NamedDecl *PartialPack =
+ CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ unsigned PartialDepth, PartialIndex;
+ std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ if (PartialDepth == Depth && PartialIndex == Index) {
RetainExpansion = true;
// We don't actually know the new pack size yet.
- PartialExpansion = {NewPackSize, Loc};
+ NumPartialExpansions = NewPackSize;
+ PartiallySubstitutedPackLoc = ParmPack.second;
continue;
}
+ }
}
- // FIXME: Workaround for Canonical TTP.
- const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr;
- if (!CurNumExpansions) {
+ if (!NumExpansions) {
// The is the first pack we've seen for which we have an argument.
// Record it.
- CurNumExpansions = NewPackSize;
- FirstPack = {Name, Loc};
- } else if (NewPackSize != *CurNumExpansions) {
+ NumExpansions = NewPackSize;
+ FirstPack.first = Name;
+ FirstPack.second = ParmPack.second;
+ HaveFirstPack = true;
+ continue;
+ }
+
+ if (NewPackSize != *NumExpansions) {
// C++0x [temp.variadic]p5:
// All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
- Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
- << FirstPack.first << Name << *CurNumExpansions << NewPackSize
- << SourceRange(FirstPack.second) << SourceRange(Loc);
+ if (HaveFirstPack)
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+ << FirstPack.first << Name << *NumExpansions << NewPackSize
+ << SourceRange(FirstPack.second) << SourceRange(ParmPack.second);
+ else
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
+ << Name << *NumExpansions << NewPackSize
+ << SourceRange(ParmPack.second);
return true;
}
}
- if (NumExpansions && CurNumExpansions &&
- *NumExpansions != *CurNumExpansions) {
- Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
- << FirstPack.first << *CurNumExpansions << *NumExpansions
- << SourceRange(FirstPack.second);
- return true;
- }
-
// If we're performing a partial expansion but we also have a full expansion,
// expand to the number of common arguments. For example, given:
//
@@ -790,18 +786,17 @@ bool Sema::CheckParameterPacksForExpansion(
//
// ... a call to 'A<int, int>().f<int>' should expand the pack once and
// retain an expansion.
- if (PartialExpansion) {
- if (CurNumExpansions && *CurNumExpansions < PartialExpansion->first) {
+ if (NumPartialExpansions) {
+ if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
- << PartialPack << PartialExpansion->first << *CurNumExpansions
- << SourceRange(PartialExpansion->second);
+ << PartialPack << *NumPartialExpansions << *NumExpansions
+ << SourceRange(PartiallySubstitutedPackLoc);
return true;
}
- NumExpansions = PartialExpansion->first;
- } else {
- NumExpansions = CurNumExpansions;
+
+ NumExpansions = NumPartialExpansions;
}
return false;
@@ -814,48 +809,47 @@ std::optional<unsigned> Sema::getNumArgumentsInExpansion(
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
std::optional<unsigned> Result;
- auto setResultSz = [&Result](unsigned Size) {
- assert((!Result || *Result == Size) && "inconsistent pack sizes");
- Result = Size;
- };
- auto setResultPos = [&](const std::pair<unsigned, unsigned> &Pos) -> bool {
- unsigned Depth = Pos.first, Index = Pos.second;
- if (Depth >= TemplateArgs.getNumLevels() ||
- !TemplateArgs.hasTemplateArgument(Depth, Index))
- // The pattern refers to an unknown template argument. We're not ready to
- // expand this pack yet.
- return true;
- // Determine the size of the argument pack.
- setResultSz(TemplateArgs(Depth, Index).pack_size());
- return false;
- };
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth;
+ unsigned Index;
- for (auto [I, _] : Unexpanded) {
- if (const auto *TTP = I.dyn_cast<const TemplateTypeParmType *>()) {
- if (setResultPos({TTP->getDepth(), TTP->getIndex()}))
- return std::nullopt;
- } else if (const auto *STP =
- I.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
- setResultSz(STP->getNumArgs());
- } else if (const auto *SEP =
- I.dyn_cast<const SubstNonTypeTemplateParmPackExpr *>()) {
- setResultSz(SEP->getArgumentPack().pack_size());
+ if (const TemplateTypeParmType *TTP =
+ Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
} else {
- const auto *ND = I.get<const NamedDecl *>();
- // Function parameter pack or init-capture pack.
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<VarDecl>(ND)) {
- const auto *DAP =
- CurrentInstantiationScope->findInstantiationOf(ND)
- ->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
- if (!DAP)
+ // Function parameter pack or init-capture pack.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
+ CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation->is<Decl *>())
// The pattern refers to an unexpanded pack. We're not ready to expand
// this pack yet.
return std::nullopt;
- setResultSz(DAP->size());
- } else if (setResultPos(getDepthAndIndex(ND))) {
- return std::nullopt;
+
+ unsigned Size = Instantiation->get<DeclArgumentPack *>()->size();
+ assert((!Result || *Result == Size) && "inconsistent pack sizes");
+ Result = Size;
+ continue;
}
+
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
}
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index))
+ // The pattern refers to an unknown template argument. We're not ready to
+ // expand this pack yet.
+ return std::nullopt;
+
+ // Determine the size of the argument pack.
+ unsigned Size = TemplateArgs(Depth, Index).pack_size();
+ assert((!Result || *Result == Size) && "inconsistent pack sizes");
+ Result = Size;
}
return Result;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 9d4c7b01aa5c..48bb28b56cd3 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -5897,7 +5897,6 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams(
= dyn_cast<PackExpansionType>(OldType)) {
// We have a function parameter pack that may need to be expanded.
QualType Pattern = Expansion->getPattern();
- NumExpansions = Expansion->getNumExpansions();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 2d82a4f26b14..7542186c22c7 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -473,51 +473,45 @@ int fn() {
}
}
-namespace pr56094 {
-template <typename... T> struct D {
- template <typename... U> using B = int(int (*...p)(T, U));
- // expected-error@-1 {{pack expansion contains parameter packs 'T' and 'U' that have different lengths (1 vs. 2)}}
- template <typename U1, typename U2> D(B<U1, U2> *);
- // expected-note@-1 {{in instantiation of template type alias 'B' requested here}}
+namespace GH58452 {
+template <typename... As> struct A {
+ template <typename... Bs> using B = void(As...(Bs));
};
-using t1 = D<float>::B<int>;
-// expected-note@-1 {{in instantiation of template class 'pr56094::D<float>' requested here}}
-
-template <bool...> struct F {};
-template <class...> struct G {};
-template <bool... I> struct E {
- template <bool... U> using B = G<F<I, U>...>;
- // expected-error@-1 {{pack expansion contains parameter packs 'I' and 'U' that have different lengths (1 vs. 2)}}
- template <bool U1, bool U2> E(B<U1, U2> *);
- // expected-note@-1 {{in instantiation of template type alias 'B' requested here}}
+
+template <typename... Cs> struct C {
+ template <typename... Ds> using D = typename A<Cs...>::template B<Ds...>;
};
-using t2 = E<true>::B<false>;
-// expected-note@-1 {{in instantiation of template class 'pr56094::E<true>' requested here}}
-} // namespace pr56094
-
-namespace GH56094 {
-#if __cplusplus >= 201402L
-template <class> struct A; // expected-note {{template is declared here}}
-template <class> using B = char;
-template <class ...Cs> int C{ A<B<Cs>>{}... }; // expected-error {{implicit instantiation of undefined template}}
-#endif
-} // namespace GH56094
-namespace GH58679 {
-#if __cplusplus >= 201402L
-template <class> constexpr int A = 1;
+using t1 = C<int, int>::template D<float, float>;
-template <int> struct B;
-template <> struct B<1> { using b1 = void; };
+template <typename A, typename B>
+using ConditionalRewrite = B;
-template <class> using C = char;
+template <typename T>
+using SignatureType = int;
-template <class... Ds> int D{ B<A<C<Ds>>>{}... };
+template <typename... Args>
+struct Type1 {
+ template <typename... Params>
+ using Return = SignatureType<int(ConditionalRewrite<Args, Params>...)>;
-struct E {
- template <class E1, class = typename B<A<E1>>::b1> E(E1);
};
-template <typename... Es> int F{ E(C<Es>{})... };
-#endif
-} // namespace GH58679
+template <typename... Args>
+struct Type2 {
+ using T1 = Type1<Args...>;
+
+ template <typename... Params>
+ using Return = typename T1::template Return<Params...>;
+
+};
+
+template <typename T>
+typename T::template Return<int, int> InvokeMethod() {
+ return 3;
+}
+
+int Function1() {
+ return InvokeMethod<Type2<int, int>>();
+}
+}
diff --git a/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp b/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp
index 98876baf1f3e..518eaf0e0523 100644
--- a/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp
+++ b/clang/test/SemaTemplate/cxx1z-fold-expressions.cpp
@@ -97,7 +97,7 @@ namespace PR41845 {
template <int I> struct Constant {};
template <int... Is> struct Sum {
- template <int... Js> using type = Constant<((Is + Js) + ... + 0)>; // expected-error {{pack expansion contains parameter packs 'Is' and 'Js' that have different lengths (1 vs. 2)}}
+ template <int... Js> using type = Constant<((Is + Js) + ... + 0)>; // expected-error {{pack expansion contains parameter pack 'Js' that has a different length (1 vs. 2) from outer parameter packs}}
};
Sum<1>::type<1, 2> x; // expected-note {{instantiation of}}
diff --git a/clang/test/SemaTemplate/pack-deduction.cpp b/clang/test/SemaTemplate/pack-deduction.cpp
index f07bafdf86bc..e42709820e9c 100644
--- a/clang/test/SemaTemplate/pack-deduction.cpp
+++ b/clang/test/SemaTemplate/pack-deduction.cpp
@@ -134,14 +134,14 @@ namespace partial_full_mix {
template<typename ...T> struct tuple {};
template<typename ...T> struct A {
template<typename ...U> static pair<tuple<T...>, tuple<U...>> f(pair<T, U> ...p);
- // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter packs 'T' and 'U' that have different lengths (2 vs. 3)}}
+ // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}}
// expected-note@-2 {{[with U = <char, double, void>]: pack expansion contains parameter pack 'U' that has a different length (at least 3 vs. 2) from outer parameter packs}}
template<typename ...U> static pair<tuple<T...>, tuple<U...>> g(pair<T, U> ...p, ...);
- // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter packs 'T' and 'U' that have different lengths (2 vs. 3)}}
+ // expected-note@-1 {{[with U = <char, double, long>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}}
template<typename ...U> static tuple<U...> h(tuple<pair<T, U>..., pair<int, int>>);
- // expected-note@-1 {{[with U = <int[2]>]: pack expansion contains parameter packs 'T' and 'U' that have different lengths (2 vs. 1)}}
+ // expected-note@-1 {{[with U = <int[2]>]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 1) from outer parameter packs}}
};
pair<tuple<int, float>, tuple<char, double>> k1 = A<int, float>().f<char>(pair<int, char>(), pair<float, double>());