https://github.com/zyn0217 updated 
https://github.com/llvm/llvm-project/pull/199617

>From dd85ecb9ba4217f2d49746c97da3478d14d9d513 Mon Sep 17 00:00:00 2001
From: Younan Zhang <[email protected]>
Date: Tue, 26 May 2026 15:12:52 +0800
Subject: [PATCH] [Clang] Profile the NNS of UnresolvedUsingType correctly in
 concept hashing

They were sometimes incorrect because the written type doesn't contain an
NNS which contains template parameters we're interested in.
---
 clang/lib/Sema/SemaConcept.cpp                | 14 +++
 .../test/SemaTemplate/concepts-using-decl.cpp | 98 +++++++++++++++++++
 2 files changed, 112 insertions(+)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index ea03c3f408986..f41f37b8a3d19 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -381,6 +381,10 @@ class HashParameterMapping : public 
RecursiveASTVisitor<HashParameterMapping> {
     return true;
   }
 
+  bool TraverseCXXThisExpr(CXXThisExpr *E) {
+    return inherited::TraverseType(E->getType());
+  }
+
   bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
     // We don't care about TypeLocs. So traverse Types instead.
     return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
@@ -399,6 +403,16 @@ class HashParameterMapping : public 
RecursiveASTVisitor<HashParameterMapping> {
     return true;
   }
 
+  bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
+                                   bool TraverseQualifier) {
+    // Sometimes the written type doesn't contain a qualifier which contains
+    // necessary template arguments, whereas the declaration does.
+    if (NestedNameSpecifier NNS = T->getDecl()->getQualifier();
+        TraverseQualifier && NNS)
+      return inherited::TraverseNestedNameSpecifier(NNS);
+    return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
+  }
+
   bool TraverseInjectedClassNameType(InjectedClassNameType *T,
                                      bool TraverseQualifier) {
     return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
diff --git a/clang/test/SemaTemplate/concepts-using-decl.cpp 
b/clang/test/SemaTemplate/concepts-using-decl.cpp
index 26bd0b60b691c..00df6b899782c 100644
--- a/clang/test/SemaTemplate/concepts-using-decl.cpp
+++ b/clang/test/SemaTemplate/concepts-using-decl.cpp
@@ -197,3 +197,101 @@ struct child : base<int> {
 };
 
 }
+
+namespace GH198663 {
+
+template <class T>
+concept HasIsTransparent = requires { typename T::is_transparent; };
+
+template <class K, class V, class Compare>
+struct FlatMapBase {
+    using key_compare = Compare;
+};
+
+template <class K, class V, class Compare>
+struct FlatMap : FlatMapBase<K, V, Compare> {
+    using Base = FlatMapBase<K, V, Compare>;
+
+    using typename Base::key_compare;
+
+    void at(const K&) {}
+    void at(const K&) const {}
+    template <class Other>
+    void at(const Other&)
+        requires HasIsTransparent<key_compare>
+    {}
+    template <class Other>
+    void at(const Other&) const
+        requires HasIsTransparent<key_compare>
+    {}
+};
+
+template <class T>
+struct Transparent {
+    T t;
+};
+
+struct TransparentComparator {
+    using is_transparent = void;
+
+    template <class T>
+    bool operator()(const T&, const Transparent<T>&) const;
+
+    template <class T>
+    bool operator()(const Transparent<T>&, const T& t) const;
+
+    template <class T>
+    bool operator()(const T&, const T&) const;
+};
+
+struct NonTransparentComparator {
+    template <class T>
+    bool operator()(const T&, const Transparent<T>&) const;
+
+    template <class T>
+    bool operator()(const Transparent<T>&, const T&) const;
+
+    template <class T>
+    bool operator()(const T&, const T&) const;
+};
+
+template <class M>
+concept CanAt = requires(M m, Transparent<int> k) { m.at(k); };
+
+using TransparentMap = FlatMap<int, double, TransparentComparator>;
+using NonTransparentMap = FlatMap<int, double, NonTransparentComparator>;
+
+static_assert(CanAt<TransparentMap>);
+
+static_assert(!CanAt<NonTransparentMap>);
+
+}
+
+namespace GH198663_2 {
+
+template<typename T>
+auto mv(T& t) -> T&&;
+
+template<typename S, typename T>
+concept does_foo = requires(S s) {
+       s.template foo<T>();
+};
+
+template<typename S>
+struct type {
+       S member;
+       template<typename T>
+       auto foo() -> T requires does_foo<decltype(mv(member)), T>;
+};
+
+struct returns_int {
+       template<typename T>
+       auto foo() -> T;
+};
+
+struct nothing {};
+
+static_assert(does_foo<type<returns_int>&, int>);
+static_assert(not does_foo<type<nothing>&, int>);
+
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to