mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 06:10:12 +00:00
Revert two patches to fix GH58452 regression
GH58452 is a regression in the 16.0 release branch caused by both:b8a1b698af
and3a0309c536
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 commit3a0309c536
. Revert "[clang] fix missing initialization of original number of expansions" This reverts commitb8a1b698af
. Differential Revision: https://reviews.llvm.org/D145605
This commit is contained in:
parent
9c645a99e4
commit
acecf68c8b
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
RetainExpansion = true;
|
||||
// We don't actually know the new pack size yet.
|
||||
PartialExpansion = {NewPackSize, Loc};
|
||||
continue;
|
||||
}
|
||||
NewPackSize = TemplateArgs(Depth, Index).pack_size();
|
||||
}
|
||||
|
||||
// FIXME: Workaround for Canonical TTP.
|
||||
const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr;
|
||||
if (!CurNumExpansions) {
|
||||
// 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.
|
||||
NumPartialExpansions = NewPackSize;
|
||||
PartiallySubstitutedPackLoc = ParmPack.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
|
||||
// Compute the depth and index for this parameter pack.
|
||||
unsigned Depth;
|
||||
unsigned Index;
|
||||
|
||||
if (const TemplateTypeParmType *TTP =
|
||||
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
} else {
|
||||
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
|
||||
if (isa<VarDecl>(ND)) {
|
||||
// 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;
|
||||
|
||||
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 true;
|
||||
// Determine the size of the argument pack.
|
||||
setResultSz(TemplateArgs(Depth, Index).pack_size());
|
||||
return false;
|
||||
};
|
||||
return std::nullopt;
|
||||
|
||||
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());
|
||||
} else {
|
||||
const auto *ND = I.get<const NamedDecl *>();
|
||||
// Function parameter pack or init-capture pack.
|
||||
if (isa<VarDecl>(ND)) {
|
||||
const auto *DAP =
|
||||
CurrentInstantiationScope->findInstantiationOf(ND)
|
||||
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
|
||||
if (!DAP)
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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}}
|
||||
};
|
||||
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}}
|
||||
};
|
||||
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;
|
||||
|
||||
template <int> struct B;
|
||||
template <> struct B<1> { using b1 = void; };
|
||||
|
||||
template <class> using C = char;
|
||||
|
||||
template <class... Ds> int D{ B<A<C<Ds>>>{}... };
|
||||
|
||||
struct E {
|
||||
template <class E1, class = typename B<A<E1>>::b1> E(E1);
|
||||
namespace GH58452 {
|
||||
template <typename... As> struct A {
|
||||
template <typename... Bs> using B = void(As...(Bs));
|
||||
};
|
||||
|
||||
template <typename... Es> int F{ E(C<Es>{})... };
|
||||
#endif
|
||||
} // namespace GH58679
|
||||
template <typename... Cs> struct C {
|
||||
template <typename... Ds> using D = typename A<Cs...>::template B<Ds...>;
|
||||
};
|
||||
|
||||
using t1 = C<int, int>::template D<float, float>;
|
||||
|
||||
template <typename A, typename B>
|
||||
using ConditionalRewrite = B;
|
||||
|
||||
template <typename T>
|
||||
using SignatureType = int;
|
||||
|
||||
template <typename... Args>
|
||||
struct Type1 {
|
||||
template <typename... Params>
|
||||
using Return = SignatureType<int(ConditionalRewrite<Args, Params>...)>;
|
||||
|
||||
};
|
||||
|
||||
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>>();
|
||||
}
|
||||
}
|
||||
|
@ -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}}
|
||||
|
@ -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>());
|
||||
|
Loading…
Reference in New Issue
Block a user