This is an archive of the discontinued LLVM Phabricator instance.

[clang] fixed bug #54406
Changes PlannedPublic

Authored by randyli on Mar 24 2022, 10:09 PM.

Details

Summary

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.)

Diff Detail

Event Timeline

randyli created this revision.Mar 24 2022, 10:09 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 10:09 PM
randyli requested review of this revision.Mar 24 2022, 10:09 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 10:09 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
randyli edited the summary of this revision. (Show Details)Mar 24 2022, 10:13 PM
rjmccall added inline comments.Mar 25 2022, 10:49 PM
clang/lib/Sema/SemaExprMember.cpp
690

We don't generally cite bug numbers in the source code; we just cite the language rule. You can reference the bug number in your test, though.

The standard says that this is an error even when the member access is implicit, so the check for BaseExpr is incorrect.

Conversely, the standard says this is not an error when the declaration referenced is not a non-static data member or member function, so you cannot do this before the lookup; in fact, you cannot do it until we've fully resolved the lookup, which may require contextual information.

All of the code paths that build a non-static member eventually funnel into BuildMemberExpr, so maybe that's the right place for the check? But note that you have to check explicitly for a non-static member, because MemberExpr is used for all of them.

Technically, this rule wasn't in C++98, but since it does appear in C++03, I agree we should just enforce it unconditionally, as we usually treat C++03 as an errata release rather than its own language mode.

randyli planned changes to this revision.Mar 27 2022, 8:01 PM
randyli added inline comments.
clang/lib/Sema/SemaExprMember.cpp
690

ok, thank you for the suggestion, I'll look into BuildMemeberExpr and try again