Skip to content

Commit de90a38

Browse files
committed
CWG 2369
1 parent 3364284 commit de90a38

File tree

5 files changed

+122
-30
lines changed

5 files changed

+122
-30
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13058,7 +13058,8 @@ class Sema final : public SemaBase {
1305813058
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
1305913059
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
1306013060
bool ForConstraintInstantiation = false,
13061-
bool SkipForSpecialization = false);
13061+
bool SkipForSpecialization = false,
13062+
MultiLevelTemplateArgumentList *Merged = nullptr);
1306213063

1306313064
/// RAII object to handle the state changes required to synthesize
1306413065
/// a function body.

clang/lib/Sema/SemaConcept.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
842842
bool ForOverloadResolution) {
843843
// Don't check constraints if the function is dependent. Also don't check if
844844
// this is a function template specialization, as the call to
845-
// CheckinstantiatedFunctionTemplateConstraints after this will check it
845+
// CheckInstantiatedFunctionTemplateConstraints after this will check it
846846
// better.
847847
if (FD->isDependentContext() ||
848848
FD->getTemplatedKind() ==

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,18 +3834,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
38343834
Result != TemplateDeductionResult::Success)
38353835
return Result;
38363836

3837-
// C++ [temp.deduct.call]p10: [DR1391]
3838-
// If deduction succeeds for all parameters that contain
3839-
// template-parameters that participate in template argument deduction,
3840-
// and all template arguments are explicitly specified, deduced, or
3841-
// obtained from default template arguments, remaining parameters are then
3842-
// compared with the corresponding arguments. For each remaining parameter
3843-
// P with a type that was non-dependent before substitution of any
3844-
// explicitly-specified template arguments, if the corresponding argument
3845-
// A cannot be implicitly converted to P, deduction fails.
3846-
if (CheckNonDependent())
3847-
return TemplateDeductionResult::NonDependentConversionFailure;
3848-
38493837
// Form the template argument list from the deduced template arguments.
38503838
TemplateArgumentList *SugaredDeducedArgumentList =
38513839
TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
@@ -3875,6 +3863,76 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
38753863
FD = const_cast<FunctionDecl *>(FDFriend);
38763864
Owner = FD->getLexicalDeclContext();
38773865
}
3866+
#if 1
3867+
// FIXME: We have to partially instantiate lambda's captures for constraint
3868+
// evaluation.
3869+
if (!isLambdaCallOperator(FD) && !isLambdaConversionOperator(FD) &&
3870+
(!PartialOverloading ||
3871+
(CanonicalBuilder.size() ==
3872+
FunctionTemplate->getTemplateParameters()->size()))) {
3873+
FunctionTemplateDecl *Template = FunctionTemplate->getCanonicalDecl();
3874+
FunctionDecl *FD = Template->getTemplatedDecl();
3875+
SmallVector<const Expr *, 3> TemplateAC;
3876+
Template->getAssociatedConstraints(TemplateAC);
3877+
if (!TemplateAC.empty()) {
3878+
3879+
// Enter the scope of this instantiation. We don't use
3880+
// PushDeclContext because we don't have a scope.
3881+
LocalInstantiationScope Scope(*this);
3882+
3883+
// Collect the list of template arguments relative to the 'primary'
3884+
// template. We need the entire list, since the constraint is completely
3885+
// uninstantiated at this point.
3886+
3887+
MultiLevelTemplateArgumentList MLTAL(FD, SugaredBuilder, /*Final=*/false);
3888+
getTemplateInstantiationArgs(nullptr, FD->getLexicalDeclContext(),
3889+
/*Final=*/false,
3890+
/*Innermost=*/std::nullopt,
3891+
/*RelativeToPrimary=*/true,
3892+
/*Pattern=*/nullptr,
3893+
/*ForConstraintInstantiation=*/true,
3894+
/*SkipForSpecialization=*/false,
3895+
/*Merged=*/&MLTAL);
3896+
3897+
// if (SetupConstraintScope(FD, SugaredBuilder, MLTAL, Scope))
3898+
// return TemplateDeductionResult::MiscellaneousDeductionFailure;
3899+
3900+
MultiLevelTemplateArgumentList JustTemplArgs(
3901+
Template, CanonicalDeducedArgumentList->asArray(),
3902+
/*Final=*/false);
3903+
if (addInstantiatedParametersToScope(nullptr, FD, Scope, JustTemplArgs))
3904+
return TemplateDeductionResult::MiscellaneousDeductionFailure;
3905+
3906+
if (FunctionTemplateDecl *FromMemTempl =
3907+
Template->getInstantiatedFromMemberTemplate()) {
3908+
while (FromMemTempl->getInstantiatedFromMemberTemplate())
3909+
FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
3910+
if (addInstantiatedParametersToScope(
3911+
nullptr, FromMemTempl->getTemplatedDecl(), Scope, MLTAL))
3912+
return TemplateDeductionResult::MiscellaneousDeductionFailure;
3913+
}
3914+
3915+
Qualifiers ThisQuals;
3916+
CXXRecordDecl *Record = nullptr;
3917+
if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
3918+
ThisQuals = Method->getMethodQualifiers();
3919+
Record = Method->getParent();
3920+
}
3921+
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
3922+
llvm::SmallVector<Expr *, 1> Converted;
3923+
if (CheckConstraintSatisfaction(Template, TemplateAC, MLTAL,
3924+
Template->getSourceRange(),
3925+
Info.AssociatedConstraintsSatisfaction))
3926+
return TemplateDeductionResult::MiscellaneousDeductionFailure;
3927+
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
3928+
Info.reset(TemplateArgumentList::CreateCopy(Context, SugaredBuilder),
3929+
Info.takeCanonical());
3930+
return TemplateDeductionResult::ConstraintsNotSatisfied;
3931+
}
3932+
}
3933+
}
3934+
#endif
3935+
38783936
MultiLevelTemplateArgumentList SubstArgs(
38793937
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
38803938
/*Final=*/false);
@@ -3924,6 +3982,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
39243982
}
39253983
}
39263984

