diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3507,6 +3507,7 @@ // Expressions appearing within a requirement-body are unevaluated operands. EnterExpressionEvaluationContext Ctx( Actions, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::ContextRAII SaveContext(Actions, Actions.CurContext); ParseScope BodyScope(this, Scope::DeclScope); RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr( diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp @@ -155,3 +155,42 @@ static_assert(!A<1>::faz()); static_assert(A<0>::faz()); } + +namespace non_dependent_access_check_hard_errors { +// Dependent access does not cause hard errors. +template class A; + +template <> class A<0> { + static void f() {} +}; +template +concept C1 = requires() { A::f(); }; +static_assert(!C1<0>); + +template <> class A<1> { +public: + static void f() {} +}; +static_assert(C1<1>); + +// Non-dependent access to private member is a hard error. +class B{ + static void f() {} // expected-note 2{{implicitly declared private here}} +}; +template +concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}} + +constexpr bool non_template_func() { + return requires() { + B::f(); // expected-error {{'f' is a private member}} + }; +} +template +constexpr bool template_func() { + return requires() { + A::f(); + }; +} +static_assert(!template_func<0>()); +static_assert(template_func<1>()); +}