From 0ebdcec675c39b26b8bee1a8b07c12fae2c58523 Mon Sep 17 00:00:00 2001 From: huqizhi 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 | 4 ++++ .../temp.fct/temp.func.order/p6.cpp | 6 +++--- clang/test/SemaCXX/PR77377.cpp | 19 +++++++++++++++++++ 4 files changed, 27 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..a23a2efa2389e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2257,6 +2257,10 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr( const SubstNonTypeTemplateParmExpr *E) { // Profile exactly as the replacement expression. Visit(E->getReplacement()); + if (auto *NTTP = dyn_cast(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 struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} } // 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 +constexpr bool is_same_v = false; + +template +constexpr bool is_same_v = true; + +template +concept same_as = is_same_v; + +template +struct A {}; + +template auto p> +struct A

{}; + +A<0> a;