diff --git a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp index 40b944618..14e84f449 100644 --- a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp @@ -37,8 +37,8 @@ inheritBaseMembers( // 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, AccessKind::Public, base.Public); + inheritBaseMembers(derivedId, derived, AccessKind::Protected, base.Protected); } else if (A == AccessKind::Protected) { @@ -46,8 +46,8 @@ inheritBaseMembers( // 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, AccessKind::Protected, base.Public); + inheritBaseMembers(derivedId, derived, AccessKind::Protected, base.Protected); } else if (A == AccessKind::Private && corpus_.config->extractPrivate) { @@ -55,8 +55,8 @@ inheritBaseMembers( // 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, AccessKind::Private, base.Public); + inheritBaseMembers(derivedId, derived, AccessKind::Private, base.Protected); } } @@ -64,19 +64,20 @@ void BaseMembersFinalizer:: inheritBaseMembers( SymbolID const& derivedId, - RecordTranche& derived, + RecordInterface& derived, + AccessKind const A, RecordTranche const& base) { - 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<&RecordTranche::NamespaceAliases>(derivedId, derived, A, base.NamespaceAliases); + inheritBaseMembers<&RecordTranche::Typedefs>(derivedId, derived, A, base.Typedefs); + inheritBaseMembers<&RecordTranche::Records>(derivedId, derived, A, base.Records); + inheritBaseMembers<&RecordTranche::Enums>(derivedId, derived, A, base.Enums); + inheritBaseMembers<&RecordTranche::Functions>(derivedId, derived, A, base.Functions); + inheritBaseMembers<&RecordTranche::StaticFunctions>(derivedId, derived, A, base.StaticFunctions); + inheritBaseMembers<&RecordTranche::Variables>(derivedId, derived, A, base.Variables); + inheritBaseMembers<&RecordTranche::StaticVariables>(derivedId, derived, A, base.StaticVariables); + inheritBaseMembers<&RecordTranche::Concepts>(derivedId, derived, A, base.Concepts); + inheritBaseMembers<&RecordTranche::Guides>(derivedId, derived, A, base.Guides); } namespace { @@ -89,19 +90,65 @@ shouldCopy(Config const& config, Info const& M) } return config->inheritBaseMembers == PublicSettings::BaseMemberInheritance::CopyAll; } + +bool isShadowed(SymbolID const& otherID, std::vector const& Usings, CorpusImpl& corpus_) +{ + for (SymbolID const& usingId: Usings) + { + Info* usingInfoPtr = corpus_.find(usingId); + MRDOCS_CHECK_OR_CONTINUE(usingInfoPtr); + + UsingInfo const& using_ = usingInfoPtr->asUsing(); + if (contains(using_.ShadowDeclarations, otherID)) + { + return true; + } + } + return false; } +RecordTranche& get(RecordInterface& derived, AccessKind const A) +{ + switch (A) + { + case AccessKind::Public: return derived.Public; + case AccessKind::Protected: return derived.Protected; + case AccessKind::Private: return derived.Private; + default: MRDOCS_UNREACHABLE(); + } +} +} + +template RecordTranche::* Symbols> void BaseMembersFinalizer:: inheritBaseMembers( SymbolID const& derivedId, - std::vector& derived, + RecordInterface& derived, + AccessKind const A, std::vector const& base) { for (SymbolID const& otherID: base) { + AccessKind effectiveA = A; + if (isShadowed(otherID, derived.Public.Usings, corpus_)) + { + effectiveA = AccessKind::Public; + } + else if (isShadowed(otherID, derived.Protected.Usings, corpus_)) + { + effectiveA = AccessKind::Protected; + } + else if (isShadowed(otherID, derived.Private.Usings, corpus_)) + { + effectiveA = AccessKind::Private; + } + + auto& tranche = get(derived, effectiveA); + auto& symbols = tranche.*Symbols; + // Find the info from the base class - MRDOCS_CHECK_OR_CONTINUE(!contains(derived, otherID)); + MRDOCS_CHECK_OR_CONTINUE(!contains(symbols, otherID)); Info* otherInfoPtr = corpus_.find(otherID); MRDOCS_CHECK_OR_CONTINUE(otherInfoPtr); Info& otherInfo = *otherInfoPtr; @@ -116,7 +163,7 @@ inheritBaseMembers( // Check if derived class has a member that shadows the base member auto shadowIt = std::ranges::find_if( - derived, + symbols, [&](SymbolID const& id) { Info* infoPtr = corpus_.find(id); @@ -135,7 +182,7 @@ inheritBaseMembers( // are the same return info.Name == otherInfo.Name; }); - MRDOCS_CHECK_OR_CONTINUE(shadowIt == derived.end()); + MRDOCS_CHECK_OR_CONTINUE(shadowIt == symbols.end()); // Not a shadow, so inherit the base member if (!shouldCopy(corpus_.config, otherInfo)) @@ -148,7 +195,7 @@ inheritBaseMembers( // extraction mode to be regular, but that is controversial. if (otherInfo.Extraction != ExtractionMode::Dependency) { - derived.push_back(otherID); + symbols.push_back(otherID); } } else @@ -163,7 +210,7 @@ inheritBaseMembers( otherCopy->id = SymbolID::createFromString( std::format("{}-{}", toBase16Str(otherCopy->Parent), toBase16Str(otherInfo.id))); - derived.push_back(otherCopy->id); + symbols.push_back(otherCopy->id); // Get the extraction mode from the derived class if (otherCopy->Extraction == ExtractionMode::Dependency) { diff --git a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp index 1b6659352..7ba029dee 100644 --- a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp @@ -42,13 +42,16 @@ class BaseMembersFinalizer void inheritBaseMembers( SymbolID const& derivedId, - RecordTranche& derived, + RecordInterface& derived, + AccessKind const A, RecordTranche const& base); + template RecordTranche::* Symbols> void inheritBaseMembers( SymbolID const& derivedId, - std::vector& derived, + RecordInterface& derived, + AccessKind const A, std::vector const& base); void