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

They were sometimes incorrect because the written type doesn't contain an NNS 
which contains template parameters we're interested in.

No release note because the bug broke MS STL and I want to backport it to the 
last 22.x release

Fixes https://github.com/llvm/llvm-project/issues/198663

>From 6e611c57f705e5a89f1e7f8e699d2a457675e48c 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                | 10 +++
 .../test/SemaTemplate/concepts-using-decl.cpp | 69 +++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index ea03c3f408986..66d1f4db29410 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -399,6 +399,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 true;
+  }
+
   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..dfdab707e4814 100644
--- a/clang/test/SemaTemplate/concepts-using-decl.cpp
+++ b/clang/test/SemaTemplate/concepts-using-decl.cpp
@@ -197,3 +197,72 @@ 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>);
+
+}

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

Reply via email to