[clang] [clang] visit constraint of NTTP (PR #91842)

Qizhi Hu via cfe-commits cfe-commits at lists.llvm.org
Fri May 10 23:25:54 PDT 2024


https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/91842

attempt to fix 
`isSameTemplateArg` returns incorrect result since clang didn't visit constraint of NTTP. Furthermore,  It makes class template partial specialization not more specialized than the class template itself.

>From ddc0fbb7a249fbc6f2d2795fda262b2e7ca0a4e9 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Sat, 11 May 2024 14:04:23 +0800
Subject: [PATCH] [clang] visit constraint of NTTP

---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/lib/AST/StmtProfile.cpp                 |  5 +++++
 .../temp.fct/temp.func.order/p6.cpp           |  6 +++---
 clang/test/SemaCXX/PR77377.cpp                | 19 +++++++++++++++++++
 4 files changed, 28 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/SemaCXX/PR77377.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7c5dcc59c7016..30d359c582d3f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -707,6 +707,7 @@ Bug Fixes to C++ Support
   initialized, rather than evaluating them as a part of the larger manifestly constant evaluated
   expression.
 - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361).
+- Fix a bug on template class partial specialization due to traverse of constraint of NTTP. Fixes (#GH77377).
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 8fb8940142eb0..0bb5a40d7350e 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2257,6 +2257,11 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
     const SubstNonTypeTemplateParmExpr *E) {
   // Profile exactly as the replacement expression.
   Visit(E->getReplacement());
+  if (auto *NTTP =
+          dyn_cast_if_present<NonTypeTemplateParmDecl>(E->getParameter());
+      NTTP && NTTP->getPlaceholderTypeConstraint()) {
+    Visit(NTTP->getPlaceholderTypeConstraint());
+  }
 }
 
 void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) {
diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp
index 9f44878da6254..5f9719a2dc561 100644
--- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp
@@ -79,14 +79,14 @@ template<C     T, int I> struct Y2<T*, I, I+1+1> {}; // expected-note {{partial
 template<C T, C auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
 struct Y3 { Y3()=delete; };
 template<C T, D auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
-struct Y3<T, I, W, S, U, Z...> { Y3()=delete; };
+struct Y3<T, I, W, S, U, Z...> { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = <int>]}}
 template<C T, E auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
-struct Y3<T, I, W, S, U, Z...> {};
+struct Y3<T, I, W, S, U, Z...> {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = <int>]}}
 
 void f() {
   Y1<int, 2> a;
   Y2<char*, 1, 3> b; // expected-error {{ambiguous partial specializations}}
-  Y3<int, 1, 1, A{}, S, int> c;
+  Y3<int, 1, 1, A{}, S, int> c; // expected-error {{ambiguous partial specializations of 'Y3<int, 1, 1, A{}, S, int>'}}
 }
 
 // Per [temp.func.order]p6.2.2, specifically "if the function parameters that
diff --git a/clang/test/SemaCXX/PR77377.cpp b/clang/test/SemaCXX/PR77377.cpp
new file mode 100644
index 0000000000000..ae34809c3903d
--- /dev/null
+++ b/clang/test/SemaCXX/PR77377.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
+// expected-no-diagnostics
+
+template<typename T, typename U>
+constexpr bool is_same_v = false;
+
+template<typename T>
+constexpr bool is_same_v<T, T> = true;
+
+template<typename T, typename U>
+concept same_as = is_same_v<T, U>;
+
+template <auto>
+struct A {};
+
+template <same_as<int> auto p>
+struct A<p> {};
+
+A<0> a;



More information about the cfe-commits mailing list