usaxena95 updated this revision to Diff 486255.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.
Adding access check related changes from https://reviews.llvm.org/D140876
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D140547/new/
https://reviews.llvm.org/D140547
Files:
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/SemaTemplateInstantiate.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
@@ -104,3 +104,129 @@
constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); };
// expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}}
// expected-note@-2{{'x' declared here}}
+
+namespace access_checks {
+template<auto>
+struct A {
+ static constexpr bool foo();
+ static constexpr bool bar();
+ static constexpr bool baz();
+ static constexpr bool faz();
+};
+
+class C{};
+
+class B {
+ void p() {}
+ bool data_member = true;
+ static const bool static_member = true;
+ friend struct A<0>;
+};
+
+template<auto x>
+constexpr bool A<x>::foo() {
+ return requires(B b) { b.p(); };
+}
+static_assert(!A<1>::foo());
+static_assert(A<0>::foo());
+
+template<auto x>
+constexpr bool A<x>::bar() {
+ return requires() { B::static_member; };
+}
+static_assert(!A<1>::bar());
+static_assert(A<0>::bar());
+
+template<auto x>
+constexpr bool A<x>::baz() {
+ return requires(B b) { b.data_member; };
+}
+static_assert(!A<1>::baz());
+static_assert(A<0>::baz());
+
+template<auto x>
+constexpr bool A<x>::faz() {
+ return requires(B a, B b) {
+ a.p();
+ b.data_member;
+ B::static_member;
+ };
+}
+static_assert(!A<1>::faz());
+static_assert(A<0>::faz());
+}
+
+namespace access_check_in_concepts {
+// 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 2{{implicitly declared private here}}
+};
+template<class T>
+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<int x>
+constexpr bool template_func() {
+ return requires() {
+ A<x>::f();
+ };
+}
+static_assert(!template_func<0>());
+static_assert(template_func<1>());
+
+namespace access_check_in_trailing_requires {
+template <class> struct B;
+class A {
+ static void f();
+ friend struct B<short>;
+};
+
+template <class T> struct B {
+ static constexpr int index() requires requires{ A::f(); } {
+ return 1;
+ }
+ static constexpr int index() {
+ return 2;
+ }
+};
+
+static_assert(B<short>::index() == 1);
+static_assert(B<int>::index() == 2);
+
+namespace missing_member_function {
+template <class T> struct Use;
+class X { int a; friend struct Use<short>; };
+template <class T> struct Use {
+ constexpr static int foo() requires requires(X x) { x.a; } {
+ return 1;
+ }
+};
+
+void test() {
+ // FIXME: This should be an error.
+ Use<int>::foo();
+ static_assert(Use<short>::foo() == 1);
+}
+}
+}
+}
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprConcepts.h"
@@ -1363,7 +1364,16 @@
ExprResult TransformRequiresExpr(RequiresExpr *E) {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- return inherited::TransformRequiresExpr(E);
+ auto TransReq = inherited::TransformRequiresExpr(E);
+ if (E->getBody()->isDependentContext()) {
+ Sema::SFINAETrap Trap(SemaRef);
+ // We recreate the RequiresExpr body, but not by instantiating it.
+ // Produce pending diagnostics for dependent access check.
+ SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
+ if (Trap.hasErrorOccurred())
+ return ExprError();
+ }
+ return TransReq;
}
bool TransformRequiresExprRequirements(
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 UndelayDiagnostics(Actions, Actions.CurContext);
ParseScope BodyScope(this, Scope::DeclScope);
RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr(
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits