alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: erichkeane, rsmith, aaron.ballman.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The associated github issue: https://github.com/llvm/llvm-project/issues/61414
It also fixes 
https://github.com/llvm/llvm-project/issues/49620#issuecomment-1387667143 and 
https://github.com/llvm/llvm-project/issues/60231

Test plan:
1/ ninja check-all
2/ Bootstrapped Clang passes all the tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146178

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

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===================================================================
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,27 @@
 static_assert(S<int>::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+namespace constrained_members {
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+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);
+
+} // namespace constrained members
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1296,9 +1296,11 @@
     //
     // We check the return type and template parameter lists for function
     // templates first; the remaining checks follow.
+
     bool SameTemplateParameterList = TemplateParameterListsAreEqual(
-        NewTemplate->getTemplateParameters(),
-        OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch);
+        NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
+        OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch,
+        SourceLocation(), false /* PartialOrdering */);
     bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(),
                                               New->getDeclaredReturnType());
     // FIXME(GH58571): Match template parameter list even for non-constrained
Index: clang/lib/Sema/SemaConcept.cpp
===================================================================
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -733,12 +733,19 @@
 }
 
 namespace {
-  class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
+class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
+public:
+  enum DepthAdjustmentKind { Diff, Value };
+
+private:
   unsigned TemplateDepth = 0;
-  public:
+  DepthAdjustmentKind Kind;
+
+public:
   using inherited = TreeTransform<AdjustConstraintDepth>;
-  AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
-      : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
+  AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth,
+                        DepthAdjustmentKind Kind)
+      : inherited(SemaRef), TemplateDepth(TemplateDepth), Kind(Kind) {}
 
   using inherited::TransformTemplateTypeParmType;
   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
@@ -751,13 +758,13 @@
           TransformDecl(TL.getNameLoc(), OldTTPDecl));
 
     QualType Result = getSema().Context.getTemplateTypeParmType(
-        T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
-        NewTTPDecl);
+        Kind == Diff ? T->getDepth() + TemplateDepth : TemplateDepth,
+        T->getIndex(), T->isParameterPack(), NewTTPDecl);
     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
     NewTL.setNameLoc(TL.getNameLoc());
     return Result;
   }
-  };
+};
 } // namespace
 
 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
@@ -765,22 +772,19 @@
                                          const NamedDecl *New,
                                          const Expr *NewConstr) {
   if (Old && New && Old != New) {
-    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();
-    }
+    unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, Old);
+    unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, New);
+    unsigned MaxDepth = std::max(Depth1, Depth2);
+    // The depths calculated for the declarations can be equal but they still
+    // may differ from the depths of types inside OldConstr and NewConstr.
+    OldConstr =
+        AdjustConstraintDepth(*this, MaxDepth, AdjustConstraintDepth::Value)
+            .TransformExpr(const_cast<Expr *>(OldConstr))
+            .get();
+    NewConstr =
+        AdjustConstraintDepth(*this, MaxDepth, AdjustConstraintDepth::Value)
+            .TransformExpr(const_cast<Expr *>(NewConstr))
+            .get();
   }
 
   llvm::FoldingSetNodeID ID1, ID2;
@@ -1454,11 +1458,11 @@
 
   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
     if (Depth2 > Depth1) {
-      AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
+      AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1, AdjustConstraintDepth::Diff)
                    .TransformExpr(const_cast<Expr *>(AC1[I]))
                    .get();
     } else if (Depth1 > Depth2) {
-      AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
+      AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2, AdjustConstraintDepth::Diff)
                    .TransformExpr(const_cast<Expr *>(AC2[I]))
                    .get();
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to