Skip to content

Commit 3e512ba

Browse files
zyn0217cor3ntin
authored andcommitted
[Clang][Concepts] Fix the constraint equivalence checking involving parameter packs (llvm#102131)
We established an instantiation scope in order for constraint equivalence checking to properly map the uninstantiated parameters. That mechanism mapped even packs to themselves. Consequently, parameter packs e.g. appearing in a function call, were not expanded. So they would end up becoming `SubstTemplateTypeParmPackType`s that circularly depend on the canonical declaration of the function template, which is not yet determined, hence the spurious error. No release note as I plan to backport it to 19. Fixes llvm#101735 --------- Co-authored-by: cor3ntin <[email protected]> (cherry picked from commit e6974da)
1 parent 1720219 commit 3e512ba

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,30 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
969969
// equivalence.
970970
LocalInstantiationScope ScopeForParameters(S);
971971
if (auto *FD = DeclInfo.getDecl()->getAsFunction())
972-
for (auto *PVD : FD->parameters())
973-
ScopeForParameters.InstantiatedLocal(PVD, PVD);
972+
for (auto *PVD : FD->parameters()) {
973+
if (!PVD->isParameterPack()) {
974+
ScopeForParameters.InstantiatedLocal(PVD, PVD);
975+
continue;
976+
}
977+
// This is hacky: we're mapping the parameter pack to a size-of-1 argument
978+
// to avoid building SubstTemplateTypeParmPackTypes for
979+
// PackExpansionTypes. The SubstTemplateTypeParmPackType node would
980+
// otherwise reference the AssociatedDecl of the template arguments, which
981+
// is, in this case, the template declaration.
982+
//
983+
// However, as we are in the process of comparing potential
984+
// re-declarations, the canonical declaration is the declaration itself at
985+
// this point. So if we didn't expand these packs, we would end up with an
986+
// incorrect profile difference because we will be profiling the
987+
// canonical types!
988+
//
989+
// FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
990+
// that we can eliminate the Scope in the cases where the declarations are
991+
// not necessarily instantiated. It would also benefit the noexcept
992+
// specifier comparison.
993+
ScopeForParameters.MakeInstantiatedLocalArgPack(PVD);
994+
ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD);
995+
}
974996

975997
std::optional<Sema::CXXThisScopeRAII> ThisScope;
976998

clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,3 +599,26 @@ template <class DerT>
599599
unsigned long DerivedCollection<DerTs...>::index() {}
600600

601601
} // namespace GH72557
602+
603+
namespace GH101735 {
604+
605+
template <class, class>
606+
concept True = true;
607+
608+
template <typename T>
609+
class A {
610+
template <typename... Ts>
611+
void method(Ts&... ts)
612+
requires requires (T t) {
613+
{ t.method(static_cast<Ts &&>(ts)...) } -> True<void>;
614+
};
615+
};
616+
617+
template <typename T>
618+
template <typename... Ts>
619+
void A<T>::method(Ts&... ts)
620+
requires requires (T t) {
621+
{ t.method(static_cast<Ts &&>(ts)...) } -> True<void>;
622+
} {}
623+
624+
}

0 commit comments

Comments
 (0)