usaxena95 created this revision.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Access to members in a non-dependent context would always yield an
invalid expression. When it appears in a requires-expression, then this
is a hard error as this would always result in a substitution failure.

https://eel.is/c++draft/expr.prim.req#general-note-1
Note 1: If a requires-expression contains invalid types or expressions in its 
requirements, and it does not appear within the declaration of a templated 
entity, then the program is ill-formed. — end note]
If the substitution of template arguments into a requirement would always 
result in a substitution failure, the program is ill-formed; no diagnostic 
required.

Fixes: https://github.com/llvm/llvm-project/issues/53334


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140876

Files:
  clang/lib/Parse/ParseExprCXX.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp


Index: clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
@@ -155,3 +155,28 @@
 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<int N> class A;
+
+template <> class A<0> {
+  static void f() {}
+};
+template<int N>
+concept C1 = requires() { A<N>::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 {{implicitly declared private here}}
+};
+template<class T>
+concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private 
member}}
+}
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ 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(


Index: clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
@@ -155,3 +155,28 @@
 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<int N> class A;
+
+template <> class A<0> {
+  static void f() {}
+};
+template<int N>
+concept C1 = requires() { A<N>::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 {{implicitly declared private here}}
+};
+template<class T>
+concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}}
+}
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ 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(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to