-
Notifications
You must be signed in to change notification settings - Fork 22
BaseMembersFinalizer considers the relationship between inherited members and shadowing #1026
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,53 +30,57 @@ inheritBaseMembers( | |
RecordInterface const& base, | ||
AccessKind const A) | ||
{ | ||
auto&& members = allMembers(derived); | ||
|
||
if (A == AccessKind::Public) | ||
{ | ||
// When a class uses public member access specifier to derive from a | ||
// base, all public members of the base class are accessible as public | ||
// members of the derived class and all protected members of the base | ||
// class are accessible as protected members of the derived class. | ||
// Private members of the base are never accessible unless friended. | ||
inheritBaseMembers(derivedId, derived.Public, base.Public); | ||
inheritBaseMembers(derivedId, derived.Protected, base.Protected); | ||
inheritBaseMembers(derivedId, derived.Public, base.Public, members); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this safe? |
||
inheritBaseMembers(derivedId, derived.Protected, base.Protected, members); | ||
} | ||
else if (A == AccessKind::Protected) | ||
{ | ||
// When a class uses protected member access specifier to derive from a | ||
// base, all public and protected members of the base class are | ||
// accessible as protected members of the derived class (private members | ||
// of the base are never accessible unless friended). | ||
inheritBaseMembers(derivedId, derived.Protected, base.Public); | ||
inheritBaseMembers(derivedId, derived.Protected, base.Protected); | ||
inheritBaseMembers(derivedId, derived.Protected, base.Public, members); | ||
inheritBaseMembers(derivedId, derived.Protected, base.Protected, members); | ||
} | ||
else if (A == AccessKind::Private && corpus_.config->extractPrivate) | ||
{ | ||
// When a class uses private member access specifier to derive from a | ||
// base, all public and protected members of the base class are | ||
// accessible as private members of the derived class (private members | ||
// of the base are never accessible unless friended). | ||
inheritBaseMembers(derivedId, derived.Private, base.Public); | ||
inheritBaseMembers(derivedId, derived.Private, base.Protected); | ||
inheritBaseMembers(derivedId, derived.Private, base.Public, members); | ||
inheritBaseMembers(derivedId, derived.Private, base.Protected, members); | ||
} | ||
} | ||
|
||
template <std::ranges::range Range> | ||
void | ||
BaseMembersFinalizer:: | ||
inheritBaseMembers( | ||
SymbolID const& derivedId, | ||
RecordTranche& derived, | ||
RecordTranche const& base) | ||
RecordTranche const& base, | ||
Range allMembers) | ||
{ | ||
inheritBaseMembers(derivedId, derived.NamespaceAliases, base.NamespaceAliases); | ||
inheritBaseMembers(derivedId, derived.Typedefs, base.Typedefs); | ||
inheritBaseMembers(derivedId, derived.Records, base.Records); | ||
inheritBaseMembers(derivedId, derived.Enums, base.Enums); | ||
inheritBaseMembers(derivedId, derived.Functions, base.Functions); | ||
inheritBaseMembers(derivedId, derived.StaticFunctions, base.StaticFunctions); | ||
inheritBaseMembers(derivedId, derived.Variables, base.Variables); | ||
inheritBaseMembers(derivedId, derived.StaticVariables, base.StaticVariables); | ||
inheritBaseMembers(derivedId, derived.Concepts, base.Concepts); | ||
inheritBaseMembers(derivedId, derived.Guides, base.Guides); | ||
inheritBaseMembers(derivedId, derived.NamespaceAliases, base.NamespaceAliases, allMembers); | ||
inheritBaseMembers(derivedId, derived.Typedefs, base.Typedefs, allMembers); | ||
inheritBaseMembers(derivedId, derived.Records, base.Records, allMembers); | ||
inheritBaseMembers(derivedId, derived.Enums, base.Enums, allMembers); | ||
inheritBaseMembers(derivedId, derived.Functions, base.Functions, allMembers); | ||
inheritBaseMembers(derivedId, derived.StaticFunctions, base.StaticFunctions, allMembers); | ||
inheritBaseMembers(derivedId, derived.Variables, base.Variables, allMembers); | ||
inheritBaseMembers(derivedId, derived.StaticVariables, base.StaticVariables, allMembers); | ||
inheritBaseMembers(derivedId, derived.Concepts, base.Concepts, allMembers); | ||
inheritBaseMembers(derivedId, derived.Guides, base.Guides, allMembers); | ||
} | ||
|
||
namespace { | ||
|
@@ -91,12 +95,14 @@ shouldCopy(Config const& config, Info const& M) | |
} | ||
} | ||
|
||
template <std::ranges::range Range> | ||
void | ||
BaseMembersFinalizer:: | ||
inheritBaseMembers( | ||
SymbolID const& derivedId, | ||
std::vector<SymbolID>& derived, | ||
std::vector<SymbolID> const& base) | ||
std::vector<SymbolID> const& base, | ||
Range allMembers) | ||
{ | ||
for (SymbolID const& otherID: base) | ||
{ | ||
|
@@ -116,7 +122,7 @@ inheritBaseMembers( | |
|
||
// Check if derived class has a member that shadows the base member | ||
auto shadowIt = std::ranges::find_if( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh... Here's the relevant point. Yes. We can just call "allMembers" here to get all members of derived. This should be a lazy operation so there's no extra non-constant cost in just calling it again. The only unnecessary extra-cost we have here is the cost of iterating all kinds of members while we want the functions in different access modes. We can fix that by just creating a lazy range that only contains the functions, or by iterating the functions for each access mode. |
||
derived, | ||
allMembers, | ||
[&](SymbolID const& id) | ||
{ | ||
Info* infoPtr = corpus_.find(id); | ||
|
@@ -135,7 +141,7 @@ inheritBaseMembers( | |
// are the same | ||
return info.Name == otherInfo.Name; | ||
}); | ||
MRDOCS_CHECK_OR_CONTINUE(shadowIt == derived.end()); | ||
MRDOCS_CHECK_OR_CONTINUE(shadowIt == allMembers.end()); | ||
|
||
// Not a shadow, so inherit the base member | ||
if (!shouldCopy(corpus_.config, otherInfo)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't
members
a value type with const-reference semantics? Is this a reference to a temporary we're relying on the compiler to keep alive?If so, wouldn't
mean the same thing here since this is just a view?