ChuanqiXu updated this revision to Diff 443141.
ChuanqiXu retitled this revision from "[AST] Profiling on constraint expression 
instead of arguments for TypeConstraint in ASTContext::isSameTemplateParameter" 
to "[AST] Accept identical TypeConstraint referring to other template 
parameters.".
ChuanqiXu added a comment.

Add more tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129068/new/

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
@@ -3,6 +3,7 @@
 // RUN: split-file %s %t
 //
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify
 
 //--- foo.h
@@ -18,6 +19,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 +33,29 @@
   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;
+  }
+
+  template <template<class> class H, class S, C<H<S>> Sentinel>
+  constexpr H<S> operator()(H<S> &&__s, Sentinel &&last) const {
+    return __s;
+  }
+
+// Tests that we could find different concept definition indeed.
+#ifndef DIFFERENT
+  template <__integer_like _Tp, __integer_like _Up, C<_Tp> Sentinel>
+  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
+    return __t;
+  }
+#else
+  template <__integer_like _Tp, __integer_like _Up, C<_Up> Sentinel>
+  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
+    return __t;
+  }
+#endif
 };
 #endif
 
@@ -38,12 +65,23 @@
 export module A;
 
 //--- B.cppm
-// expected-no-diagnostics
 module;
 #include "foo.h"
 export module B;
 import A;
 
+#ifdef DIFFERENT
+// expected-error@foo.h:41 {{'__fn::operator()' from module 'A.<global>' is not present in definition of '__fn' provided earlier}}
+// expected-note@* 1+{{declaration of 'operator()' does not match}}
+#else
+// expected-no-diagnostics
+#endif
+
+template <class T>
+struct U {
+  auto operator+(U) { return 0; }
+};
+
 void foo() {
     A a;
     struct S {
@@ -51,4 +89,8 @@
         auto operator+(S s) { return 0; }
     };
     __fn{}(S());
+    __fn{}(S(), S());
+    __fn{}(S(), S(), S());
+
+    __fn{}(U<int>(), U<int>());
 }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6245,14 +6245,31 @@
         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());
-        if (XID != YID)
-          return false;
+        // We couldn't compare the profiling result for the template
+        // args here. Consider the following example in different modules:
+        //
+        // template <__integer_like _Tp, C<_Tp> Sentinel>
+        // constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
+        //   return __t;
+        // }
+        //
+        // When we compare the profiling result for `C<_Tp>` in different
+        // modules, it will compare the type of `_Tp` in different modules.
+        // However, the type of `_Tp` in different modules refer to different
+        // types here naturally. So we couldn't compare the profiling result
+        // for the template args directly.
+      }
+      llvm::FoldingSetNodeID XID, YID;
+      auto *XConstraint = TXTC->getImmediatelyDeclaredConstraint();
+      auto *YConstraint = TYTC->getImmediatelyDeclaredConstraint();
+      if (!XConstraint != !YConstraint)
+        return false;
+      if (XConstraint) {
+        XConstraint->Profile(XID, *this, /*Canonical=*/true);
+        YConstraint->Profile(YID, *this, /*Canonical=*/true);
       }
+      if (XID != YID)
+        return false;
     }
     return true;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to