3985+
// C++ [temp.deduct.call]p10: [DR1391]
3986+
// If deduction succeeds for all parameters that contain
3987+
// template-parameters that participate in template argument deduction,
3988+
// and all template arguments are explicitly specified, deduced, or
3989+
// obtained from default template arguments, remaining parameters are then
3990+
// compared with the corresponding arguments. For each remaining parameter
3991+
// P with a type that was non-dependent before substitution of any
3992+
// explicitly-specified template arguments, if the corresponding argument
3993+
// A cannot be implicitly converted to P, deduction fails.
3994+
if (CheckNonDependent())
3995+
return TemplateDeductionResult::NonDependentConversionFailure;
3996+
39273997
// We skipped the instantiation of the explicit-specifier during the
39283998
// substitution of `FD` before. So, we try to instantiate it back if
39293999
// `Specialization` is either a constructor or a conversion function.

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,11 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
467467
const NamedDecl *ND, const DeclContext *DC, bool Final,
468468
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
469469
const FunctionDecl *Pattern, bool ForConstraintInstantiation,
470-
bool SkipForSpecialization) {
470+
bool SkipForSpecialization, MultiLevelTemplateArgumentList *Merged) {
471471
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
472472
// Accumulate the set of template argument lists in this structure.
473-
MultiLevelTemplateArgumentList Result;
473+
MultiLevelTemplateArgumentList Ret;
474+
MultiLevelTemplateArgumentList &Result = Merged ? *Merged : Ret;
474475

475476
using namespace TemplateInstArgsHelpers;
476477
const Decl *CurDecl = ND;

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4577,17 +4577,17 @@ void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function,
45774577
}
45784578
}
45794579

