[clang] GH70601 (PR #81095)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 7 23:09:12 PST 2024
https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/81095
Testing libc++'s CI.
>From 906fbf5b0796a85bf54028dfaa8e6343ea441a51 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Thu, 8 Feb 2024 15:07:47 +0800
Subject: [PATCH] GH70601
---
clang/include/clang/Sema/Sema.h | 15 ++--
clang/lib/Sema/SemaTemplate.cpp | 83 ++++++++++---------
clang/lib/Sema/SemaTemplateInstantiate.cpp | 21 +++--
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 ++-
clang/test/SemaTemplate/concepts-lambda.cpp | 19 +++++
5 files changed, 92 insertions(+), 58 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3c26003b5bda7..afc74f1a64551 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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);
@@ -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);
@@ -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);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index cf781e0e1bf3f..9c7a936aac1d6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -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(
@@ -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>. [...]
@@ -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;
@@ -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(),
@@ -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;
@@ -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;
@@ -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,
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6d59180bc446d..9c3d2ea77d44e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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,
@@ -2904,7 +2902,8 @@ bool Sema::SubstTypeConstraint(
Inst->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
- : SourceLocation());
+ : SourceLocation(),
+ EvaluateConstraint);
}
ParmVarDecl *Sema::SubstParmVarDecl(
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d67b21b4449e0..ff7b450fc31d4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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;
}
diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp
index 0b7580f91043c..0e93206cbd1a9 100644
--- a/clang/test/SemaTemplate/concepts-lambda.cpp
+++ b/clang/test/SemaTemplate/concepts-lambda.cpp
@@ -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
More information about the cfe-commits
mailing list