Skip to content

Commit e6974da

Browse files
zyn0217cor3ntin
andauthored
[Clang][Concepts] Fix the constraint equivalence checking involving parameter packs (#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 #101735 --------- Co-authored-by: cor3ntin <[email protected]>
1 parent 7e6b150 commit e6974da

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
@@ -977,8 +977,30 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
977977
// equivalence.
978978
LocalInstantiationScope ScopeForParameters(S);
979979
if (auto *FD = DeclInfo.getDecl()->getAsFunction())
980-
for (auto *PVD : FD->parameters())
981-
ScopeForParameters.InstantiatedLocal(PVD, PVD);
980+
for (auto *PVD : FD->parameters()) {
981+
if (!PVD->isParameterPack()) {
982+
ScopeForParameters.InstantiatedLocal(PVD, PVD);
983+
continue;
984+
}
985+
// This is hacky: we're mapping the parameter pack to a size-of-1 argument
986+
// to avoid building SubstTemplateTypeParmPackTypes for
987+
// PackExpansionTypes. The SubstTemplateTypeParmPackType node would
988+
// otherwise reference the AssociatedDecl of the template arguments, which
989+
// is, in this case, the template declaration.
990+
//
991+
// However, as we are in the process of comparing potential
992+
// re-declarations, the canonical declaration is the declaration itself at
993+
// this point. So if we didn't expand these packs, we would end up with an
994+
// incorrect profile difference because we will be profiling the
995+
// canonical types!
996+
//
997+
// FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
998+
// that we can eliminate the Scope in the cases where the declarations are
999+
// not necessarily instantiated. It would also benefit the noexcept
1000+
// specifier comparison.
1001+
ScopeForParameters.MakeInstantiatedLocalArgPack(PVD);
1002+
ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD);
1003+
}
9821004

9831005
std::optional<Sema::CXXThisScopeRAII> ThisScope;
9841006

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)