randyli created this revision.
randyli added reviewers: doug.gregor, rjmccall, rsmith, dblaikie,
tigerleapgorge.
Herald added a project: All.
randyli requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
try to fix bug #54406
Per [class.access.base]/6, this example is ill-formed:
struct A {
int m;
} a;
struct B : A {};
int n = a.B::m;
... because the object expression a cannot be implicitly converted to B
(because B is not a base class of A). Clang does not diagnose this and accepts
the member access. This opens a hole in the protected member access rules:
struct C {
protected:
int m;
};
struct D : private C {
int get(C &c) { return c.D::m; }
};
This example is invalid for the same reason, but Clang accepts it.
([class.protected]p1, which normally would prevent D from accessing protected
members on a C object that is not a D object, does not apply here because m as
a member of the naming class D is private, not protected.)
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D122460
Files:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaExprMember.cpp
clang/test/CXX/class.access/class.protected/p1.cpp
clang/test/CXX/drs/dr1xx.cpp
clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
clang/test/SemaCXX/member-expr.cpp
clang/test/SemaCXX/qual-id-test.cpp
clang/test/SemaTemplate/typo-dependent-name.cpp
Index: clang/test/SemaTemplate/typo-dependent-name.cpp
===
--- clang/test/SemaTemplate/typo-dependent-name.cpp
+++ clang/test/SemaTemplate/typo-dependent-name.cpp
@@ -37,9 +37,9 @@
bool f(T other) {
// We can determine that 'inner' does not exist at parse time, so can
// perform typo correction in this case.
-return this->inner::z; // expected-error {{no template named 'inner' in 'Y'; did you mean 'Inner'?}}
+return this->inner::z; // expected-error {{Y::Inner<0>' is not a base of 'Y'}} expected-error {{no template named 'inner' in 'Y'; did you mean 'Inner'?}}
}
};
struct Q { constexpr operator int() { return 0; } };
-void use_y(Y x) { x.f(Q()); }
+void use_y(Y x) { x.f(Q()); } // expected-note {{in instantiation of member function 'Y::f' requested here}}
Index: clang/test/SemaCXX/qual-id-test.cpp
===
--- clang/test/SemaCXX/qual-id-test.cpp
+++ clang/test/SemaCXX/qual-id-test.cpp
@@ -54,7 +54,7 @@
a.A::sub::x();
a.A::B::base::x();
-a.bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}}
+a.bad::x(); // expected-error{{'bad' is not a base of 'sub'}}
a->foo();
a->member::foo();
@@ -75,7 +75,7 @@
a->A::sub::x();
a->A::B::base::x();
-a->bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}}
+a->bad::x(); // expected-error{{'bad' is not a base of 'sub'}}
(*a)->foo();
(*a)->member::foo();
@@ -119,7 +119,7 @@
a.A::B::base::x();
a->A::member::foo();
-a.bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}}
+a.bad::x(); // expected-error{{'bad' is not a base of 'sub'}}
}
void test_fun5() {
Index: clang/test/SemaCXX/member-expr.cpp
===
--- clang/test/SemaCXX/member-expr.cpp
+++ clang/test/SemaCXX/member-expr.cpp
@@ -117,8 +117,8 @@
void f(Y *y) {
y->N::X1; // expected-error{{'rdar8231724::N::X1' is not a member of class 'rdar8231724::Y'}}
-y->Z::n; // expected-error{{'rdar8231724::Z::n' is not a member of class 'rdar8231724::Y'}}
-y->template Z::n; // expected-error{{'rdar8231724::Z::n' is not a member of class 'rdar8231724::Y'}}
+y->Z::n; // expected-error{{'rdar8231724::Z' is not a base of 'Y'}}
+y->template Z::n; // expected-error{{'rdar8231724::Z' is not a base of 'Y'}}
#if __cplusplus <= 199711L // C++03 or earlier modes
// expected-warning@-2{{'template' keyword outside of a template}}
#endif
Index: clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
===
--- clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
@@ -30,7 +30,7 @@
decltype(outer::middle::inner()) a;
void scope() {
-a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}}
+a.decltype(outer::middle())::mfunc(); // expected-error{{PR10127::outer::middle' is not a base of 'inner'}}
a.decltype(outer::middle::inner())::func();
a.decltype(outer::middle())::inner::func();
a.decltype(outer())::middle::inner::func();
Index: clang/test/CXX/drs/dr1xx.cpp
==