From 2a8e8270280512bc0bf12d9205469bcf01657b60 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Thu, 27 Aug 2026 08:59:36 +0200 Subject: [PATCH] fix: members re-exported via using reach further derived classes A using-declaration is a member of the class that writes it, so a class deriving from that one inherits it. The buckets of a record tranche were inherited from a list written out by hand, and the one holding using-declarations was missing from the list, so a member re-exported from a base didn't reach classes further down the hierarchy. The buckets are discovered by reflection now, so the list cannot fall behind again. A using-declaration re-exports a name rather than a signature, so whatever a derived class declares under that name hides it. This is now checked in `inheritBaseMembers`. --- .../Finalizers/BaseMembersFinalizer.cpp | 46 +- .../Finalizers/BaseMembersFinalizer.hpp | 8 +- .../using-declaration.cpp | 27 + .../using-declaration.xml | 601 ++++++++++++++++++ 4 files changed, 670 insertions(+), 12 deletions(-) create mode 100644 tests/golden/fixtures/config/inherit-base-members/using-declaration.cpp create mode 100644 tests/golden/fixtures/config/inherit-base-members/using-declaration.xml diff --git a/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.cpp b/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.cpp index 2ea9fc2dba..ca206bf11f 100644 --- a/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.cpp +++ b/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.cpp @@ -4,6 +4,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -67,16 +68,31 @@ inheritBaseMembers( RecordTranche& derived, 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); + // Taken before anything is inherited, so that a member coming from a + // base is never mistaken for one the derived class declares. + std::unordered_set const derivedNames = memberNames(derived); + + describe::for_each_member([&](auto const d) { + inheritBaseMembers( + derivedId, derived.*d.pointer, base.*d.pointer, derivedNames); + }); +} + +std::unordered_set +BaseMembersFinalizer:: +memberNames(RecordTranche const& T) const +{ + std::unordered_set result; + describe::for_each_member([&](auto const d) { + for (SymbolID const& id: T.*d.pointer) + { + if (Symbol const* infoPtr = corpus_.find(id)) + { + result.insert(infoPtr->Name); + } + } + }); + return result; } namespace { @@ -96,7 +112,8 @@ BaseMembersFinalizer:: inheritBaseMembers( SymbolID const& derivedId, std::vector& derived, - std::vector const& base) + std::vector const& base, + std::unordered_set const& derivedNames) { Symbol const* derivedInfo = nullptr; auto const getDerivedInfo = [&]() -> Symbol const* @@ -123,6 +140,13 @@ inheritBaseMembers( FunctionClass::Destructor})); } + // A using-declaration re-exports a name rather than a signature, + // so whatever the derived class declares under that name hides it, + // whichever kind of member that is. The search below cannot see + // it, since it covers the members of one kind. + MRDOCS_CHECK_OR_CONTINUE( + !otherInfo.isUsing() || !derivedNames.contains(otherInfo.Name)); + // Check if derived class has a member that shadows the base member auto shadowIt = std::ranges::find_if( derived, diff --git a/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.hpp b/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.hpp index de07150165..a59ded4f6d 100644 --- a/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.hpp +++ b/src/mrdocs/Metadata/Finalizers/BaseMembersFinalizer.hpp @@ -4,6 +4,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -50,7 +51,12 @@ class BaseMembersFinalizer inheritBaseMembers( SymbolID const& derivedId, std::vector& derived, - std::vector const& base); + std::vector const& base, + std::unordered_set const& derivedNames); + + // The names the members of a tranche go by. + std::unordered_set + memberNames(RecordTranche const& T) const; void finalizeRecords(std::vector const& ids); diff --git a/tests/golden/fixtures/config/inherit-base-members/using-declaration.cpp b/tests/golden/fixtures/config/inherit-base-members/using-declaration.cpp new file mode 100644 index 0000000000..afff2aabba --- /dev/null +++ b/tests/golden/fixtures/config/inherit-base-members/using-declaration.cpp @@ -0,0 +1,27 @@ +// A member re-exported from a private base with a using-declaration is a +// member of the class that re-exports it, so a class deriving from that +// one inherits it like any other member. +// +// `Shadowing` declares the same name for itself, which hides the name +// the base re-exported, so only its own member is listed. + +struct Base +{ + int size() const; +}; + +struct Mid : private Base +{ + using Base::size; + + int count() const; +}; + +struct Leaf : Mid {}; + +struct Deeper : Leaf {}; + +struct Shadowing : Mid +{ + void size(int); +}; diff --git a/tests/golden/fixtures/config/inherit-base-members/using-declaration.xml b/tests/golden/fixtures/config/inherit-base-members/using-declaration.xml new file mode 100644 index 0000000000..33b28d3a27 --- /dev/null +++ b/tests/golden/fixtures/config/inherit-base-members/using-declaration.xml @@ -0,0 +1,601 @@ + + + + index + namespace + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + regular + + 2QDQSSTt2u1SGtB1MPniUV22mgRU 3X6tMK9xDPUFDevsgcGQHqP9Nr7n 4FH6BaSS19xTMtMTnCo9SGnD4GKX AwWrW8E3FDzdDMaBzJKTH6Gdwjv 3wsijUy1xTyDeXCC41zXrkdXzXoU + + + + Base + Base + + + using-declaration.cpp + using-declaration.cpp + 8 + 1 + + + record + 2QDQSSTt2u1SGtB1MPniUV22mgRU + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + struct + + + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + + + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 10 + 5 + + + + function + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + named + + + identifier + int + + + int + + + normal + + + + + Deeper + Deeper + + + using-declaration.cpp + using-declaration.cpp + 22 + 1 + + + record + 3X6tMK9xDPUFDevsgcGQHqP9Nr7n + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + struct + + + + + named + + + identifier + 4FH6BaSS19xTMtMTnCo9SGnD4GKX + Leaf + + + + + public + + + + + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + + + + + count + count + + + + using-declaration.cpp + using-declaration.cpp + 17 + 5 + + + + function + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + + + named + + + identifier + int + + + int + + + normal + + + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 15 + 5 + + + + using + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + normal + + + identifier + size + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 10 + 5 + + + + function + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + named + + + identifier + int + + + int + + + normal + + + + + Leaf + Leaf + + + using-declaration.cpp + using-declaration.cpp + 20 + 1 + + + record + 4FH6BaSS19xTMtMTnCo9SGnD4GKX + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + struct + + + + + named + + + identifier + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + Mid + + + + + public + + + 3X6tMK9xDPUFDevsgcGQHqP9Nr7n + + + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + + + + + count + count + + + + using-declaration.cpp + using-declaration.cpp + 17 + 5 + + + + function + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + + + named + + + identifier + int + + + int + + + normal + + + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 15 + 5 + + + + using + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + normal + + + identifier + size + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 10 + 5 + + + + function + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + named + + + identifier + int + + + int + + + normal + + + + + Mid + Mid + + + using-declaration.cpp + using-declaration.cpp + 13 + 1 + + + record + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + struct + 4FH6BaSS19xTMtMTnCo9SGnD4GKX 3wsijUy1xTyDeXCC41zXrkdXzXoU + + + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + + + + + count + count + + + + using-declaration.cpp + using-declaration.cpp + 17 + 5 + + + + function + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + + + named + + + identifier + int + + + int + + + normal + + + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 15 + 5 + + + + using + 4A2bZWuyNwe8WFq7CNLzicDnVG2s + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + normal + + + identifier + size + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 10 + 5 + + + + function + 2LyeUq3z6s3sEYmVKB4G7MNwVjX6 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + named + + + identifier + int + + + int + + + normal + + + + + Shadowing + Shadowing + + + using-declaration.cpp + using-declaration.cpp + 24 + 1 + + + record + 3wsijUy1xTyDeXCC41zXrkdXzXoU + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + struct + + + + + named + + + identifier + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + Mid + + + + + public + + + + + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 2378zG2zRT4TjhemcZ7T8eXxnWd4 + + + + + count + count + + + + using-declaration.cpp + using-declaration.cpp + 17 + 5 + + + + function + 4K76dkDsi3AdCeBLM2n8KGvKVvw8 + public + regular + AwWrW8E3FDzdDMaBzJKTH6Gdwjv + + + named + + + identifier + int + + + int + + + normal + + + + + size + size + + + + using-declaration.cpp + using-declaration.cpp + 26 + 5 + + + + function + 2378zG2zRT4TjhemcZ7T8eXxnWd4 + public + regular + 3wsijUy1xTyDeXCC41zXrkdXzXoU + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + + + normal + + +