[clang] [clang] Fix static_cast bypassing access control (PR #132285)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 22 12:57:27 PDT 2025
================
@@ -23,3 +22,67 @@ void test(A &a, B &b) {
const A &&ar10 = static_cast<const A&&>(xvalue<A>());
const A &&ar11 = static_cast<const A&&>(xvalue<B>());
}
+
+struct C : private A { // expected-note 4 {{declared private here}}
+ C&& that();
+
+ void f() {
+ (void)static_cast<A&&>(*this);
+ (void)static_cast<const A&&>(*this);
+
+ (void)static_cast<A&&>(that());
+ (void)static_cast<const A&&>(that());
+ }
+};
+C c;
+const C cc;
+
+void f() {
+ static_cast<A&&>(c); // expected-error {{cannot cast 'C' to its private base class 'A'}}
+ static_cast<A&&>(c.that()); // expected-error {{cannot cast 'C' to its private base class 'A'}}
+
+ static_cast<const A&&>(c); // expected-error {{cannot cast 'C' to its private base class 'const A'}}
+ static_cast<const A&&>(c.that()); // expected-error {{cannot cast 'C' to its private base class 'const A'}}
+}
+
+constexpr auto v = (
+ (A&&)c,
+ (A&&)(C&&)c,
+ (A&&)cc,
+ (A&&)(const C&&)c,
+ (const A&&)c,
+ (const A&&)(C&&)c,
+ (const A&&)cc,
+ (const A&&)(const C&&)c
+);
+
+struct D : A, B { // expected-warning {{direct base 'A' is inaccessible due to ambiguity}}
+ D&& rv();
+};
+D d;
+
+void g(const D cd) {
+ static_cast<A&&>(d); // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ static_cast<A&&>(d.rv()); // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+
+ static_cast<const A&&>(d); // expected-error {{ambiguous conversion from derived class 'D' to base class 'const A'}}
+ static_cast<const A&&>(d.rv()); // expected-error {{ambiguous conversion from derived class 'D' to base class 'const A'}}
+
+ (A&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (A&&)(D&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (A&&)cd; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (A&&)(const D&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (const A&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (const A&&)(D&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (const A&&)cd; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+ (const A&&)(const D&&)d; // expected-error {{ambiguous conversion from derived class 'D' to base class 'A'}}
+}
+
+template<class T, class U>
+auto h(U u = {}) -> decltype(static_cast<T&&>(u));
+
+template<class, class>
+int h();
+
+int i = h<A, C>();
+int j = h<A, D>();
----------------
Sirraide wrote:
I don’t think we normally test via SFINAE like this; I’d probably just remove the second `h()` overload and test that we actually emit an error.
https://github.com/llvm/llvm-project/pull/132285
More information about the cfe-commits
mailing list