https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/141207
>From c63f3f82d6e4c576051532b2272abf4ac0055d7f Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Fri, 23 May 2025 15:29:49 +0800 Subject: [PATCH 1/2] [Clang] Fix the access checking for non-aggregates in default arguments We check the accessibility of constructors when initializing a default argument whose type is not an aggregate. Make sure the check is performed within the correct DeclContext. Otherwise, it will be delayed until the end of the declaration, at which point the context is mismatched. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaTemplateInstantiate.cpp | 14 ++++++------ clang/test/SemaTemplate/default-arguments.cpp | 22 +++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 573ae97bff710..45c96af809505 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -767,6 +767,7 @@ Bug Fixes to C++ Support - Clang could incorrectly instantiate functions in discarded contexts (#GH140449) - Fix instantiation of default-initialized variable template specialization. (#GH140632) (#GH140622) - Clang modules now allow a module and its user to differ on TrivialAutoVarInit* +- Fixed a C++20 access checking bug when initializing non-aggregates in default arguments (#GH83608) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index d028eea4f8f3e..cd20dfb4fe093 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3340,13 +3340,13 @@ bool Sema::SubstDefaultArgument( } ExprResult Result; + // C++ [dcl.fct.default]p5: + // The names in the [default argument] expression are bound, and + // the semantic constraints are checked, at the point where the + // default argument expression appears. + ContextRAII SavedContext(*this, FD); { - // C++ [dcl.fct.default]p5: - // The names in the [default argument] expression are bound, and - // the semantic constraints are checked, at the point where the - // default argument expression appears. - ContextRAII SavedContext(*this, FD); - std::unique_ptr<LocalInstantiationScope> LIS; + std::optional<LocalInstantiationScope> LIS; if (ForCallExpr) { // When instantiating a default argument due to use in a call expression, @@ -3354,7 +3354,7 @@ bool Sema::SubstDefaultArgument( // required to satisfy references from the default argument. For example: // template<typename T> void f(T a, int = decltype(a)()); // void g() { f(0); } - LIS = std::make_unique<LocalInstantiationScope>(*this); + LIS.emplace(*this); FunctionDecl *PatternFD = FD->getTemplateInstantiationPattern( /*ForDefinition*/ false); if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs)) diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp index 5ea34c0254ec1..e9d781bfe5712 100644 --- a/clang/test/SemaTemplate/default-arguments.cpp +++ b/clang/test/SemaTemplate/default-arguments.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s template<typename T, int N = 2> struct X; // expected-note{{template is declared here}} X<int, 1> *x1; @@ -282,4 +283,25 @@ static_assert(S<short *>().SizeOfT<char>() == sizeof(short *), ""); } // namespace GH68490 +namespace GH83608 { + +class single; + +class check_constructible { + // This makes it a non-aggregate in C++20+. + check_constructible() = default; + + friend class single; +}; + +struct single { + template <class T> single(T u, check_constructible = {}) {} +}; + +// We perform access checking when substituting into the default argument. +// Make sure it runs within class single. +single x(0); + +} + #endif >From 7b15ebae62f0c2e492164dcbabcdb04f60b628ac Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Fri, 23 May 2025 19:45:18 +0800 Subject: [PATCH 2/2] feedback --- clang/docs/ReleaseNotes.rst | 2 +- clang/test/SemaCXX/access-control-check.cpp | 46 +++++++++++++++++++ clang/test/SemaTemplate/default-arguments.cpp | 22 --------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 45c96af809505..400d447518c73 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -767,7 +767,7 @@ Bug Fixes to C++ Support - Clang could incorrectly instantiate functions in discarded contexts (#GH140449) - Fix instantiation of default-initialized variable template specialization. (#GH140632) (#GH140622) - Clang modules now allow a module and its user to differ on TrivialAutoVarInit* -- Fixed a C++20 access checking bug when initializing non-aggregates in default arguments (#GH83608) +- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/test/SemaCXX/access-control-check.cpp b/clang/test/SemaCXX/access-control-check.cpp index 4540e99d8a337..76d27ce3e55cb 100644 --- a/clang/test/SemaCXX/access-control-check.cpp +++ b/clang/test/SemaCXX/access-control-check.cpp @@ -13,3 +13,49 @@ class N : M,P { N() {} int PR() { return iP + PPR(); } // expected-error 2 {{private member of 'P'}} }; + +namespace GH83608 { + +class single; + +class check_constructible { + // This makes the class a non-aggregate, which enforces us to check + // the constructor when initializing. + check_constructible() {} + + friend class single; +}; + +struct single { + template <class T> single(T u, check_constructible = {}) {} +}; + +// We perform access checking when substituting into the default argument. +// Make sure it runs within the context of 'single'. +single x(0); + +} + +namespace GH62444 { + +struct B { + friend struct A; +private: + B(int); // #B +}; + +template<class T> +int f(T = 0); // #Decl + +struct A { + A() { + int i = f<B>(); + // expected-error@#Decl {{calling a private constructor}} + // expected-note@-2 {{in instantiation of default function argument}} + // expected-note@#B {{declared private}} + } +}; + +int i = f<B>(); + +} diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp index e9d781bfe5712..5ea34c0254ec1 100644 --- a/clang/test/SemaTemplate/default-arguments.cpp +++ b/clang/test/SemaTemplate/default-arguments.cpp @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s template<typename T, int N = 2> struct X; // expected-note{{template is declared here}} X<int, 1> *x1; @@ -283,25 +282,4 @@ static_assert(S<short *>().SizeOfT<char>() == sizeof(short *), ""); } // namespace GH68490 -namespace GH83608 { - -class single; - -class check_constructible { - // This makes it a non-aggregate in C++20+. - check_constructible() = default; - - friend class single; -}; - -struct single { - template <class T> single(T u, check_constructible = {}) {} -}; - -// We perform access checking when substituting into the default argument. -// Make sure it runs within class single. -single x(0); - -} - #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits