ChuanqiXu created this revision.
ChuanqiXu added reviewers: rsmith, vsapsai, ilya-biryukov.
ChuanqiXu added a project: clang-modules.
Herald added a project: All.
ChuanqiXu requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The current implementation to judge the similarity of TypeConstraint in 
ASTContext::isSameTemplateParameter is problematic, it couldn't handle the 
following case:

  C++
  template <__integer_like _Tp, C<_Tp> Sentinel>
  constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
      return __t;
  }

When we see 2 such declarations from different modules, we would judge their 
similarity by `ASTContext::isSame*` methods. But problems come for the 
TypeConstraint. Originally, we would profile each argument one by one. But it 
is not right. Since the profiling result of `_Tp` would refer to two different 
template type declarations. So it would get different results. It is right 
since the `_Tp` in different modules refers to different declarations indeed. 
So the same declaration in different modules would meet incorrect our-checking 
results.

It is not the thing we want. We want to know if the TypeConstraint have the 
same expression.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129068

Files:
  clang/lib/AST/ASTContext.cpp
  clang/test/Modules/concept.cppm


Index: clang/test/Modules/concept.cppm
===================================================================
--- clang/test/Modules/concept.cppm
+++ clang/test/Modules/concept.cppm
@@ -18,6 +18,9 @@
 template <class _Tp>
 concept __member_size = requires(_Tp &&t) { t.size(); };
 
+template <class First, class Second>
+concept C = requires(First x, Second y) { x+y; };
+
 struct A {
 public:
   template <Range T>
@@ -29,6 +32,11 @@
   constexpr __integer_like auto operator()(_Tp&& __t) const {
     return __t.size();
   }
+
+  template <__integer_like _Tp, C<_Tp> Sentinel>
+  constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
+    return __t;
+  }
 };
 #endif
 
@@ -51,4 +59,5 @@
         auto operator+(S s) { return 0; }
     };
     __fn{}(S());
+    __fn{}(S(), S());
 }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6245,11 +6245,14 @@
         auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
         if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
           return false;
+
         llvm::FoldingSetNodeID XID, YID;
-        for (auto &ArgLoc : TXTCArgs->arguments())
-          ArgLoc.getArgument().Profile(XID, X->getASTContext());
-        for (auto &ArgLoc : TYTCArgs->arguments())
-          ArgLoc.getArgument().Profile(YID, Y->getASTContext());
+        auto *XConstraint = TXTC->getImmediatelyDeclaredConstraint();
+        auto *YConstraint = TYTC->getImmediatelyDeclaredConstraint();
+        if (XConstraint)
+          XConstraint->Profile(XID, *this, /*Canonical=*/true);
+        if (YConstraint)
+          YConstraint->Profile(YID, *this, /*Canonical=*/true);
         if (XID != YID)
           return false;
       }
@@ -6524,10 +6527,10 @@
   // and patterns match.
   if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
     const auto *TemplateY = cast<TemplateDecl>(Y);
-    return isSameEntity(TemplateX->getTemplatedDecl(),
-                        TemplateY->getTemplatedDecl()) &&
-           isSameTemplateParameterList(TemplateX->getTemplateParameters(),
-                                       TemplateY->getTemplateParameters());
+    return  isSameEntity(TemplateX->getTemplatedDecl(),
+                         TemplateY->getTemplatedDecl()) &&
+            isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+                                        TemplateY->getTemplateParameters());
   }
 
   // Fields with the same name and the same type match.


Index: clang/test/Modules/concept.cppm
===================================================================
--- clang/test/Modules/concept.cppm
+++ clang/test/Modules/concept.cppm
@@ -18,6 +18,9 @@
 template <class _Tp>
 concept __member_size = requires(_Tp &&t) { t.size(); };
 
+template <class First, class Second>
+concept C = requires(First x, Second y) { x+y; };
+
 struct A {
 public:
   template <Range T>
@@ -29,6 +32,11 @@
   constexpr __integer_like auto operator()(_Tp&& __t) const {
     return __t.size();
   }
+
+  template <__integer_like _Tp, C<_Tp> Sentinel>
+  constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
+    return __t;
+  }
 };
 #endif
 
@@ -51,4 +59,5 @@
         auto operator+(S s) { return 0; }
     };
     __fn{}(S());
+    __fn{}(S(), S());
 }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6245,11 +6245,14 @@
         auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
         if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
           return false;
+
         llvm::FoldingSetNodeID XID, YID;
-        for (auto &ArgLoc : TXTCArgs->arguments())
-          ArgLoc.getArgument().Profile(XID, X->getASTContext());
-        for (auto &ArgLoc : TYTCArgs->arguments())
-          ArgLoc.getArgument().Profile(YID, Y->getASTContext());
+        auto *XConstraint = TXTC->getImmediatelyDeclaredConstraint();
+        auto *YConstraint = TYTC->getImmediatelyDeclaredConstraint();
+        if (XConstraint)
+          XConstraint->Profile(XID, *this, /*Canonical=*/true);
+        if (YConstraint)
+          YConstraint->Profile(YID, *this, /*Canonical=*/true);
         if (XID != YID)
           return false;
       }
@@ -6524,10 +6527,10 @@
   // and patterns match.
   if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
     const auto *TemplateY = cast<TemplateDecl>(Y);
-    return isSameEntity(TemplateX->getTemplatedDecl(),
-                        TemplateY->getTemplatedDecl()) &&
-           isSameTemplateParameterList(TemplateX->getTemplateParameters(),
-                                       TemplateY->getTemplateParameters());
+    return  isSameEntity(TemplateX->getTemplatedDecl(),
+                         TemplateY->getTemplatedDecl()) &&
+            isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+                                        TemplateY->getTemplateParameters());
   }
 
   // Fields with the same name and the same type match.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to