Skip to content

Conversation

bricknerb
Copy link
Contributor

@bricknerb bricknerb commented Oct 10, 2025

This demonstrates two issues:

  1. It seems like we wrongly treat private static data members the same way we treat protected and allow access to them from within derived classes member functions.
  2. Calling instance member functions of a base C++ class using a derived class as self (no implicit upcast) is not yet supported. This isn't related to access control, but prevents us from testing some access control use cases.

Part of #5859.

…data/function members

This demonstrates two bugs:
1. It seems like we wrongly treat private static data members the same way we treat protected and allow access to them from within derived classes member functions.
2. We wrongly don't allow calling instance member functions of a base C++ class using a derived class as self (no implicit upcast). This doesn't seem related to access control, but prevents us from testing some access control use cases.
@bricknerb bricknerb marked this pull request as ready for review October 10, 2025 15:27
@bricknerb bricknerb requested a review from a team as a code owner October 10, 2025 15:27
@bricknerb bricknerb requested review from danakj and removed request for a team October 10, 2025 15:27
// CHECK:STDERR: let static_x: i32 = d.static_x;
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR:
let static_x: i32 = d.static_x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Carbon allow accessing C++ static members like this (as C++ does), or do we need to write static_data?

How about we write static_data here like we did in other tests, and maybe Derived.static_data and Cpp.C.static_data as well?

And we could add another test that just checks the form instance.static_x?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced to Derived.static_data and Cpp.C.static_data.
I might be missing something because just writing static_data would not find that name here.

class Derived {
extend base: Cpp.C;
fn Foo() -> i32 {
return static_x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return static_x;
// TODO: C.static_x is private, so this should fail.
return static_x;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 355 to 359
// CHECK:STDERR: fail_import_function_member_private.carbon:[[@LINE+4]]:3: error: member name `S` not found in `Cpp` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: Cpp.S.static_foo();
// CHECK:STDERR: ^~~~~
// CHECK:STDERR:
Cpp.S.static_foo();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this meant to be Cpp.C? Maybe we also want a Derived.static_fn() as mentioned above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry about that.
Added.

// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_import_function_member_private.carbon: note: declared here [ClassMemberDeclaration]
// CHECK:STDERR:
self.instance_foo();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this testing that the c->instance_foo() below isn't testing? Both are calling a method on C from within the scope of Derived. AFAICT the only difference is pointer vs value, which isn't something this test seems to need to differentiate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c->instance_foo() below isn't calling a method on C from within the scope of Derived, it's calling it from within the scope of the global F, which isn't in the scope of Derived.
I might be missing something here.

class Derived {
extend base: Cpp.C;
fn Foo[self: Self]() -> (i32, i32) {
return (self.instance_x, static_x);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to also test Derived.static_data and maybe Cpp.C.static_data too?

FWIW we don't need to use a return statement here, which will make things simpler I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 142 to 143
int instance_x;
static int static_x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int instance_x;
static int static_x;
int instance_data;
static int static_data;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


class Derived {
extend base: Cpp.C;
fn Foo[self: Self]() -> i32 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we combine this with F() below? self and d are the same things?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the below to Derived and not d when accessing the static variable.
For the instance, if instance_data was protected then it would be behave differently, so I think we want both checks.

class Derived {
extend base: Cpp.C;
fn Foo[self: Self]() {
static_foo();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also Derived.static_fn() and Cpp.C.static_fn()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 320 to 321
auto instance_foo() -> void;
static auto static_foo() -> void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto instance_foo() -> void;
static auto static_foo() -> void;
auto instance_fn() -> void;
static auto static_fn() -> void;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@bricknerb bricknerb requested a review from danakj October 14, 2025 08:45
Copy link
Contributor

@danakj danakj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bricknerb bricknerb added this pull request to the merge queue Oct 14, 2025
Merged via the queue into carbon-language:trunk with commit a0ef7e7 Oct 14, 2025
8 checks passed
@bricknerb bricknerb deleted the private_static branch October 14, 2025 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants