Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,25 @@ operator()(RecordSymbol& I)
auto& baseNameType = baseI.Type->asNamed();
MRDOCS_ASSERT(!baseNameType.Name.valueless_after_move());
auto& baseName = baseNameType.Name->asName();
// `baseName.id` is the primary template's ID. When the base
// names a concrete specialization (e.g. `base<int>`) and
// `extract-implicit-specializations` is on, we prefer the
// implicit specialization's ID so inherited members carry
// the substituted types. For a dependent base such as
// `base<T>` in `template<T> class derived : public base<T>`,
// `specializationID` stays invalid (no `ClassTemplate-
// SpecializationDecl` exists in the AST), so we fall back
// to the primary's ID and inherit its members with the
// primary's template parameter intact.
SymbolID baseID = baseName.id;
if (corpus_.config->extractImplicitSpecializations &&
baseName.isSpecialization())
{
auto& baseSpec = baseName.asSpecialization();
baseID = baseSpec.specializationID;
if (baseSpec.specializationID)
{
baseID = baseSpec.specializationID;
}
}
MRDOCS_CHECK_OR_CONTINUE(baseID);
auto basePtr = corpus_.find(baseID);
Expand Down
236 changes: 236 additions & 0 deletions test-files/golden-tests/config/inherit-base-members/template-base.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
= Reference
:mrdocs:

[#index]
== Global namespace

=== Types

[cols="1,4"]
|===
| Name| Description
| link:#base-06[`base`]
| A class template base&period;
| link:#concrete_derived[`concrete&lowbar;derived`]
| A non&hyphen;template that inherits from a concrete specialization&period;
| link:#derived[`derived`]
| A class template that inherits from `base&lt;T&gt;`&period;
|===

[#base-06]
== base

A class template base&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;typename T&gt;
class base;
----

=== Member Functions

[cols="1,4"]
|===
| Name| Description
| link:#base-06-method[`method`]
| A regular member function that should also be inherited&period;
| link:#base-06-operator_subs[`operator&lsqb;&rsqb;`]
| Indexing operator that should be inherited&period;
|===

=== Derived Classes

[cols="1,4"]
|===
|Name|Description

| link:#concrete_derived[`concrete&lowbar;derived`]
| A non&hyphen;template that inherits from a concrete specialization&period;
| link:#derived[`derived`]
| A class template that inherits from `base&lt;T&gt;`&period;
|===

[#base-06-method]
== link:#base-06[base]::method

A regular member function that should also be inherited&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
T&
method();
----

[#base-06-operator_subs]
== link:#base-06[base]::operator&lsqb;&rsqb;

Indexing operator that should be inherited&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
T&
operator&lsqb;&rsqb;(int n);
----

=== Parameters

[cols="1,4"]
|===
|Name|Description

| *n*
| The right operand
|===

[#concrete_derived]
== concrete&lowbar;derived

A non&hyphen;template that inherits from a concrete specialization&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
class concrete&lowbar;derived
: public link:#base-06[base&lt;int&gt;]
----

=== Base Classes

[cols="1,4"]
|===
|Name|Description

| `link:#base-06[base&lt;int&gt;]`
| A class template base&period;
|===

=== Member Functions

[cols=1]
|===
| Name
| link:#concrete_derived-method[`method`]
| link:#concrete_derived-operator_subs[`operator&lsqb;&rsqb;`]
|===

[#concrete_derived-method]
== link:#concrete_derived[concrete&lowbar;derived]::method

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
int&
method();
----

[#concrete_derived-operator_subs]
== link:#concrete_derived[concrete&lowbar;derived]::operator&lsqb;&rsqb;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
int&
operator&lsqb;&rsqb;(int n);
----

[#derived]
== derived

A class template that inherits from `base&lt;T&gt;`&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;typename T&gt;
class derived
: public link:#base-06[base&lt;T&gt;]
----

=== Base Classes

[cols="1,4"]
|===
|Name|Description

| `link:#base-06[base&lt;T&gt;]`
| A class template base&period;
|===

=== Member Functions

[cols="1,4"]
|===
| Name| Description
| link:#derived-method[`method`]
| A regular member function that should also be inherited&period;
| link:#derived-operator_subs[`operator&lsqb;&rsqb;`]
| Indexing operator that should be inherited&period;
|===

[#derived-method]
== link:#derived[derived]::method

A regular member function that should also be inherited&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
T&
method();
----

[#derived-operator_subs]
== link:#derived[derived]::operator&lsqb;&rsqb;

Indexing operator that should be inherited&period;

=== Synopsis

Declared in `&lt;template&hyphen;base&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
T&
operator&lsqb;&rsqb;(int n);
----

=== Parameters

[cols="1,4"]
|===
|Name|Description

| *n*
| The right operand
|===


[.small]#Created with https://www.mrdocs.com[MrDocs]#
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Reproduces issue #1176: members defined in a class template base do not
// appear in derived classes that inherit from a specialization of that base.
//
// Boost.Multi's `array_ref` derives from `subarray`, and `subarray`'s
// `operator[]` did not show up on `array_ref`'s documentation page,
// even with `inherit-base-members: copy-all`.

/// A class template base.
template <typename T>
class base
{
public:
/// Indexing operator that should be inherited.
T& operator[](int n);

/// A regular member function that should also be inherited.
T& method();
};

/// A class template that inherits from `base<T>`.
template <typename T>
class derived
: public base<T>
{};

/// A non-template that inherits from a concrete specialization.
class concrete_derived
: public base<int>
{};
Loading
Loading