diff options
author | Younan Zhang <zyn7109@gmail.com> | 2025-05-23 20:11:22 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-23 20:11:22 +0800 |
commit | d4f0f43506d04807e82e5c722c6362bcf112a2a0 (patch) | |
tree | c8f76f220c5bd0dcdac8a7a230b694da63d65dd0 | |
parent | 989aadf4b112ef55648d801c4003b63f8aad930e (diff) | |
download | llvm-d4f0f43506d04807e82e5c722c6362bcf112a2a0.zip llvm-d4f0f43506d04807e82e5c722c6362bcf112a2a0.tar.gz llvm-d4f0f43506d04807e82e5c722c6362bcf112a2a0.tar.bz2 |
[Clang] Fix the access checking for non-aggregates in default arguments (#141207)
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.
Fixes #62444
Fixes https://github.com/llvm/llvm-project/issues/83608
-rw-r--r-- | clang/docs/ReleaseNotes.rst | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 14 | ||||
-rw-r--r-- | clang/test/SemaCXX/access-control-check.cpp | 46 |
3 files changed, 54 insertions, 7 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8a4ff6e..b93fa33 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -794,6 +794,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 an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index d028eea..cd20dfb 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/SemaCXX/access-control-check.cpp b/clang/test/SemaCXX/access-control-check.cpp index 4540e99..76d27ce 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>(); + +} |