[clang] 13d44a8 - Revert "[Clang][Sema] Fix comparison of constraint expressions"

Alexander Shaposhnikov via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 7 11:43:06 PDT 2023


Author: Alexander Shaposhnikov
Date: 2023-04-07T18:41:57Z
New Revision: 13d44a8f5647819efd3ef57af384a3666f99d066

URL: https://github.com/llvm/llvm-project/commit/13d44a8f5647819efd3ef57af384a3666f99d066
DIFF: https://github.com/llvm/llvm-project/commit/13d44a8f5647819efd3ef57af384a3666f99d066.diff

LOG: Revert "[Clang][Sema] Fix comparison of constraint expressions"

This temporarily reverts commit
60bee9ff544541e83ffbd4be31923d0e8b644690.
The diff will be recommitted once the newly discovered
regressions are fixed.

Added: 
    

Modified: 
    clang/lib/Sema/SemaConcept.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/lib/Sema/SemaTemplateInstantiate.cpp
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
    clang/test/SemaTemplate/concepts-out-of-line-def.cpp
    clang/test/SemaTemplate/concepts.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 4e7033c9d588..2882b10613fd 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -260,9 +260,6 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
     return SubstitutedAtomicExpr;
   }
 
-  if (SubstitutedAtomicExpr.get()->isValueDependent())
-    return SubstitutedAtomicExpr;
-
   EnterExpressionEvaluationContext ConstantEvaluated(
       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
@@ -755,43 +752,27 @@ namespace {
   };
 } // namespace
 
-static const Expr *SubstituteConstraintExpression(Sema &S, const NamedDecl *ND,
-                                                  const Expr *ConstrExpr) {
-  MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
-      ND, /*Final=*/false, /*Innermost=*/nullptr,
-      /*RelativeToPrimary=*/true,
-      /*Pattern=*/nullptr,
-      /*ForConstraintInstantiation=*/true, /*SkipForSpecialization*/ false);
-  if (MLTAL.getNumSubstitutedLevels() == 0)
-    return ConstrExpr;
-  Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
-  std::optional<Sema::CXXThisScopeRAII> ThisScope;
-  if (auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext()))
-    ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
-  ExprResult SubstConstr =
-      S.SubstConstraintExpr(const_cast<clang::Expr *>(ConstrExpr), MLTAL);
-  if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
-    return nullptr;
-  return SubstConstr.get();
-}
-
 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
                                          const Expr *OldConstr,
                                          const NamedDecl *New,
                                          const Expr *NewConstr) {
-  if (OldConstr == NewConstr)
-    return true;
   if (Old && New && Old != New) {
-    if (const Expr *SubstConstr =
-            SubstituteConstraintExpression(*this, Old, OldConstr))
-      OldConstr = SubstConstr;
-    else
-      return false;
-    if (const Expr *SubstConstr =
-            SubstituteConstraintExpression(*this, New, NewConstr))
-      NewConstr = SubstConstr;
-    else
-      return false;
+    unsigned Depth1 = CalculateTemplateDepthForConstraints(
+        *this, Old);
+    unsigned Depth2 = CalculateTemplateDepthForConstraints(
+        *this, New);
+
+    // Adjust the 'shallowest' verison of this to increase the depth to match
+    // the 'other'.
+    if (Depth2 > Depth1) {
+      OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
+                      .TransformExpr(const_cast<Expr *>(OldConstr))
+                      .get();
+    } else if (Depth1 > Depth2) {
+      NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
+                      .TransformExpr(const_cast<Expr *>(NewConstr))
+                      .get();
+    }
   }
 
   llvm::FoldingSetNodeID ID1, ID2;

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index aa40bff4c575..ab4300518ecf 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1294,7 +1294,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
     // We check the return type and template parameter lists for function
     // templates first; the remaining checks follow.
     bool SameTemplateParameterList = TemplateParameterListsAreEqual(
-        NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
+        NewTemplate->getTemplateParameters(),
         OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch);
     bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(),
                                               New->getDeclaredReturnType());

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index bdcee77ce67c..526f19b8aedc 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -208,10 +208,6 @@ Response HandleFunction(const FunctionDecl *Function,
   return Response::UseNextDecl(Function);
 }
 
-Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
-  return Response::ChangeDecl(FTD->getLexicalDeclContext());
-}
-
 Response HandleRecordDecl(const CXXRecordDecl *Rec,
                           MultiLevelTemplateArgumentList &Result,
                           ASTContext &Context,
@@ -322,8 +318,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
     } else if (const auto *CSD =
                    dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
       R = HandleImplicitConceptSpecializationDecl(CSD, Result);
-    } else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
-      R = HandleFunctionTemplateDecl(FTD);
     } else if (!isa<DeclContext>(CurDecl)) {
       R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
       if (CurDecl->getDeclContext()->isTranslationUnit()) {

diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f9418829186e..e749c24e7f70 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,12 +1653,33 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
         << QualifierLoc.getSourceRange();
       return nullptr;
     }
+
+    if (PrevClassTemplate) {
+      const ClassTemplateDecl *MostRecentPrevCT =
+          PrevClassTemplate->getMostRecentDecl();
+      TemplateParameterList *PrevParams =
+          MostRecentPrevCT->getTemplateParameters();
+
+      // Make sure the parameter lists match.
+      if (!SemaRef.TemplateParameterListsAreEqual(
+              D->getTemplatedDecl(), InstParams,
+              MostRecentPrevCT->getTemplatedDecl(), PrevParams, true,
+              Sema::TPL_TemplateMatch))
+        return nullptr;
+
+      // Do some additional validation, then merge default arguments
+      // from the existing declarations.
+      if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+                                             Sema::TPC_ClassTemplate))
+        return nullptr;
+    }
   }
 
   CXXRecordDecl *RecordInst = CXXRecordDecl::Create(
       SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(),
       Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl,
       /*DelayTypeCreation=*/true);
+
   if (QualifierLoc)
     RecordInst->setQualifierInfo(QualifierLoc);
 
@@ -1668,37 +1689,16 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   ClassTemplateDecl *Inst
     = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
                                 D->getIdentifier(), InstParams, RecordInst);
+  assert(!(isFriend && Owner->isDependentContext()));
+  Inst->setPreviousDecl(PrevClassTemplate);
+
   RecordInst->setDescribedClassTemplate(Inst);
 
   if (isFriend) {
-    assert(!Owner->isDependentContext());
-    Inst->setLexicalDeclContext(Owner);
-    RecordInst->setLexicalDeclContext(Owner);
-
-    if (PrevClassTemplate) {
-      RecordInst->setTypeForDecl(
-          PrevClassTemplate->getTemplatedDecl()->getTypeForDecl());
-      const ClassTemplateDecl *MostRecentPrevCT =
-          PrevClassTemplate->getMostRecentDecl();
-      TemplateParameterList *PrevParams =
-          MostRecentPrevCT->getTemplateParameters();
-
-      // Make sure the parameter lists match.
-      if (!SemaRef.TemplateParameterListsAreEqual(
-              RecordInst, InstParams, MostRecentPrevCT->getTemplatedDecl(),
-              PrevParams, true, Sema::TPL_TemplateMatch))
-        return nullptr;
-
-      // Do some additional validation, then merge default arguments
-      // from the existing declarations.
-      if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
-                                             Sema::TPC_ClassTemplate))
-        return nullptr;
-
+    if (PrevClassTemplate)
       Inst->setAccess(PrevClassTemplate->getAccess());
-    } else {
+    else
       Inst->setAccess(D->getAccess());
-    }
 
     Inst->setObjectOfFriendDecl();
     // TODO: do we want to track the instantiation progeny of this
@@ -1709,15 +1709,15 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
       Inst->setInstantiatedFromMemberTemplate(D);
   }
 
-  Inst->setPreviousDecl(PrevClassTemplate);
-
   // Trigger creation of the type for the instantiation.
-  SemaRef.Context.getInjectedClassNameType(
-      RecordInst, Inst->getInjectedClassNameSpecialization());
+  SemaRef.Context.getInjectedClassNameType(RecordInst,
+                                    Inst->getInjectedClassNameSpecialization());
 
   // Finish handling of friends.
   if (isFriend) {
     DC->makeDeclVisibleInContext(Inst);
+    Inst->setLexicalDeclContext(Owner);
+    RecordInst->setLexicalDeclContext(Owner);
     return Inst;
   }
 

diff  --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index a0fb1c397303..222b78e0d22f 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,153 +127,3 @@ static_assert(S<XY>::specialization("str") == SPECIALIZATION_CONCEPT);
 static_assert(S<int>::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
-
-static constexpr int CONSTRAINED_METHOD_1 = 1;
-static constexpr int CONSTRAINED_METHOD_2 = 2;
-
-namespace constrained_members {
-
-template <int>
-struct S {
-  template <Concept C>
-  static constexpr int constrained_method();
-};
-
-template <>
-template <Concept C>
-constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template <>
-template <Concept C>
-constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-
-template <class T1, class T2>
-concept ConceptT1T2 = true;
-
-template<typename T3>
-struct S12 {
-  template<ConceptT1T2<T3> T4>
-  static constexpr int constrained_method();
-};
-
-template<>
-template<ConceptT1T2<int> T5>
-constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template<>
-template<ConceptT1T2<double> T5>
-constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained members
-
-namespace constrained_members_of_nested_types {
-
-template <int>
-struct S {
-  struct Inner0 {
-    struct Inner1 {
-      template <Concept C>
-      static constexpr int constrained_method();
-    };
-  };
-};
-
-template <>
-template <Concept C>
-constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template <>
-template <Concept C>
-constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S<1>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S<2>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-
-template <class T1, class T2>
-concept ConceptT1T2 = true;
-
-template<typename T3>
-struct S12 {
-  struct Inner0 {
-    struct Inner1 {
-      template<ConceptT1T2<T3> T4>
-      static constexpr int constrained_method();
-    };
-  };
-};
-
-template<>
-template<ConceptT1T2<int> T5>
-constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template<>
-template<ConceptT1T2<double> T5>
-constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S12<int>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S12<double>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained_members_of_nested_types
-
-namespace constrained_member_sfinae {
-
-template<int N> struct S {
-  template<class T>
-  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
-    return CONSTRAINED_METHOD_1;
-  }
-
-  template<class T>
-  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
-};
-
-template<>
-template<typename T>
-constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
-  return CONSTRAINED_METHOD_2;
-}
-
-// Verify that there is no amiguity in this case.
-static_assert(S<4>::constrained_method<double>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained_member_sfinae
-
-namespace requires_expression_references_members {
-
-void accept1(int x);
-void accept2(XY xy);
-
-template <class T> struct S {
-  T Field = T();
-
-  constexpr int constrained_method()
-      requires requires { accept1(Field); };
-
-  constexpr int constrained_method()
-      requires requires { accept2(Field); };
-};
-
-template <class T>
-constexpr int S<T>::constrained_method()
-  requires requires { accept1(Field); } {
-  return CONSTRAINED_METHOD_1;
-}
-
-template <class T>
-constexpr int S<T>::constrained_method()
-  requires requires { accept2(Field); } {
-  return CONSTRAINED_METHOD_2;
-}
-
-static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1);
-static_assert(S<XY>().constrained_method() == CONSTRAINED_METHOD_2);
-
-} // namespace requires_expression_references_members

diff  --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 19638bba3072..d28c2b22bd04 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -816,12 +816,3 @@ static_assert(Parent<int>::TakesBinary<int, 0>::i == 0);
 static_assert(Parent<int>::TakesBinary<int, 0ULL>::i == 0);
 }
 
-namespace TemplateInsideNonTemplateClass {
-template<typename T, typename U> concept C = true;
-
-template<typename T> auto L = []<C<T> U>() {};
-
-struct Q {
-  template<C<int> U> friend constexpr auto decltype(L<int>)::operator()() const;
-};
-} // namespace TemplateInsideNonTemplateClass


        


More information about the cfe-commits mailing list