4580-
bool Sema::addInstantiatedParametersToScope(
4581-
FunctionDecl *Function, const FunctionDecl *PatternDecl,
4582-
LocalInstantiationScope &Scope,
4580+
static bool addInstantiatedParametersToScope(
4581+
Sema &SemaRef, MutableArrayRef<ParmVarDecl *> InstantiatedParamDecls,
4582+
const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope,
45834583
const MultiLevelTemplateArgumentList &TemplateArgs) {
45844584
unsigned FParamIdx = 0;
45854585
for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
45864586
const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
45874587
if (!PatternParam->isParameterPack()) {
45884588
// Simple case: not a parameter pack.
4589-
assert(FParamIdx < Function->getNumParams());
4590-
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
4589+
assert(FParamIdx < InstantiatedParamDecls.size());
4590+
ParmVarDecl *FunctionParam = InstantiatedParamDecls[FParamIdx];
45914591
FunctionParam->setDeclName(PatternParam->getDeclName());
45924592
// If the parameter's type is not dependent, update it to match the type
45934593
// in the pattern. They can differ in top-level cv-qualifiers, and we want
@@ -4596,9 +4596,9 @@ bool Sema::addInstantiatedParametersToScope(
45964596
// it's instantiation-dependent.
45974597
// FIXME: Updating the type to work around this is at best fragile.
45984598
if (!PatternDecl->getType()->isDependentType()) {
4599-
QualType T = SubstType(PatternParam->getType(), TemplateArgs,
4600-
FunctionParam->getLocation(),
4601-
FunctionParam->getDeclName());
4599+
QualType T = SemaRef.SubstType(PatternParam->getType(), TemplateArgs,
4600+
FunctionParam->getLocation(),
4601+
FunctionParam->getDeclName());
46024602
if (T.isNull())
46034603
return true;
46044604
FunctionParam->setType(T);
@@ -4612,18 +4612,19 @@ bool Sema::addInstantiatedParametersToScope(
46124612
// Expand the parameter pack.
46134613
Scope.MakeInstantiatedLocalArgPack(PatternParam);
46144614
std::optional<unsigned> NumArgumentsInExpansion =
4615-
getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
4615+
SemaRef.getNumArgumentsInExpansion(PatternParam->getType(),
4616+
TemplateArgs);
46164617
if (NumArgumentsInExpansion) {
46174618
QualType PatternType =
46184619
PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
46194620
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
4620-
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
4621+
ParmVarDecl *FunctionParam = InstantiatedParamDecls[FParamIdx];
46214622
FunctionParam->setDeclName(PatternParam->getDeclName());
46224623
if (!PatternDecl->getType()->isDependentType()) {
4623-
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Arg);
4624-
QualType T =
4625-
SubstType(PatternType, TemplateArgs, FunctionParam->getLocation(),
4626-
FunctionParam->getDeclName());
4624+
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, Arg);
4625+
QualType T = SemaRef.SubstType(PatternType, TemplateArgs,
4626+
FunctionParam->getLocation(),
4627+
FunctionParam->getDeclName());
46274628
if (T.isNull())
46284629
return true;
46294630
FunctionParam->setType(T);
@@ -4638,6 +4639,25 @@ bool Sema::addInstantiatedParametersToScope(
46384639
return false;
46394640
}
46404641

4642+
bool Sema::addInstantiatedParametersToScope(
4643+
FunctionDecl *Function, const FunctionDecl *PatternDecl,
4644+
LocalInstantiationScope &Scope,
4645+
const MultiLevelTemplateArgumentList &TemplateArgs) {
4646+
if (Function)
4647+
return ::addInstantiatedParametersToScope(*this, Function->parameters(),
4648+
PatternDecl, Scope, TemplateArgs);
4649+
FunctionTypeLoc TypeLoc = PatternDecl->getFunctionTypeLoc();
4650+
assert(!TypeLoc.isNull() && "Invalid function TypeLoc?");
4651+
SmallVector<QualType> ParamTypes;
4652+
SmallVector<ParmVarDecl *> OutParams;
4653+
Sema::ExtParameterInfoBuilder ExtParamInfos;
4654+
if (SubstParmTypes(PatternDecl->getLocation(), TypeLoc.getParams(), nullptr,
4655+
TemplateArgs, ParamTypes, &OutParams, ExtParamInfos))
4656+
return true;
4657+
return ::addInstantiatedParametersToScope(*this, OutParams, PatternDecl,
4658+
Scope, TemplateArgs);
4659+
}
4660+
46414661
bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
46424662
ParmVarDecl *Param) {
46434663
assert(Param->hasUninstantiatedDefaultArg());

0 commit comments

Comments
 (0)