[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