Skip to content

GH70601 #81095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

GH70601 #81095

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8343,12 +8343,14 @@ class Sema final {
ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs,
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc);
SourceLocation EllipsisLoc,
bool EvaluateConstraint = true);

bool AttachTypeConstraint(AutoTypeLoc TL,
NonTypeTemplateParmDecl *NewConstrainedParm,
NonTypeTemplateParmDecl *OrigConstrainedParm,
SourceLocation EllipsisLoc);
SourceLocation EllipsisLoc,
bool EvaluateConstraint = true);

bool RequireStructuralType(QualType T, SourceLocation Loc);

Expand Down Expand Up @@ -8479,11 +8481,11 @@ class Sema final {
const TemplateArgumentListInfo *TemplateArgs);

ExprResult
CheckConceptTemplateId(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs);
const TemplateArgumentListInfo *TemplateArgs,
bool EvaluateConstraint = true);

void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);

Expand Down Expand Up @@ -10518,7 +10520,8 @@ class Sema final {

bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool EvaluateConstraint);
bool RebuildConstraint,
bool EvaluateConstraints = true);

bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param);
Expand Down
83 changes: 43 additions & 40 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1176,13 +1176,13 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
ConstrainedParameter, EllipsisLoc);
}

template<typename ArgumentLocAppender>
template <typename ArgumentLocAppender>
static ExprResult formImmediatelyDeclaredConstraint(
Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
ConceptDecl *NamedConcept, SourceLocation LAngleLoc,
SourceLocation RAngleLoc, QualType ConstrainedType,
SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
SourceLocation EllipsisLoc) {
SourceLocation EllipsisLoc, bool EvaluateConstraint) {

TemplateArgumentListInfo ConstraintArgs;
ConstraintArgs.addArgument(
Expand Down Expand Up @@ -1233,7 +1233,8 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs,
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc) {
SourceLocation EllipsisLoc,
bool EvaluateConstraint) {
// C++2a [temp.param]p4:
// [...] If Q is of the form C<A1, ..., An>, then let E' be
// C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
Expand All @@ -1243,17 +1244,17 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,

QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);

ExprResult ImmediatelyDeclaredConstraint =
formImmediatelyDeclaredConstraint(
*this, NS, NameInfo, NamedConcept,
TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
ParamAsArgument, ConstrainedParameter->getLocation(),
[&] (TemplateArgumentListInfo &ConstraintArgs) {
if (TemplateArgs)
for (const auto &ArgLoc : TemplateArgs->arguments())
ConstraintArgs.addArgument(ArgLoc);
}, EllipsisLoc);
ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
*this, NS, NameInfo, NamedConcept,
TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
ParamAsArgument, ConstrainedParameter->getLocation(),
[&](TemplateArgumentListInfo &ConstraintArgs) {
if (TemplateArgs)
for (const auto &ArgLoc : TemplateArgs->arguments())
ConstraintArgs.addArgument(ArgLoc);
},
EllipsisLoc, EvaluateConstraint);
if (ImmediatelyDeclaredConstraint.isInvalid())
return true;

Expand All @@ -1271,7 +1272,8 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
NonTypeTemplateParmDecl *NewConstrainedParm,
NonTypeTemplateParmDecl *OrigConstrainedParm,
SourceLocation EllipsisLoc) {
SourceLocation EllipsisLoc,
bool EvaluateConstraint) {
if (NewConstrainedParm->getType() != TL.getType() ||
TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
Expand All @@ -1296,7 +1298,7 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
ConstraintArgs.addArgument(TL.getArgLoc(I));
},
EllipsisLoc);
EllipsisLoc, EvaluateConstraint);
if (ImmediatelyDeclaredConstraint.isInvalid() ||
!ImmediatelyDeclaredConstraint.isUsable())
return true;
Expand Down Expand Up @@ -4990,13 +4992,11 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
}
}

ExprResult
Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &ConceptNameInfo,
NamedDecl *FoundDecl,
ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs) {
ExprResult Sema::CheckConceptTemplateId(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
ConceptDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs,
bool EvaluateConstraint) {
assert(NamedConcept && "A concept template id without a template?");

llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
Expand All @@ -5011,30 +5011,33 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
CanonicalConverted);
ConstraintSatisfaction Satisfaction;
bool AreArgsDependent =
TemplateSpecializationType::anyDependentTemplateArguments(
bool ShouldEvaluate =
EvaluateConstraint &&
!TemplateSpecializationType::anyDependentTemplateArguments(
*TemplateArgs, CanonicalConverted);
MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
/*Final=*/false);
LocalInstantiationScope Scope(*this);

EnterExpressionEvaluationContext EECtx{
*this, ExpressionEvaluationContext::ConstantEvaluated, CSD};

if (!AreArgsDependent &&
CheckConstraintSatisfaction(
NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
TemplateArgs->getRAngleLoc()),
Satisfaction))
return ExprError();
if (ShouldEvaluate) {
MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
/*Final=*/false);
LocalInstantiationScope Scope(*this);

EnterExpressionEvaluationContext EECtx{
*this, ExpressionEvaluationContext::ConstantEvaluated, CSD};

if (CheckConstraintSatisfaction(
NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
SourceRange(SS.isSet() ? SS.getBeginLoc()
: ConceptNameInfo.getLoc(),
TemplateArgs->getRAngleLoc()),
Satisfaction))
return ExprError();
}
auto *CL = ConceptReference::Create(
Context,
SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
return ConceptSpecializationExpr::Create(
Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
Context, CL, CSD, !ShouldEvaluate ? nullptr : &Satisfaction);
}

ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
Expand Down
21 changes: 10 additions & 11 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2878,20 +2878,18 @@ namespace {

bool Sema::SubstTypeConstraint(
TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool EvaluateConstraints) {
const ASTTemplateArgumentListInfo *TemplArgInfo =
TC->getTemplateArgsAsWritten();

if (!EvaluateConstraints) {
Inst->setTypeConstraint(TC->getConceptReference(),
TC->getImmediatelyDeclaredConstraint());
return false;
const MultiLevelTemplateArgumentList &TemplateArgs, bool RebuildConstraint,
bool EvaluateConstraint) {
if (!RebuildConstraint) {
Inst->setTypeConstraint(TC->getConceptReference(),
TC->getImmediatelyDeclaredConstraint());
return false;
}

TemplateArgumentListInfo InstArgs;

if (TemplArgInfo) {
if (const ASTTemplateArgumentListInfo *TemplArgInfo =
TC->getTemplateArgsAsWritten()) {
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs,
Expand All @@ -2904,7 +2902,8 @@ bool Sema::SubstTypeConstraint(
Inst->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
: SourceLocation());
: SourceLocation(),
EvaluateConstraint);
}

ParmVarDecl *Sema::SubstParmVarDecl(
Expand Down
12 changes: 11 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2903,10 +2903,20 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
Inst->setImplicit(D->isImplicit());
if (auto *TC = D->getTypeConstraint()) {
if (!D->isImplicit()) {
bool RebuildConstraint = [&] {
if (EvaluateConstraints)
return true;
for (auto Active = SemaRef.CodeSynthesisContexts.rbegin();
Active != SemaRef.CodeSynthesisContexts.rend(); ++Active) {
if (llvm::isa_and_present<TypeAliasTemplateDecl>(Active->Entity))
return true;
}
return false;
}();
// Invented template parameter type constraints will be instantiated
// with the corresponding auto-typed parameter as it might reference
// other parameters.
if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs,
if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs, RebuildConstraint,
EvaluateConstraints))
return nullptr;
}
Expand Down
19 changes: 19 additions & 0 deletions clang/test/SemaTemplate/concepts-lambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,22 @@ void foo() {
}(x);
}
} // namespace GH73418

namespace GH70601 {

template <class>
concept C = true;

template <class T, class U>
concept D = C<T> && C<U>;

template <class T>
using Type = decltype([]<C U> {
return []<D<U> V>(V val) {
return val;
}(U());
}.template operator()<T>());

static_assert(__is_same(Type<int>, int));

} // namespace GH70601