From 82f1c436c437d72c3ede8d918afddb6838fdd57d Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Tue, 22 Sep 2026 11:14:17 +0200 Subject: [PATCH 1/3] fix: an inheriting constructor is named after its base This fixes a bug for which an inheriting constructor was documented under the wrong name, or under no name at all. The synopsis of `using Base::Base;` read `using Base::Derived;`, and the heading and the member table gave the declaration the derived class's name, so several of them in one class were indistinguishable. With a base that depends on a template parameter the name came out empty instead, reaching the page as "Unnamed using" and the synopsis as `using Base::;`. Clang stores the first as a constructor of the derived class, and the second as a constructor of a type that has no class behind it at all. We now take the name from the last component of the qualifier, which spells the class as written, be it a class, a class template specialization, an alias or a template parameter. A declaration named after the base would hide the base from references written in the derived class or in its members, such as `@ref Base` or `@copydoc Base`, since lookup searches the members of a class before the enclosing scopes. Lookup now passes over an inheriting constructor, so these references still resolve to the base class. I've added tests. Refs #1276. --- src/mrdocs/AST/ASTVisitor.cpp | 21 + src/mrdocs/Corpus.cpp | 19 + .../ref/inheriting-constructor-base.adoc | 439 +++++ .../ref/inheriting-constructor-base.cpp | 53 + .../ref/inheriting-constructor-base.xml | 1008 +++++++++++ .../ref/inheriting-constructor-base.yml | 1 + .../symbols/using/using-filtered-base.cpp | 14 +- .../symbols/using/using-filtered-base.xml | 389 ++++- .../using/using-inheriting-constructor.adoc | 619 +++++++ .../using/using-inheriting-constructor.cpp | 80 + .../using/using-inheriting-constructor.xml | 1478 +++++++++++++++++ .../using/using-inheriting-constructor.yml | 1 + .../symbols/using/using-member-function.xml | 36 +- 13 files changed, 4132 insertions(+), 26 deletions(-) create mode 100644 tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.adoc create mode 100644 tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.cpp create mode 100644 tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.xml create mode 100644 tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.yml create mode 100644 tests/golden/fixtures/symbols/using/using-inheriting-constructor.adoc create mode 100644 tests/golden/fixtures/symbols/using/using-inheriting-constructor.cpp create mode 100644 tests/golden/fixtures/symbols/using/using-inheriting-constructor.xml create mode 100644 tests/golden/fixtures/symbols/using/using-inheriting-constructor.yml diff --git a/src/mrdocs/AST/ASTVisitor.cpp b/src/mrdocs/AST/ASTVisitor.cpp index 1e9fc460597..0c185aa63ec 100644 --- a/src/mrdocs/AST/ASTVisitor.cpp +++ b/src/mrdocs/AST/ASTVisitor.cpp @@ -138,6 +138,25 @@ underlyingConversion(clang::NamedDecl const* D) return dyn_cast(target); } +// Name an inheriting constructor after the class it inherits from. +// +// `using Base::Base;` declares the constructors of `Base`, but Clang names +// the declaration as a constructor of the derived class, and, where the +// base depends on a template parameter, as a constructor of a type with no +// class behind it. The prefix built from the qualifier spells the class as +// written: a class, a class template specialization, an alias or a +// template parameter. +void +nameInheritingConstructor(UsingSymbol& I, clang::DeclarationName const& Name) +{ + if (Name.getNameKind() == clang::DeclarationName::CXXConstructorName && + I.IntroducedName->Prefix) + { + I.Name = (*I.IntroducedName->Prefix)->Identifier; + I.IntroducedName->Identifier = I.Name; + } +} + } // unnamed namespace void @@ -1414,6 +1433,7 @@ populate( { I.IntroducedName->Identifier = conversionNameAsWritten(CD); } + nameInheritingConstructor(I, Name); for (clang::UsingShadowDecl const* UDS: D->shadows()) { ScopeExitRestore s(mode_, Dependency); @@ -1442,6 +1462,7 @@ populateDependentUsing( auto INI = toName(Name, {}, NNS); MRDOCS_CHECK_OR(INI); I.IntroducedName = *INI; + nameInheritingConstructor(I, Name); } void diff --git a/src/mrdocs/Corpus.cpp b/src/mrdocs/Corpus.cpp index b5c404eb50c..9e75ca367b9 100644 --- a/src/mrdocs/Corpus.cpp +++ b/src/mrdocs/Corpus.cpp @@ -59,6 +59,17 @@ isTransparent(Symbol const& info) }); } +// Whether `U` inherits constructors: within a class, `using Base::Base;` +// names the constructors of `Base`, because the name repeats the last +// component of the qualifier. +bool +isInheritingConstructor(UsingSymbol const& U) +{ + Name const& introduced = *U.IntroducedName; + return introduced.Prefix && + (*introduced.Prefix)->Identifier == introduced.Identifier; +} + SymbolID findFirstParentInfo( detail::SymbolSet const& info, @@ -1002,6 +1013,14 @@ lookupImpl( } else { + if constexpr (std::same_as) + { + // An inheriting constructor is named after its base, + // and the name still means the base class. + MRDOCS_CHECK_OR( + !(context.isRecord() && isInheritingConstructor(M)), + matchRes); + } MRDOCS_CHECK_OR(member.Name == component.Name, matchRes); } matchRes = MatchLevel::Name; diff --git a/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.adoc b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.adoc new file mode 100644 index 00000000000..a129c3d69a8 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.adoc @@ -0,0 +1,439 @@ += Reference +:mrdocs: + +[#index] +== Global index + +=== Types + +[cols="1,4"] +|=== +| Name| Description +| link:#AliasDerived[`AliasDerived`] +| Inherit the constructors of a base named through a member alias. +| link:#Base[`Base`] +| A base with constructors to inherit. +| link:#BaseTemplate[`BaseTemplate`] +| A base template with constructors to inherit. +| link:#DependentDerived[`DependentDerived`] +| Inherit the constructors of link:#BaseTemplate[`BaseTemplate`]. +| link:#Derived[`Derived`] +| Inherit the constructors of link:#Base[`Base`]. +|=== + + +[#AliasDerived] +== AliasDerived + +Inherit the constructors of a base named through a member alias. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct AliasDerived + : link:#BaseTemplate[BaseTemplate<T>] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#BaseTemplate[BaseTemplate<T>]` +| A base template with constructors to inherit. +|=== + +=== Type Aliases + +[cols="1,4"] +|=== +| Name| Description +| link:#AliasDerived-base_type-097[`base_type`] +| The base class. +|=== + + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#AliasDerived-h[`h`] +| The base class. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#AliasDerived-base_type-09c[`base_type`] +| The constructors of `base_type`. +|=== + + +[#AliasDerived-base_type-097] +== link:#AliasDerived[AliasDerived]::base_type + +The base class. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using base_type = link:#BaseTemplate[BaseTemplate<T>]; +---- + +[#AliasDerived-h] +== link:#AliasDerived[AliasDerived]::h + +The base class. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +h(); +---- + +[#AliasDerived-base_type-09c] +== link:#AliasDerived[AliasDerived]::base_type + +The constructors of `base_type`. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using base_type::base_type; +---- + +[#Base] +== Base + +A base with constructors to inherit. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Base; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-2constructor-00[`Base`] [.small]#[constructor]# +| Constructors +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#Derived[`Derived`] +| Inherit the constructors of `Base`. +|=== + +[#Base-2constructor-00] +== link:#Base[Base]::Base + +Constructors + +=== Synopses + +Declared in `<inheriting‐constructor‐base.cpp>` + +A base with constructors to inherit. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +constexpr +link:#Base[Base](link:#Base[Base] const&) = default; +---- + +[.small]#link:#Base[_» more..._]# + +A base with constructors to inherit. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +constexpr +link:#Base[Base](link:#Base[Base]&&) = default; +---- + +[.small]#link:#Base[_» more..._]# + +Construct from a count. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +link:#Base-2constructor-09[Base](int value); +---- + +[.small]#link:#Base-2constructor-09[_» more..._]# + +[#Base-2constructor-09] +== link:#Base[Base]::Base + +Construct from a count. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +Base(int value); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *value* +| The value to construct from +|=== + +[#BaseTemplate] +== BaseTemplate + +A base template with constructors to inherit. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct BaseTemplate; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#BaseTemplate-2constructor[`BaseTemplate`] [.small]#[constructor]# +| Construct from a value. +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#AliasDerived[`AliasDerived`] +| Inherit the constructors of a base named through a member alias. +| link:#DependentDerived[`DependentDerived`] +| Inherit the constructors of `BaseTemplate`. +|=== + +[#BaseTemplate-2constructor] +== link:#BaseTemplate[BaseTemplate]::BaseTemplate + +Construct from a value. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +BaseTemplate(T value); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *value* +| The object to construct from +|=== + +[#DependentDerived] +== DependentDerived + +Inherit the constructors of link:#BaseTemplate[`BaseTemplate`]. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct DependentDerived + : link:#BaseTemplate[BaseTemplate<T>] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#BaseTemplate[BaseTemplate<T>]` +| A base template with constructors to inherit. +|=== + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#DependentDerived-g[`g`] +| A base template with constructors to inherit. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#DependentDerived-BaseTemplate[`BaseTemplate`] +| The constructors of `BaseTemplate`. +|=== + + +[#DependentDerived-g] +== link:#DependentDerived[DependentDerived]::g + +A base template with constructors to inherit. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +g(); +---- + +[#DependentDerived-BaseTemplate] +== link:#DependentDerived[DependentDerived]::BaseTemplate + +The constructors of `BaseTemplate`. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseTemplate<T>::BaseTemplate; +---- + +[#Derived] +== Derived + +Inherit the constructors of link:#Base[`Base`]. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Derived + : link:#Base[Base] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#Base[Base]` +| A base with constructors to inherit. +|=== + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Derived-f[`f`] +| A base with constructors to inherit. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Derived-2constructor[`Base`] +| The constructors of `Base`. +|=== + + +[#Derived-f] +== link:#Derived[Derived]::f + +A base with constructors to inherit. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +f(); +---- + +[#Derived-2constructor] +== link:#Derived[Derived]::Base + +The constructors of `Base`. + +=== Synopsis + +Declared in `<inheriting‐constructor‐base.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using Base::Base; +---- + +=== Introduced Symbols + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-2constructor-09[`Base`] [.small]#[constructor]# +| Construct from a count. +|=== + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.cpp b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.cpp new file mode 100644 index 00000000000..249b412f8de --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.cpp @@ -0,0 +1,53 @@ +// A class that inherits the constructors of its base has a member named +// after the base: the using-declaration. A reference to that name from +// the class or from one of its members still means the base. + +/// A base with constructors to inherit. +struct Base +{ + /// Construct from a count. + explicit Base(int); +}; + +/// Inherit the constructors of @ref Base. +struct Derived : Base +{ + /// The constructors of `Base`. + using Base::Base; + + /// @copydoc Base + void f(); +}; + +/// A base template with constructors to inherit. +template +struct BaseTemplate +{ + /// Construct from a value. + explicit BaseTemplate(T); +}; + +/// Inherit the constructors of @ref BaseTemplate. +template +struct DependentDerived : BaseTemplate +{ + /// The constructors of `BaseTemplate`. + using BaseTemplate::BaseTemplate; + + /// @copydoc BaseTemplate + void g(); +}; + +/// Inherit the constructors of a base named through a member alias. +template +struct AliasDerived : BaseTemplate +{ + /// The base class. + using base_type = BaseTemplate; + + /// The constructors of `base_type`. + using base_type::base_type; + + /// @copydoc base_type + void h(); +}; diff --git a/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.xml b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.xml new file mode 100644 index 00000000000..978d61ad390 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.xml @@ -0,0 +1,1008 @@ + + + + index + namespace + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + regular + + rgyMURE42iwFFznjoTRbCxiLWHJ 2QDQSSTt2u1SGtB1MPniUV22mgRU 37ak26eCioiUagg244czg7Tfferh 3HCWrvCAwcGXZNKsRyWUP18Yr7Ph 2QfuRYRMzuRBwzGdx83iwR1prTJZ + + + + AliasDerived + AliasDerived + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 42 + 1 + + + + record + rgyMURE42iwFFznjoTRbCxiLWHJ + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a base named through a member alias. + + + + + struct + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + public + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 43 + 23 + + + + + + + 375uAsQr3B9Q41aMAJPW59Y8g1tk + 2MAKgZ82xtjwqCPKaVRbYiuPfuxs + 3BY7v4dB9XQ9h6f5GVEXZEEU2piK + + + + + base_type + base_type-097 + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 46 + 5 + + + + + typedef + 375uAsQr3B9Q41aMAJPW59Y8g1tk + public + regular + rgyMURE42iwFFznjoTRbCxiLWHJ + + + brief + + + text + The base class. + + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + + h + h + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 52 + 5 + + + + + function + 2MAKgZ82xtjwqCPKaVRbYiuPfuxs + public + regular + rgyMURE42iwFFznjoTRbCxiLWHJ + + + brief + + + text + The base class. + + + + base_type + + + + + + named + + + identifier + void + + + void + + + normal + + + + base_type + base_type-09c + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 49 + 5 + + + + + using + 3BY7v4dB9XQ9h6f5GVEXZEEU2piK + public + regular + rgyMURE42iwFFznjoTRbCxiLWHJ + + + brief + + + text + The constructors of + + + code + + + text + base_type + + + + + text + . + + + + + normal + + + identifier + base_type + + + identifier + 375uAsQr3B9Q41aMAJPW59Y8g1tk + base_type + + + + + + + Base + Base + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 6 + 1 + + + + record + 2QDQSSTt2u1SGtB1MPniUV22mgRU + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base with constructors to inherit. + + + + + struct + 2QfuRYRMzuRBwzGdx83iwR1prTJZ + + + 6nxnBxu76i4CNTU56TEAdJaK7S3 + + + + + Base + 2constructor-00 + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 6 + 8 + + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 9 + 5 + + + + + overloads + 6nxnBxu76i4CNTU56TEAdJaK7S3 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Constructors + + + + + constructor + 2pYCUC4g41YZueFgKj6bWPpt3cBY 2vUVyxM3mF2tPi3t95dyB6n2pMSt 37UmJk6nbWYMWgYzRfPMwFyFyaCE + + + named + + + identifier + void + + + void + + + + + Base + 2constructor-09 + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 9 + 5 + + + + + function + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + + + BaseTemplate + BaseTemplate + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 23 + 1 + + + + record + 37ak26eCioiUagg244czg7Tfferh + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base template with constructors to inherit. + + + + + struct + + rgyMURE42iwFFznjoTRbCxiLWHJ 3HCWrvCAwcGXZNKsRyWUP18Yr7Ph + + + 2HWftN9YUwLBCHBFitq5MTuxSMZK + + + + + BaseTemplate + 2constructor + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 27 + 5 + + + + + function + 2HWftN9YUwLBCHBFitq5MTuxSMZK + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Construct from a value. + + + + + + param + + + text + The object to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + T + + + + + value + + + constructor + + + + DependentDerived + DependentDerived + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 31 + 1 + + + + record + 3HCWrvCAwcGXZNKsRyWUP18Yr7Ph + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of + + + reference + BaseTemplate + 37ak26eCioiUagg244czg7Tfferh + + + text + . + + + + + struct + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + public + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 32 + 27 + + + + + + + giWaHNnvrzAhtWt3K4j6peWVdxT + 3uiWPr2Eb7ahf36ryCit6UntESX3 + + + + + g + g + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 38 + 5 + + + + + function + giWaHNnvrzAhtWt3K4j6peWVdxT + public + regular + 3HCWrvCAwcGXZNKsRyWUP18Yr7Ph + + + brief + + + text + A base template with constructors to inherit. + + + + BaseTemplate + + + + + + named + + + identifier + void + + + void + + + normal + + + + BaseTemplate + BaseTemplate + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 35 + 5 + + + + + using + 3uiWPr2Eb7ahf36ryCit6UntESX3 + public + regular + 3HCWrvCAwcGXZNKsRyWUP18Yr7Ph + + + brief + + + text + The constructors of + + + code + + + text + BaseTemplate + + + + + text + . + + + + + normal + + + identifier + BaseTemplate + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + Derived + Derived + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 13 + 1 + + + + record + 2QfuRYRMzuRBwzGdx83iwR1prTJZ + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of + + + reference + Base + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + text + . + + + + + struct + + + + + named + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + public + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 13 + 18 + + + + + + + n7sp7u7EcnkowMYQEnETsveWP5h + 26X9XwXJan99THTDGWRXXoR7imFg + + + + + f + f + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 19 + 5 + + + + + function + n7sp7u7EcnkowMYQEnETsveWP5h + public + regular + 2QfuRYRMzuRBwzGdx83iwR1prTJZ + + + brief + + + text + A base with constructors to inherit. + + + + Base + + + + + + named + + + identifier + void + + + void + + + normal + + + + Base + 2constructor + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 16 + 5 + + + + + using + 26X9XwXJan99THTDGWRXXoR7imFg + public + regular + 2QfuRYRMzuRBwzGdx83iwR1prTJZ + + + brief + + + text + The constructors of + + + code + + + text + Base + + + + + text + . + + + + + normal + + + identifier + Base + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + + + Base + 2constructor-09 + + + + inheriting-constructor-base.cpp + inheriting-constructor-base.cpp + 9 + 5 + + + + + function + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + + diff --git a/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.yml b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.yml new file mode 100644 index 00000000000..4507c7d09b6 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/inheriting-constructor-base.yml @@ -0,0 +1 @@ +generator: [xml, adoc] diff --git a/tests/golden/fixtures/symbols/using/using-filtered-base.cpp b/tests/golden/fixtures/symbols/using/using-filtered-base.cpp index 1ce4956fe71..2e1076d884f 100644 --- a/tests/golden/fixtures/symbols/using/using-filtered-base.cpp +++ b/tests/golden/fixtures/symbols/using/using-filtered-base.cpp @@ -8,6 +8,9 @@ namespace ns { /// A base marked as an implementation detail. struct Detail { + /// Construct from a count. + explicit Detail(int); + /// A member of the detail base. int hidden() const; }; @@ -15,13 +18,22 @@ struct Detail /// A base excluded from extraction. struct Excluded { + /// Construct from a string. + explicit Excluded(char const*); + /// A member of the excluded base. int gone() const; }; -/// Re-export a member of each. +/// Re-export members of each. struct Reexport : private Detail, private Excluded { + /// The constructors of the implementation-defined base. + using Detail::Detail; + + /// The constructors of the excluded base. + using Excluded::Excluded; + /// Re-exported from the implementation-defined base. using Detail::hidden; diff --git a/tests/golden/fixtures/symbols/using/using-filtered-base.xml b/tests/golden/fixtures/symbols/using/using-filtered-base.xml index cf145443b43..ac037dac532 100644 --- a/tests/golden/fixtures/symbols/using/using-filtered-base.xml +++ b/tests/golden/fixtures/symbols/using/using-filtered-base.xml @@ -60,10 +60,295 @@ struct - 2pZPcSxiLCTW81Ep9WcR6CSNvBe7 + 3yhiTTQBtLW1uvaK5JkQisLQff6b 2pZPcSxiLCTW81Ep9WcR6CSNvBe7 + + Detail + 2constructor-0d + + + using-filtered-base.cpp + using-filtered-base.cpp + 9 + 8 + + + + + using-filtered-base.cpp + using-filtered-base.cpp + 12 + 5 + + + + + overloads + 3yhiTTQBtLW1uvaK5JkQisLQff6b + public + implementation-defined + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + + + brief + + + text + Constructors + + + + + constructor + 25QYJmCVGUJ193ynvbDgb6gTh7cy hhHVAaaxpAPw5zLwZkh8xSFifqd 2FQUaDnVistFkBzg32eg37ZVrWuD + + + named + + + identifier + void + + + void + + + + + Detail + 2constructor-04 + + + using-filtered-base.cpp + using-filtered-base.cpp + 9 + 8 + + + + function + 25QYJmCVGUJ193ynvbDgb6gTh7cy + public + implementation-defined + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + + + brief + + + text + A base marked as an implementation detail. + + + + + + param + + + text + The object to copy construct from + + + other + + + + + + named + + + identifier + void + + + void + + + + + + + lvalue-reference + + + named + + + + identifier + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + Detail + + + + + + + other + + + constructor + + constexpr + + + + Detail + 2constructor-03 + + + using-filtered-base.cpp + using-filtered-base.cpp + 9 + 8 + + + + function + hhHVAaaxpAPw5zLwZkh8xSFifqd + public + implementation-defined + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + + + brief + + + text + A base marked as an implementation detail. + + + + + + param + + + text + The object to move construct from + + + other + + + + + + named + + + identifier + void + + + void + + + + + + + rvalue-reference + + + named + + + identifier + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + Detail + + + + + + + other + + + constructor + + constexpr + + + + Detail + 2constructor-05 + + + + using-filtered-base.cpp + using-filtered-base.cpp + 12 + 5 + + + + + function + 2FQUaDnVistFkBzg32eg37ZVrWuD + public + implementation-defined + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + hidden hidden @@ -72,7 +357,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 12 + 15 5 @@ -117,7 +402,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 23 + 29 1 @@ -132,7 +417,7 @@ text - Re-export a member of each. + Re-export members of each. @@ -140,10 +425,100 @@ struct - npRa45X8z2orh68KkLG7cQmGXz1 3a9zMXoj73M9zQcYYmsCqtCxtEE4 + 3cF5rVRHGaz8c3pRdjTbmftK8jFK 2L4rQr1ZEKwSCSeK9UHJVVQb1FT9 npRa45X8z2orh68KkLG7cQmGXz1 3a9zMXoj73M9zQcYYmsCqtCxtEE4 + + Detail + Detail + + + + using-filtered-base.cpp + using-filtered-base.cpp + 32 + 5 + + + + + using + 3cF5rVRHGaz8c3pRdjTbmftK8jFK + public + regular + 3D3Ncqr4SiKkKtsbeUAFYeJcB64v + + + brief + + + text + The constructors of the implementation-defined base. + + + + + normal + + + identifier + Detail + + + identifier + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + Detail + + + + + + + Excluded + Excluded + + + + using-filtered-base.cpp + using-filtered-base.cpp + 35 + 5 + + + + + using + 2L4rQr1ZEKwSCSeK9UHJVVQb1FT9 + public + regular + 3D3Ncqr4SiKkKtsbeUAFYeJcB64v + + + brief + + + text + The constructors of the excluded base. + + + + + normal + + + identifier + Excluded + + + identifier + 3c5RuWKWcxGpq8T1Vzzp41kueCYr + Excluded + + + + + gone gone @@ -152,7 +527,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 29 + 41 5 @@ -197,7 +572,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 26 + 38 5 diff --git a/tests/golden/fixtures/symbols/using/using-inheriting-constructor.adoc b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.adoc new file mode 100644 index 00000000000..911e4fcec79 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.adoc @@ -0,0 +1,619 @@ += Reference +:mrdocs: + +[#index] +== Global index + +=== Types + +[cols="1,4"] +|=== +| Name| Description +| link:#Base[`Base`] +| A base with constructors to inherit. +| link:#BaseTemplate[`BaseTemplate`] +| A base template with constructors to inherit. +| link:#Concrete[`Concrete`] +| Inherit the constructors of a concrete base. +| link:#Dependent[`Dependent`] +| Inherit the constructors of a base that depends on a template parameter. +| link:#FromPack[`FromPack`] +| Inherit the constructors of every base in a pack. +| link:#Mixin[`Mixin`] +| Inherit the constructors of a base that is a template parameter. +| link:#ViaAlias[`ViaAlias`] +| Inherit the constructors of a base named through an alias. +| link:#ViaMemberAlias[`ViaMemberAlias`] +| Inherit the constructors of a base named through a member alias. +|=== + + +=== Type Aliases + +[cols="1,4"] +|=== +| Name| Description +| link:#BaseAlias[`BaseAlias`] +| An alias of the base. +|=== + + +[#BaseAlias] +== BaseAlias + +An alias of the base. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseAlias = link:#Base[Base]; +---- + +[#Base] +== Base + +A base with constructors to inherit. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Base; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-2constructor-00[`Base`] [.small]#[constructor]# +| Constructors +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#Concrete[`Concrete`] +| Inherit the constructors of a concrete base. +| link:#ViaAlias[`ViaAlias`] +| Inherit the constructors of a base named through an alias. +|=== + +[#Base-2constructor-00] +== link:#Base[Base]::Base + +Constructors + +=== Synopses + +Declared in `<using‐inheriting‐constructor.cpp>` + +Construct an empty base. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +link:#Base-2constructor-0a[Base](); +---- + +[.small]#link:#Base-2constructor-0a[_» more..._]# + +A base with constructors to inherit. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +constexpr +link:#Base[Base](link:#Base[Base] const&) = default; +---- + +[.small]#link:#Base[_» more..._]# + +A base with constructors to inherit. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +constexpr +link:#Base[Base](link:#Base[Base]&&) = default; +---- + +[.small]#link:#Base[_» more..._]# + +Construct from a count. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +link:#Base-2constructor-09[Base](int value); +---- + +[.small]#link:#Base-2constructor-09[_» more..._]# + +[#Base-2constructor-0a] +== link:#Base[Base]::Base + +Construct an empty base. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +Base(); +---- + +[#Base-2constructor-09] +== link:#Base[Base]::Base + +Construct from a count. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +Base(int value); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *value* +| The value to construct from +|=== + +[#BaseTemplate] +== BaseTemplate + +A base template with constructors to inherit. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct BaseTemplate; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#BaseTemplate-2constructor-0a[`BaseTemplate`] [.small]#[constructor]# +| Constructors +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#Dependent[`Dependent`] +| Inherit the constructors of a base that depends on a template parameter. +| link:#ViaMemberAlias[`ViaMemberAlias`] +| Inherit the constructors of a base named through a member alias. +|=== + +[#BaseTemplate-2constructor-0a] +== link:#BaseTemplate[BaseTemplate]::BaseTemplate + +Constructors + +=== Synopses + +Declared in `<using‐inheriting‐constructor.cpp>` + +Construct an empty base. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +link:#BaseTemplate-2constructor-01[BaseTemplate](); +---- + +[.small]#link:#BaseTemplate-2constructor-01[_» more..._]# + +Construct from a value. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +link:#BaseTemplate-2constructor-05[BaseTemplate](T value); +---- + +[.small]#link:#BaseTemplate-2constructor-05[_» more..._]# + +[#BaseTemplate-2constructor-01] +== link:#BaseTemplate[BaseTemplate]::BaseTemplate + +Construct an empty base. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +BaseTemplate(); +---- + +[#BaseTemplate-2constructor-05] +== link:#BaseTemplate[BaseTemplate]::BaseTemplate + +Construct from a value. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +BaseTemplate(T value); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *value* +| The object to construct from +|=== + +[#Concrete] +== Concrete + +Inherit the constructors of a concrete base. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Concrete + : link:#Base[Base] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#Base[Base]` +| A base with constructors to inherit. +|=== + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Concrete-2constructor[`Base`] +| The constructors of `Base`. +|=== + + +[#Concrete-2constructor] +== link:#Concrete[Concrete]::Base + +The constructors of `Base`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using Base::Base; +---- + +=== Introduced Symbols + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-2constructor-09[`Base`] [.small]#[constructor]# +| Construct from a count. +|=== + +[#Dependent] +== Dependent + +Inherit the constructors of a base that depends on a template parameter. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct Dependent + : link:#BaseTemplate[BaseTemplate<T>] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#BaseTemplate[BaseTemplate<T>]` +| A base template with constructors to inherit. +|=== + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Dependent-BaseTemplate[`BaseTemplate`] +| The constructors of `BaseTemplate`. +|=== + + +[#Dependent-BaseTemplate] +== link:#Dependent[Dependent]::BaseTemplate + +The constructors of `BaseTemplate`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseTemplate<T>::BaseTemplate; +---- + +[#FromPack] +== FromPack + +Inherit the constructors of every base in a pack. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class... Bases> +struct FromPack + : Bases... +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `Bases...` +| +|=== + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#FromPack-Bases[`Bases`] +| The constructors of each of `Bases`. +|=== + + +[#FromPack-Bases] +== link:#FromPack[FromPack]::Bases + +The constructors of each of `Bases`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using Bases::Bases; +---- + +[#Mixin] +== Mixin + +Inherit the constructors of a base that is a template parameter. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class B> +struct Mixin + : B +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `B` +| +|=== + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Mixin-B[`B`] +| The constructors of `B`. +|=== + + +[#Mixin-B] +== link:#Mixin[Mixin]::B + +The constructors of `B`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using B::B; +---- + +[#ViaAlias] +== ViaAlias + +Inherit the constructors of a base named through an alias. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct ViaAlias + : link:#Base[Base] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#Base[Base]` +| A base with constructors to inherit. +|=== + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#ViaAlias-2constructor[`BaseAlias`] +| The constructors of `BaseAlias`. +|=== + + +[#ViaAlias-2constructor] +== link:#ViaAlias[ViaAlias]::BaseAlias + +The constructors of `BaseAlias`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseAlias::BaseAlias; +---- + +=== Introduced Symbols + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-2constructor-09[`Base`] [.small]#[constructor]# +| Construct from a count. +|=== + +[#ViaMemberAlias] +== ViaMemberAlias + +Inherit the constructors of a base named through a member alias. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct ViaMemberAlias + : link:#BaseTemplate[BaseTemplate<T>] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#BaseTemplate[BaseTemplate<T>]` +| A base template with constructors to inherit. +|=== + +=== Type Aliases + +[cols="1,4"] +|=== +| Name| Description +| link:#ViaMemberAlias-base_type-0c[`base_type`] +| The base class. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#ViaMemberAlias-base_type-06[`base_type`] +| The constructors of `base_type`. +|=== + + +[#ViaMemberAlias-base_type-0c] +== link:#ViaMemberAlias[ViaMemberAlias]::base_type + +The base class. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using base_type = link:#BaseTemplate[BaseTemplate<T>]; +---- + +[#ViaMemberAlias-base_type-06] +== link:#ViaMemberAlias[ViaMemberAlias]::base_type + +The constructors of `base_type`. + +=== Synopsis + +Declared in `<using‐inheriting‐constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using base_type::base_type; +---- + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/tests/golden/fixtures/symbols/using/using-inheriting-constructor.cpp b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.cpp new file mode 100644 index 00000000000..6c1fae4382a --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.cpp @@ -0,0 +1,80 @@ +// A using-declaration that inherits constructors is written with the name +// of the base class, and that is the name it is documented under. Clang +// stores it as a constructor of the derived class instead, and, when the +// base depends on a template parameter, as a constructor of a type with +// no class behind it at all. Both shapes are here, along with a base that +// is a template parameter, a pack of them (the synopsis doesn't show the +// ellipsis yet), and a base named through an alias. + +/// A base with constructors to inherit. +struct Base +{ + /// Construct an empty base. + Base(); + + /// Construct from a count. + explicit Base(int); +}; + +/// Inherit the constructors of a concrete base. +struct Concrete : Base +{ + /// The constructors of `Base`. + using Base::Base; +}; + +/// A base template with constructors to inherit. +template +struct BaseTemplate +{ + /// Construct an empty base. + BaseTemplate(); + + /// Construct from a value. + explicit BaseTemplate(T); +}; + +/// Inherit the constructors of a base that depends on a template parameter. +template +struct Dependent : BaseTemplate +{ + /// The constructors of `BaseTemplate`. + using BaseTemplate::BaseTemplate; +}; + +/// Inherit the constructors of a base that is a template parameter. +template +struct Mixin : B +{ + /// The constructors of `B`. + using B::B; +}; + +/// Inherit the constructors of every base in a pack. +template +struct FromPack : Bases... +{ + /// The constructors of each of `Bases`. + using Bases::Bases...; +}; + +/// An alias of the base. +using BaseAlias = Base; + +/// Inherit the constructors of a base named through an alias. +struct ViaAlias : Base +{ + /// The constructors of `BaseAlias`. + using BaseAlias::BaseAlias; +}; + +/// Inherit the constructors of a base named through a member alias. +template +struct ViaMemberAlias : BaseTemplate +{ + /// The base class. + using base_type = BaseTemplate; + + /// The constructors of `base_type`. + using base_type::base_type; +}; diff --git a/tests/golden/fixtures/symbols/using/using-inheriting-constructor.xml b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.xml new file mode 100644 index 00000000000..e3fc6157aa8 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.xml @@ -0,0 +1,1478 @@ + + + + index + namespace + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + regular + + 3UjRMqZBD848qFs8or2nyQX4AhB5 + 2QDQSSTt2u1SGtB1MPniUV22mgRU 37ak26eCioiUagg244czg7Tfferh 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd 35QU1wZVPUWr1pXrspYwH3zDPFvL 32CDyg3MZt8iEmqmwdTi2mvzXmDi 3F2TmbGGE7nBiVfrryiQtfcAs3po cZBDBbVSP1raE7JEdrQmZKQE2r9 + + + + BaseAlias + BaseAlias + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 62 + 1 + + + + + typedef + 3UjRMqZBD848qFs8or2nyQX4AhB5 + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + An alias of the base. + + + + + + + named + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + + + + Base + Base + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 10 + 1 + + + + record + 2QDQSSTt2u1SGtB1MPniUV22mgRU + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base with constructors to inherit. + + + + + struct + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ 3F2TmbGGE7nBiVfrryiQtfcAs3po + + + 6nxnBxu76i4CNTU56TEAdJaK7S3 + + + + + Base + 2constructor-00 + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 10 + 8 + + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 13 + 5 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 16 + 5 + + + + + overloads + 6nxnBxu76i4CNTU56TEAdJaK7S3 + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Constructors + + + + + constructor + 3Pfzhg3dXxXLRvN41S1xkrNgTffs 2pYCUC4g41YZueFgKj6bWPpt3cBY 2vUVyxM3mF2tPi3t95dyB6n2pMSt 37UmJk6nbWYMWgYzRfPMwFyFyaCE + + + named + + + identifier + void + + + void + + + + + Base + 2constructor-0a + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 13 + 5 + + + + + function + 3Pfzhg3dXxXLRvN41S1xkrNgTffs + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct an empty base. + + + + + + + named + + + identifier + void + + + void + + + constructor + + + + Base + 2constructor-09 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 16 + 5 + + + + + function + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + + + BaseTemplate + BaseTemplate + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 27 + 1 + + + + record + 37ak26eCioiUagg244czg7Tfferh + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base template with constructors to inherit. + + + + + struct + + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd cZBDBbVSP1raE7JEdrQmZKQE2r9 + + + 3JDmyzQ37eZsF6npDyoPBGmTfKyj + + + + + BaseTemplate + 2constructor-0a + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 31 + 5 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 34 + 5 + + + + + overloads + 3JDmyzQ37eZsF6npDyoPBGmTfKyj + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Constructors + + + + + constructor + KaKNMxm1d3HTHcsoM1AAUDZevwr 2HWftN9YUwLBCHBFitq5MTuxSMZK + + + named + + + identifier + void + + + void + + + + + BaseTemplate + 2constructor-01 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 31 + 5 + + + + + function + KaKNMxm1d3HTHcsoM1AAUDZevwr + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Construct an empty base. + + + + + + + named + + + identifier + void + + + void + + + constructor + + + + BaseTemplate + 2constructor-05 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 34 + 5 + + + + + function + 2HWftN9YUwLBCHBFitq5MTuxSMZK + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Construct from a value. + + + + + + param + + + text + The object to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + T + + + + + value + + + constructor + + + + Concrete + Concrete + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 20 + 1 + + + + record + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a concrete base. + + + + + struct + + + + + named + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 20 + 19 + + + + + + + 3WhC9Pjhrbyv5fLt2EvEjjP31NG + + + + + Base + 2constructor + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 23 + 5 + + + + + using + 3WhC9Pjhrbyv5fLt2EvEjjP31NG + public + regular + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ + + + brief + + + text + The constructors of + + + code + + + text + Base + + + + + text + . + + + + + normal + + + identifier + Base + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + + + Base + 2constructor-09 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 16 + 5 + + + + + function + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + + + Dependent + Dependent + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 38 + 1 + + + + record + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a base that depends on a template parameter. + + + + + struct + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 39 + 20 + + + + + + + dn6F1eQG618pBEQmkWGHTWVSTsi + + + + + BaseTemplate + BaseTemplate + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 42 + 5 + + + + + using + dn6F1eQG618pBEQmkWGHTWVSTsi + public + regular + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + brief + + + text + The constructors of + + + code + + + text + BaseTemplate + + + + + text + . + + + + + normal + + + identifier + BaseTemplate + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + FromPack + FromPack + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 54 + 1 + + + + record + 35QU1wZVPUWr1pXrspYwH3zDPFvL + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of every base in a pack. + + + + + struct + + + + + + named + + + + identifier + Bases + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 55 + 19 + + + + + + + 2nP71ndWjBiNtEFQrcHsEtbrCkiv + + + + + Bases + Bases + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 58 + 5 + + + + + using + 2nP71ndWjBiNtEFQrcHsEtbrCkiv + public + regular + 35QU1wZVPUWr1pXrspYwH3zDPFvL + + + brief + + + text + The constructors of each of + + + code + + + text + Bases + + + + + text + . + + + + + normal + + + identifier + Bases + + + identifier + Bases + + + + + + + Mixin + Mixin + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 46 + 1 + + + + record + 32CDyg3MZt8iEmqmwdTi2mvzXmDi + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a base that is a template parameter. + + + + + struct + + + + + + named + + + identifier + B + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 47 + 16 + + + + + + + 3EY2BnsTc6yb29nn4r17yvpcecQf + + + + + B + B + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 50 + 5 + + + + + using + 3EY2BnsTc6yb29nn4r17yvpcecQf + public + regular + 32CDyg3MZt8iEmqmwdTi2mvzXmDi + + + brief + + + text + The constructors of + + + code + + + text + B + + + + + text + . + + + + + normal + + + identifier + B + + + identifier + B + + + + + + + ViaAlias + ViaAlias + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 65 + 1 + + + + record + 3F2TmbGGE7nBiVfrryiQtfcAs3po + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a base named through an alias. + + + + + struct + + + + + named + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 65 + 19 + + + + + + + 417U8DJgNGXkLApqRXwWV2h1A6hs + + + + + BaseAlias + 2constructor + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 68 + 5 + + + + + using + 417U8DJgNGXkLApqRXwWV2h1A6hs + public + regular + 3F2TmbGGE7nBiVfrryiQtfcAs3po + + + brief + + + text + The constructors of + + + code + + + text + BaseAlias + + + + + text + . + + + + + normal + + + identifier + BaseAlias + + + identifier + 3UjRMqZBD848qFs8or2nyQX4AhB5 + BaseAlias + + + + + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + + + Base + 2constructor-09 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 16 + 5 + + + + + function + 37UmJk6nbWYMWgYzRfPMwFyFyaCE + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Construct from a count. + + + + + + param + + + text + The value to construct from + + + value + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + value + + + constructor + + + + ViaMemberAlias + ViaMemberAlias + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 72 + 1 + + + + record + cZBDBbVSP1raE7JEdrQmZKQE2r9 + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Inherit the constructors of a base named through a member alias. + + + + + struct + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + public + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 73 + 25 + + + + + + + 3rmd8cdPSvGg8yPXGxtwp1mUB83m + 2SQWTaajKJXzHDBNUyoHwxs2PHR1 + + + + + base_type + base_type-0c + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 76 + 5 + + + + + typedef + 3rmd8cdPSvGg8yPXGxtwp1mUB83m + public + regular + cZBDBbVSP1raE7JEdrQmZKQE2r9 + + + brief + + + text + The base class. + + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + + base_type + base_type-06 + + + + using-inheriting-constructor.cpp + using-inheriting-constructor.cpp + 79 + 5 + + + + + using + 2SQWTaajKJXzHDBNUyoHwxs2PHR1 + public + regular + cZBDBbVSP1raE7JEdrQmZKQE2r9 + + + brief + + + text + The constructors of + + + code + + + text + base_type + + + + + text + . + + + + + normal + + + identifier + base_type + + + identifier + 3rmd8cdPSvGg8yPXGxtwp1mUB83m + base_type + + + + + + diff --git a/tests/golden/fixtures/symbols/using/using-inheriting-constructor.yml b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.yml new file mode 100644 index 00000000000..4507c7d09b6 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inheriting-constructor.yml @@ -0,0 +1 @@ +generator: [xml, adoc] diff --git a/tests/golden/fixtures/symbols/using/using-member-function.xml b/tests/golden/fixtures/symbols/using/using-member-function.xml index 53697f9e0dd..ffcaebb2d88 100644 --- a/tests/golden/fixtures/symbols/using/using-member-function.xml +++ b/tests/golden/fixtures/symbols/using/using-member-function.xml @@ -908,8 +908,8 @@ - U - U-0a + A + A @@ -941,7 +941,7 @@ identifier - U + A identifier @@ -953,8 +953,8 @@ - U - U-01b + B + B @@ -986,7 +986,7 @@ identifier - U + B identifier @@ -998,8 +998,8 @@ - U - U-01d + C + C @@ -1031,7 +1031,7 @@ identifier - U + C identifier @@ -1043,8 +1043,8 @@ - U - U-0c + D + D @@ -1076,7 +1076,7 @@ identifier - U + D identifier @@ -1088,8 +1088,8 @@ - U - U-04 + E + E @@ -1121,7 +1121,7 @@ identifier - U + E identifier @@ -1133,8 +1133,8 @@ - U - U-06 + F + F-06 @@ -1166,7 +1166,7 @@ identifier - U + F identifier From f7215bc9f4c5c009ee6f21548a4e0e3c5a082062 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Tue, 22 Sep 2026 11:45:16 +0200 Subject: [PATCH 2/3] fix: an operator named by a using-declaration gets a safe anchor This fixes a bug for which a using-declaration that names an operator produced a page no link could reach, and sometimes no page at all. `operator[]` broke the link, because AsciiDoc ends a link target at the first bracket. `operator->` and `operator<=>` broke more quietly, because AsciiDoc rewrites `->` and `=>` inside the target as arrow characters, and the link then points at a page that does not exist. `operator/` put the page inside a directory of its own, because a slash is a path separator. A conversion such as `operator bool` got a space in the file name and in the link. On Windows a file name cannot hold `"`, `*`, `<`, `>` or `|` at all, so every operator spelled with one of those could not be opened and generation stopped with an error. The anchor is what a page file name and a link are built from, so it has to be a plain identifier. A using-declaration does not make one up: it takes the anchor of its first shadow declaration, which is safe already, an operator having gone through the table of safe operator names. There are no shadow declarations when the base depends on a template parameter, since the name cannot be looked up before the template is instantiated, nor when the filters removed the target. The anchor then fell back to the declaration's own name, punctuation and all. All of them now take the anchor the operator itself would get (e.g. `operator_subs` for `operator[]`), and a conversion takes the one that every conversion shares. A literal operator such as `operator""_km` drops its double quotes, as the anchor of the literal operator itself already does. I've added tests. Fixes #1276. --- .../Metadata/Finalizers/AnchorFinalizer.cpp | 69 +- .../symbols/using/using-filtered-base.cpp | 23 + .../symbols/using/using-filtered-base.xml | 320 ++++- .../symbols/using/using-filtered-base.yml | 1 + .../using/using-inherited-operator.adoc | 339 +++++ .../using/using-inherited-operator.cpp | 48 + .../using/using-inherited-operator.xml | 1087 +++++++++++++++++ .../using/using-inherited-operator.yml | 1 + 8 files changed, 1859 insertions(+), 29 deletions(-) create mode 100644 tests/golden/fixtures/symbols/using/using-inherited-operator.adoc create mode 100644 tests/golden/fixtures/symbols/using/using-inherited-operator.cpp create mode 100644 tests/golden/fixtures/symbols/using/using-inherited-operator.xml create mode 100644 tests/golden/fixtures/symbols/using/using-inherited-operator.yml diff --git a/src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp b/src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp index fe905c9545c..53aed105d1d 100644 --- a/src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp +++ b/src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) // Copyright (c) 2026 Alan de Freitas (alandefreitas@gmail.com) +// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -27,23 +28,23 @@ namespace mrdocs { namespace { +// All valid C++ identifiers begin with an underscore or +// alphabetic character, so a numeric prefix ensures no +// conflicts. +constexpr +std::string_view +func_reserved[] = { + "2function", + "2constructor", + "2conversion", + "2destructor" +}; + std::string getUnnamedInfoName(Symbol const& I) { - // All valid c++ identifiers begin with - // an underscore or alphabetic character, - // so a numeric prefix ensures no conflicts if (I.isFunction() || I.isOverloads()) { - static - constexpr - std::string_view - func_reserved[] = { - "2function", - "2constructor", - "2conversion", - "2destructor" - }; std::size_t func_idx = 0; if (auto const* FI = I.asFunctionPtr()) { @@ -82,6 +83,39 @@ getUnnamedInfoName(Symbol const& I) return res; } +// A name without the double quotes of a literal operator, `operator""_x`, +// which are not URL-safe. +std::string +withoutDoubleQuotes(std::string_view name) +{ + std::string result(name); + std::erase(result, '"'); + return result; +} + +// The anchor of a using-declaration with no target to take one from: the +// safe name of an operator, the name that every conversion shares, or the +// name itself. +std::string +usingAnchorName(std::string_view name) +{ + std::string result; + if (OperatorKind const kind = getOperatorKind(name); + kind != OperatorKind::None) + { + result = getSafeOperatorName(kind, true); + } + else if (name.starts_with("operator ")) + { + result = func_reserved[to_underlying(FunctionClass::Conversion)]; + } + else + { + result = withoutDoubleQuotes(name); + } + return result; +} + // Computes each symbol's unqualified, URL-safe legible name, unique among // its siblings (siblings that would collide are disambiguated with a // suffix taken from the SymbolID). This is a build-time helper for the @@ -233,15 +267,7 @@ class LegibleNameTable { return getUnnamedInfoName(t); } - // User-defined literal operators (operator""_x) carry a - // double quote in their name, which is not URL-safe; strip - // it so the anchor stays a plain identifier (operator_x). - if (t.Name.find('"') != std::string::npos) - { - std::string safe(t.Name); - std::erase(safe, '"'); - return safe; - } + return withoutDoubleQuotes(t.Name); } else if constexpr(T::isUsing()) { @@ -249,6 +275,7 @@ class LegibleNameTable { return getRawUnqualified(t.ShadowDeclarations.front()); } + return usingAnchorName(t.Name); } return t.Name; }); diff --git a/tests/golden/fixtures/symbols/using/using-filtered-base.cpp b/tests/golden/fixtures/symbols/using/using-filtered-base.cpp index 2e1076d884f..cacbd081cb1 100644 --- a/tests/golden/fixtures/symbols/using/using-filtered-base.cpp +++ b/tests/golden/fixtures/symbols/using/using-filtered-base.cpp @@ -13,6 +13,9 @@ struct Detail /// A member of the detail base. int hidden() const; + + /// Indexed access. + int operator[](int i) const; }; /// A base excluded from extraction. @@ -23,6 +26,9 @@ struct Excluded /// A member of the excluded base. int gone() const; + + /// Convert to bool. + explicit operator bool() const; }; /// Re-export members of each. @@ -39,6 +45,23 @@ struct Reexport : private Detail, private Excluded /// Re-exported from the excluded base. using Excluded::gone; + + /// Indexed access, re-exported from the implementation-defined base. + using Detail::operator[]; + + /// Conversion, re-exported from the excluded base. + using Excluded::operator bool; }; +/// Implementation details. +namespace detail { + +/// A literal operator for lengths in kilometers. +int operator""_km(unsigned long long); + +} // namespace detail + +/// A literal operator re-exported from the implementation-defined namespace. +using detail::operator""_km; + } // namespace ns diff --git a/tests/golden/fixtures/symbols/using/using-filtered-base.xml b/tests/golden/fixtures/symbols/using/using-filtered-base.xml index ac037dac532..6f0552edd56 100644 --- a/tests/golden/fixtures/symbols/using/using-filtered-base.xml +++ b/tests/golden/fixtures/symbols/using/using-filtered-base.xml @@ -27,12 +27,106 @@ regular 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + 34VGGLmMfEu4bsPZE7jico5h3kC8 3SGcYLppJA2rdQ8vTWo5rKV22sPK 3c5RuWKWcxGpq8T1Vzzp41kueCYr 3D3Ncqr4SiKkKtsbeUAFYeJcB64v + 2CunHkePV9ABNwqteAiKUwNEeQgm + + detail + detail-09 + + + + using-filtered-base.cpp + using-filtered-base.cpp + 57 + 1 + + + + + namespace + 34VGGLmMfEu4bsPZE7jico5h3kC8 + implementation-defined + M24JSbN7468AETx5E9NkwAwd79o + + + brief + + + text + Implementation details. + + + + + + 4Qg6kVa8tGDGXJCixSYeFfJYYact + + + + operator""_km + operator_km + + + + using-filtered-base.cpp + using-filtered-base.cpp + 60 + 1 + + + + + function + 4Qg6kVa8tGDGXJCixSYeFfJYYact + implementation-defined + 34VGGLmMfEu4bsPZE7jico5h3kC8 + + + brief + + + text + A literal operator for lengths in kilometers. + + + + + + + named + + + identifier + int + + + int + + + + + + + named + + + identifier + unsigned long long + + + unsigned long long + + + + + normal + Detail - Detail + Detail-0a using-filtered-base.cpp @@ -60,7 +154,7 @@ struct - 3yhiTTQBtLW1uvaK5JkQisLQff6b 2pZPcSxiLCTW81Ep9WcR6CSNvBe7 + 3yhiTTQBtLW1uvaK5JkQisLQff6b 2pZPcSxiLCTW81Ep9WcR6CSNvBe7 3q5ZWJ5mVYKDyNPD6xQiKt1z2Arn @@ -395,6 +489,82 @@ + + operator[] + operator_subs + + + + using-filtered-base.cpp + using-filtered-base.cpp + 18 + 5 + + + + + function + 3q5ZWJ5mVYKDyNPD6xQiKt1z2Arn + public + implementation-defined + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + named + + + identifier + int + + + int + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + Reexport Reexport @@ -402,7 +572,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 29 + 35 1 @@ -425,7 +595,7 @@ struct - 3cF5rVRHGaz8c3pRdjTbmftK8jFK 2L4rQr1ZEKwSCSeK9UHJVVQb1FT9 npRa45X8z2orh68KkLG7cQmGXz1 3a9zMXoj73M9zQcYYmsCqtCxtEE4 + 3cF5rVRHGaz8c3pRdjTbmftK8jFK 2L4rQr1ZEKwSCSeK9UHJVVQb1FT9 npRa45X8z2orh68KkLG7cQmGXz1 3a9zMXoj73M9zQcYYmsCqtCxtEE4 zkXnScWDKddfVT6MZgD35y1hLGa 365kYrAQ6Wcu73hMR89AAXANH5bm @@ -437,7 +607,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 32 + 38 5 @@ -482,7 +652,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 35 + 41 5 @@ -527,7 +697,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 41 + 47 5 @@ -572,7 +742,7 @@ using-filtered-base.cpp using-filtered-base.cpp - 38 + 44 5 @@ -609,4 +779,138 @@ + + operator bool + 2conversion + + + + using-filtered-base.cpp + using-filtered-base.cpp + 53 + 5 + + + + + using + zkXnScWDKddfVT6MZgD35y1hLGa + public + regular + 3D3Ncqr4SiKkKtsbeUAFYeJcB64v + + + brief + + + text + Conversion, re-exported from the excluded base. + + + + + normal + + + identifier + operator bool + + + identifier + 3c5RuWKWcxGpq8T1Vzzp41kueCYr + Excluded + + + + + + + operator[] + operator_subs + + + + using-filtered-base.cpp + using-filtered-base.cpp + 50 + 5 + + + + + using + 365kYrAQ6Wcu73hMR89AAXANH5bm + public + regular + 3D3Ncqr4SiKkKtsbeUAFYeJcB64v + + + brief + + + text + Indexed access, re-exported from the implementation-defined base. + + + + + normal + + + identifier + operator[] + + + identifier + 3SGcYLppJA2rdQ8vTWo5rKV22sPK + Detail + + + + + + + operator""_km + operator_km + + + + using-filtered-base.cpp + using-filtered-base.cpp + 65 + 1 + + + + + using + 2CunHkePV9ABNwqteAiKUwNEeQgm + regular + M24JSbN7468AETx5E9NkwAwd79o + + + brief + + + text + A literal operator re-exported from the implementation-defined namespace. + + + + + normal + + + identifier + operator""_km + + + identifier + 34VGGLmMfEu4bsPZE7jico5h3kC8 + detail + + + + + diff --git a/tests/golden/fixtures/symbols/using/using-filtered-base.yml b/tests/golden/fixtures/symbols/using/using-filtered-base.yml index 2d0d17608cc..1898c1355c5 100644 --- a/tests/golden/fixtures/symbols/using/using-filtered-base.yml +++ b/tests/golden/fixtures/symbols/using/using-filtered-base.yml @@ -1,4 +1,5 @@ implementation-defined: - 'ns::Detail' + - 'ns::detail' exclude-symbols: - 'ns::Excluded' diff --git a/tests/golden/fixtures/symbols/using/using-inherited-operator.adoc b/tests/golden/fixtures/symbols/using/using-inherited-operator.adoc new file mode 100644 index 00000000000..fa35c18ad1f --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inherited-operator.adoc @@ -0,0 +1,339 @@ += Reference +:mrdocs: + +[#index] +== Global index + +=== Types + +[cols="1,4"] +|=== +| Name| Description +| link:#Base[`Base`] +| A base with operators to re‐export. +| link:#BaseTemplate[`BaseTemplate`] +| A base template with operators to re‐export. +| link:#Concrete[`Concrete`] +| Re‐export the operators of a concrete base. +| link:#Dependent[`Dependent`] +| Re‐export the operators of a base that depends on a template parameter. +|=== + + +[#Base] +== Base + +A base with operators to re‐export. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Base; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-operator_subs[`operator[]`] +| Indexed access. +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#Concrete[`Concrete`] +| Re‐export the operators of a concrete base. +|=== + +[#Base-operator_subs] +== link:#Base[Base]::operator[] + +Indexed access. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +int& +operator[](int i); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *i* +| The right operand +|=== + +[#BaseTemplate] +== BaseTemplate + +A base template with operators to re‐export. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct BaseTemplate; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#BaseTemplate-operator_call[`operator()`] +| Call. +| link:#BaseTemplate-operator_subs[`operator[]`] +| Indexed access. +| link:#BaseTemplate-2conversion[`operator bool`] +| Convert to bool. +|=== + + +=== Derived Classes + +[cols="1,4"] +|=== +| Name| Description +| link:#Dependent[`Dependent`] +| Re‐export the operators of a base that depends on a template parameter. +|=== + +[#BaseTemplate-operator_call] +== link:#BaseTemplate[BaseTemplate]::operator() + +Call. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +operator()(); +---- + +[#BaseTemplate-operator_subs] +== link:#BaseTemplate[BaseTemplate]::operator[] + +Indexed access. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +T& +operator[](int i); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *i* +| The right operand +|=== + +[#BaseTemplate-2conversion] +== link:#BaseTemplate[BaseTemplate]::operator bool + +Convert to bool. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +operator bool() const; +---- + +=== Return Value + +The object converted to `bool` + +[#Concrete] +== Concrete + +Re‐export the operators of a concrete base. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Concrete + : link:#Base[Base] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#Base[Base]` +| A base with operators to re‐export. +|=== + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-operator_subs[`operator[]`] +| Indexed access. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Concrete-operator_subs[`operator[]`] +| Indexed access, re‐exported. +|=== + + +[#Concrete-operator_subs] +== link:#Concrete[Concrete]::operator[] + +Indexed access, re‐exported. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using Base::operator[]; +---- + +=== Introduced Symbols + +[cols="1,4"] +|=== +| Name| Description +| link:#Base-operator_subs[`operator[]`] +| Indexed access. +|=== + +[#Dependent] +== Dependent + +Re‐export the operators of a base that depends on a template parameter. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +template<class T> +struct Dependent + : link:#BaseTemplate[BaseTemplate<T>] +---- + +=== Base Classes + +[cols="1,4"] +|=== +| Name| Description +| `link:#BaseTemplate[BaseTemplate<T>]` +| A base template with operators to re‐export. +|=== + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#BaseTemplate-operator_call[`operator()`] +| Call. +| link:#BaseTemplate-operator_subs[`operator[]`] +| Indexed access. +| link:#BaseTemplate-2conversion[`operator bool`] +| Convert to bool. +|=== + + +=== Using Declarations + +[cols="1,4"] +|=== +| Name| Description +| link:#Dependent-2conversion[`operator bool`] +| Conversion, re‐exported. +| link:#Dependent-operator_call[`operator()`] +| Call, re‐exported. +| link:#Dependent-operator_subs[`operator[]`] +| Indexed access, re‐exported. +|=== + + +[#Dependent-2conversion] +== link:#Dependent[Dependent]::operator bool + +Conversion, re‐exported. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseTemplate<T>::operator bool; +---- + +[#Dependent-operator_call] +== link:#Dependent[Dependent]::operator() + +Call, re‐exported. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseTemplate<T>::operator(); +---- + +[#Dependent-operator_subs] +== link:#Dependent[Dependent]::operator[] + +Indexed access, re‐exported. + +=== Synopsis + +Declared in `<using‐inherited‐operator.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using BaseTemplate<T>::operator[]; +---- + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/tests/golden/fixtures/symbols/using/using-inherited-operator.cpp b/tests/golden/fixtures/symbols/using/using-inherited-operator.cpp new file mode 100644 index 00000000000..40d41db2125 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inherited-operator.cpp @@ -0,0 +1,48 @@ +// A using-declaration off a base that depends on a template parameter +// names nothing until the template is instantiated, so the anchor cannot +// be taken from what it introduces, and the name it is written with may +// contain characters that are invalid for a file name or URL. The same +// declarations off a concrete base are here for comparison, since those +// name something already and take its anchor. + +/// A base template with operators to re-export. +template +struct BaseTemplate +{ + /// Indexed access. + T& operator[](int i); + + /// Call. + void operator()(); + + /// Convert to bool. + explicit operator bool() const; +}; + +/// Re-export the operators of a base that depends on a template parameter. +template +struct Dependent : BaseTemplate +{ + /// Indexed access, re-exported. + using BaseTemplate::operator[]; + + /// Call, re-exported. + using BaseTemplate::operator(); + + /// Conversion, re-exported. + using BaseTemplate::operator bool; +}; + +/// A base with operators to re-export. +struct Base +{ + /// Indexed access. + int& operator[](int i); +}; + +/// Re-export the operators of a concrete base. +struct Concrete : Base +{ + /// Indexed access, re-exported. + using Base::operator[]; +}; diff --git a/tests/golden/fixtures/symbols/using/using-inherited-operator.xml b/tests/golden/fixtures/symbols/using/using-inherited-operator.xml new file mode 100644 index 00000000000..58b9c5f4946 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inherited-operator.xml @@ -0,0 +1,1087 @@ + + + + index + namespace + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + regular + + 2QDQSSTt2u1SGtB1MPniUV22mgRU 37ak26eCioiUagg244czg7Tfferh 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + + Base + Base + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 37 + 1 + + + + record + 2QDQSSTt2u1SGtB1MPniUV22mgRU + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base with operators to re-export. + + + + + struct + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ + + + 2pPRcUtq3EtjgoerUG48CgVNMMgu + + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 40 + 5 + + + + + function + 2pPRcUtq3EtjgoerUG48CgVNMMgu + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + lvalue-reference + + + named + + + identifier + int + + + int + + + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + + BaseTemplate + BaseTemplate + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 9 + 1 + + + + record + 37ak26eCioiUagg244czg7Tfferh + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A base template with operators to re-export. + + + + + struct + + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + 467wGLZsncRdHMLAyiZkSZtAXH6p 3HPkJqCTjgBUZzPrES16nAmRnyXV 2ceG5zdS4ZDcnu8iLmKinrVXatyn + + + + + operator() + operator_call + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 16 + 5 + + + + + function + 467wGLZsncRdHMLAyiZkSZtAXH6p + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Call. + + + + + + + named + + + identifier + void + + + void + + + normal + () + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 13 + 5 + + + + + function + 3HPkJqCTjgBUZzPrES16nAmRnyXV + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + lvalue-reference + + + named + + + identifier + T + + + + + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + + operator bool + 2conversion + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 19 + 5 + + + + + function + 2ceG5zdS4ZDcnu8iLmKinrVXatyn + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Convert to bool. + + + + + + returns + + + text + The object converted to + + + code + + + text + bool + + + + + + + + + + named + + + identifier + bool + + + bool + + + conversion + + + + + Concrete + Concrete + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 44 + 1 + + + + record + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Re-export the operators of a concrete base. + + + + + struct + + + + + named + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + public + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 44 + 19 + + + + + + + 2pPRcUtq3EtjgoerUG48CgVNMMgu + 71mgME8nEUx1Eneje2R3BnE2E5h + + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 40 + 5 + + + + + function + 2pPRcUtq3EtjgoerUG48CgVNMMgu + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + lvalue-reference + + + named + + + identifier + int + + + int + + + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 47 + 5 + + + + + using + 71mgME8nEUx1Eneje2R3BnE2E5h + public + regular + 4Ncp9DFsAbF7SPAFKHEHFu5aMkrZ + + + brief + + + text + Indexed access, re-exported. + + + + + normal + + + identifier + operator[] + + + identifier + 2QDQSSTt2u1SGtB1MPniUV22mgRU + Base + + + + + 2pPRcUtq3EtjgoerUG48CgVNMMgu + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 40 + 5 + + + + + function + 2pPRcUtq3EtjgoerUG48CgVNMMgu + public + regular + 2QDQSSTt2u1SGtB1MPniUV22mgRU + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + lvalue-reference + + + named + + + identifier + int + + + int + + + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + + Dependent + Dependent + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 23 + 1 + + + + record + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Re-export the operators of a base that depends on a template parameter. + + + + + struct + + + + + + named + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + public + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 24 + 20 + + + + + + + 467wGLZsncRdHMLAyiZkSZtAXH6p 3HPkJqCTjgBUZzPrES16nAmRnyXV 2ceG5zdS4ZDcnu8iLmKinrVXatyn + 22BY8cwUQvXeqhMv9AGX8NxvUZ7N 4G3pj7dm3ooJm1WfbAPBNne2xGHD 3cTDdC9cj4yLjbEy1e9NFQnhh7R9 + + + + + operator() + operator_call + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 16 + 5 + + + + + function + 467wGLZsncRdHMLAyiZkSZtAXH6p + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Call. + + + + + + + named + + + identifier + void + + + void + + + normal + () + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 13 + 5 + + + + + function + 3HPkJqCTjgBUZzPrES16nAmRnyXV + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Indexed access. + + + + + + param + + + text + The right operand + + + i + + + + + + lvalue-reference + + + named + + + identifier + T + + + + + + + + + + + named + + + identifier + int + + + int + + + i + + + normal + [] + + + + operator bool + 2conversion + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 19 + 5 + + + + + function + 2ceG5zdS4ZDcnu8iLmKinrVXatyn + public + regular + 37ak26eCioiUagg244czg7Tfferh + + + brief + + + text + Convert to bool. + + + + + + returns + + + text + The object converted to + + + code + + + text + bool + + + + + + + + + + named + + + identifier + bool + + + bool + + + conversion + + + + + operator bool + 2conversion + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 33 + 5 + + + + + using + 22BY8cwUQvXeqhMv9AGX8NxvUZ7N + public + regular + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + brief + + + text + Conversion, re-exported. + + + + + normal + + + identifier + operator bool + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + operator() + operator_call + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 30 + 5 + + + + + using + 4G3pj7dm3ooJm1WfbAPBNne2xGHD + public + regular + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + brief + + + text + Call, re-exported. + + + + + normal + + + identifier + operator() + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + + operator[] + operator_subs + + + + using-inherited-operator.cpp + using-inherited-operator.cpp + 27 + 5 + + + + + using + 3cTDdC9cj4yLjbEy1e9NFQnhh7R9 + public + regular + 2hZiaQRRxm9fcFu3nJxjHCTUM9Yd + + + brief + + + text + Indexed access, re-exported. + + + + + normal + + + identifier + operator[] + + + specialization + 37ak26eCioiUagg244czg7Tfferh + BaseTemplate + + + type + + + named + + + identifier + T + + + + + + + + + + + + diff --git a/tests/golden/fixtures/symbols/using/using-inherited-operator.yml b/tests/golden/fixtures/symbols/using/using-inherited-operator.yml new file mode 100644 index 00000000000..4507c7d09b6 --- /dev/null +++ b/tests/golden/fixtures/symbols/using/using-inherited-operator.yml @@ -0,0 +1 @@ +generator: [xml, adoc] From a4a8a13ac7efcc351988675d21a2d1faac694d77 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Wed, 21 Oct 2026 09:31:34 +0200 Subject: [PATCH 3/3] fix: within a class, its name refers to the class, not to its constructor A reference to a class, written in the doc comment of one of its own members, resolved to the class's constructor: the `@ref Widget` of a member function of `Widget` linked to `Widget()`, while the same reference from outside the class linked to `Widget`. Lookup searches the members of a class before the enclosing scopes, and a constructor has the name of its class, so it matched first. In C++, a constructor has no name that lookup finds: within `Widget`, `Widget` names the class. Only after a qualifier that names the class does a name refer to the constructors, when it is the name of the class or repeats the qualifier, as in `Widget::Widget`, or `Alias::Alias` for `using Alias = Widget;`. We now follow the same rule. The second form didn't resolve at all before, as the class has no member named `Alias`. I've added tests. Fixes #1359. --- include/mrdocs/Corpus.hpp | 1 + src/mrdocs/Corpus.cpp | 20 +- .../javadoc/ref/class-name-in-member.adoc | 308 +++++++ .../javadoc/ref/class-name-in-member.cpp | 44 + .../javadoc/ref/class-name-in-member.xml | 784 ++++++++++++++++++ .../javadoc/ref/class-name-in-member.yml | 1 + 6 files changed, 1156 insertions(+), 2 deletions(-) create mode 100644 tests/golden/fixtures/javadoc/ref/class-name-in-member.adoc create mode 100644 tests/golden/fixtures/javadoc/ref/class-name-in-member.cpp create mode 100644 tests/golden/fixtures/javadoc/ref/class-name-in-member.xml create mode 100644 tests/golden/fixtures/javadoc/ref/class-name-in-member.yml diff --git a/include/mrdocs/Corpus.hpp b/include/mrdocs/Corpus.hpp index 9235c66d8ca..e34c3e81dbc 100644 --- a/include/mrdocs/Corpus.hpp +++ b/include/mrdocs/Corpus.hpp @@ -491,6 +491,7 @@ class MRDOCS_VISIBLE lookupImpl( SymbolID const& contextId, ParsedRefComponent const& component, + ParsedRefComponent const* qualifier, ParsedRef const& ref, bool checkParameters) const; diff --git a/src/mrdocs/Corpus.cpp b/src/mrdocs/Corpus.cpp index 9e75ca367b9..fd99e851887 100644 --- a/src/mrdocs/Corpus.cpp +++ b/src/mrdocs/Corpus.cpp @@ -885,7 +885,10 @@ lookupImpl( { ParsedRefComponent const& component = ref.Components[i]; bool const isLast = i == ref.Components.size() - 1; - curContext = self.lookupImpl(curContext->id, component, ref, isLast); + ParsedRefComponent const* const qualifier = + i == 0 ? nullptr : &ref.Components[i - 1]; + curContext = self.lookupImpl( + curContext->id, component, qualifier, ref, isLast); if (!curContext) { break; @@ -909,6 +912,7 @@ Corpus:: lookupImpl( SymbolID const& contextId, ParsedRefComponent const& component, + ParsedRefComponent const* qualifier, ParsedRef const& ref, bool const checkParameters) const { @@ -929,6 +933,14 @@ lookupImpl( } Symbol const& context = *contextPtr; + // A constructor has no name of its own: within `Widget`, `Widget` names + // the class. Only after a qualifier naming the class does a name refer + // to the constructors, when it is the name of the class or repeats the + // qualifier: `Widget::Widget`, or `Alias::Alias` for an alias of it. + bool const namesConstructor = + qualifier && context.isRecord() && + (component.Name == context.Name || component.Name == qualifier->Name); + // 2. Get a list of members report::trace(" Finding members of context '{}'", contextPtr->Name); llvm::SmallVector memberIDs; @@ -1006,6 +1018,10 @@ lookupImpl( MRDOCS_CHECK_OR(M.FuncClass == FunctionClass::Conversion, matchRes); MRDOCS_CHECK_OR(component.ConversionType == M.ReturnType, matchRes); } + else if (M.FuncClass == FunctionClass::Constructor) + { + MRDOCS_CHECK_OR(namesConstructor, matchRes); + } else { MRDOCS_CHECK_OR(member.Name == component.Name, matchRes); @@ -1130,7 +1146,7 @@ lookupImpl( MRDOCS_CHECK_OR_CONTINUE(memberPtr); Symbol const& member = *memberPtr; MRDOCS_CHECK_OR_CONTINUE(isTransparent(member)); - if (Symbol const* r = lookupImpl(member.id, component, ref, checkParameters)) + if (Symbol const* r = lookupImpl(member.id, component, qualifier, ref, checkParameters)) { return r; } diff --git a/tests/golden/fixtures/javadoc/ref/class-name-in-member.adoc b/tests/golden/fixtures/javadoc/ref/class-name-in-member.adoc new file mode 100644 index 00000000000..be1ff51e8b3 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/class-name-in-member.adoc @@ -0,0 +1,308 @@ += Reference +:mrdocs: + +[#index] +== Global index + +=== Types + +[cols="1,4"] +|=== +| Name| Description +| link:#Gadget[`Gadget`] +| A gadget, with overloaded constructors. +| link:#Widget[`Widget`] +| A widget. +|=== + + +=== Type Aliases + +[cols="1,4"] +|=== +| Name| Description +| link:#WidgetAlias[`WidgetAlias`] +| Another name for link:#Widget[`Widget`]. +|=== + + +=== Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#make[`make`] +| Make one. See link:#Widget-2constructor[`WidgetAlias::Widget`] and link:#Widget-2constructor[`WidgetAlias::WidgetAlias`]. +| link:#use[`use`] +| Use one. See link:#Widget[`Widget`]. +|=== + + +[#WidgetAlias] +== WidgetAlias + +Another name for link:#Widget[`Widget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +using WidgetAlias = link:#Widget[Widget]; +---- + +[#Gadget] +== Gadget + +A gadget, with overloaded constructors. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Gadget; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Gadget-2constructor-0d[`Gadget`] [.small]#[constructor]# +| Constructors +| link:#Gadget-reset[`reset`] +| Reset it. See link:#Gadget-2constructor-0d[`Gadget::Gadget`]. +| link:#Gadget-resize[`resize`] +| Resize it. See `Gadget`. +|=== + + +[#Gadget-2constructor-0d] +== link:#Gadget[Gadget]::Gadget + +Constructors + +=== Synopses + +Declared in `<class‐name‐in‐member.cpp>` + +Construct an empty gadget. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +link:#Gadget-2constructor-0e[Gadget](); +---- + +[.small]#link:#Gadget-2constructor-0e[_» more..._]# + +Construct a gadget of a given size. + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +link:#Gadget-2constructor-06[Gadget](int n); +---- + +[.small]#link:#Gadget-2constructor-06[_» more..._]# + +[#Gadget-2constructor-0e] +== link:#Gadget[Gadget]::Gadget + +Construct an empty gadget. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +Gadget(); +---- + +[#Gadget-2constructor-06] +== link:#Gadget[Gadget]::Gadget + +Construct a gadget of a given size. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +explicit +Gadget(int n); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *n* +| The value to construct from +|=== + +[#Gadget-reset] +== link:#Gadget[Gadget]::reset + +Reset it. See link:#Gadget-2constructor-0d[`Gadget::Gadget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +reset(); +---- + +[#Gadget-resize] +== link:#Gadget[Gadget]::resize + +Resize it. See link:#Gadget[`Gadget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +resize(int n); +---- + +[#Widget] +== Widget + +A widget. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct Widget; +---- + +=== Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#Widget-2constructor[`Widget`] [.small]#[constructor]# +| Construct an empty widget. +| link:#Widget-reset[`reset`] +| Reset it. See link:#Widget-2constructor[`Widget::Widget`]. +| link:#Widget-resize[`resize`] +| Resize it. See `Widget`. +|=== + + +=== Non-Member Functions + +[cols="1,4"] +|=== +| Name| Description +| link:#make[`make`] +| Make one. See link:#Widget-2constructor[`WidgetAlias::Widget`] and link:#Widget-2constructor[`WidgetAlias::WidgetAlias`]. +| link:#use[`use`] +| Use one. See `Widget`. +|=== + +[#Widget-2constructor] +== link:#Widget[Widget]::Widget + +Construct an empty widget. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +Widget(); +---- + +[#Widget-reset] +== link:#Widget[Widget]::reset + +Reset it. See link:#Widget-2constructor[`Widget::Widget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +reset(); +---- + +[#Widget-resize] +== link:#Widget[Widget]::resize + +Resize it. See link:#Widget[`Widget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +resize(int n); +---- + +[#make] +== make + +Make one. See link:#Widget-2constructor[`WidgetAlias::Widget`] and link:#Widget-2constructor[`WidgetAlias::WidgetAlias`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +link:#Widget[Widget] +make(); +---- + +=== Return Value + +A widget. + +[#use] +== use + +Use one. See link:#Widget[`Widget`]. + +=== Synopsis + +Declared in `<class‐name‐in‐member.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +use(link:#Widget[Widget]& w); +---- + +=== Parameters + +[cols="1,4"] +|=== +| Name| Description +| *w* +| A widget. +|=== + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/tests/golden/fixtures/javadoc/ref/class-name-in-member.cpp b/tests/golden/fixtures/javadoc/ref/class-name-in-member.cpp new file mode 100644 index 00000000000..f7120547649 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/class-name-in-member.cpp @@ -0,0 +1,44 @@ +// Within a class, the name of the class names the class, not its +// constructors, as in C++. Only after a qualifier naming the class does a +// name refer to the constructors, when it is the name of the class or +// repeats the qualifier: `Widget::Widget`, `WidgetAlias::Widget` and +// `WidgetAlias::WidgetAlias`. So a reference to the class from one of its +// members links to the class, as the same reference from outside it does. + +/// A widget. +struct Widget +{ + /// Construct an empty widget. + Widget(); + + /// Resize it. See @ref Widget. + void resize(int n); + + /// Reset it. See @ref Widget::Widget. + void reset(); +}; + +/// A gadget, with overloaded constructors. +struct Gadget +{ + /// Construct an empty gadget. + Gadget(); + + /// Construct a gadget of a given size. + explicit Gadget(int n); + + /// Resize it. See @ref Gadget. + void resize(int n); + + /// Reset it. See @ref Gadget::Gadget. + void reset(); +}; + +/// Use one. See @ref Widget. +void use(Widget& w); + +/// Another name for @ref Widget. +using WidgetAlias = Widget; + +/// Make one. See @ref WidgetAlias::Widget and @ref WidgetAlias::WidgetAlias. +Widget make(); diff --git a/tests/golden/fixtures/javadoc/ref/class-name-in-member.xml b/tests/golden/fixtures/javadoc/ref/class-name-in-member.xml new file mode 100644 index 00000000000..ed1baf3b3de --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/class-name-in-member.xml @@ -0,0 +1,784 @@ + + + + index + namespace + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + regular + + 3HhbACkD6XTno1weUc9b7eoMjxW8 + 6mLSYRat4SHv7d3caNaetwDoVR9 4STgDrwLeHv7mqV5anD6cJEd6K4T + 2dMgtrNZN9xGT8ghvegdRm7JBrCN 4JdcbfveYsXFZiaRFwBbdwwh3YnX + + + + WidgetAlias + WidgetAlias + + + + class-name-in-member.cpp + class-name-in-member.cpp + 41 + 1 + + + + + typedef + 3HhbACkD6XTno1weUc9b7eoMjxW8 + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Another name for + + + reference + Widget + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + text + . + + + + + + + named + + + identifier + 4STgDrwLeHv7mqV5anD6cJEd6K4T + Widget + + + + + + + + Gadget + Gadget + + + class-name-in-member.cpp + class-name-in-member.cpp + 22 + 1 + + + + record + 6mLSYRat4SHv7d3caNaetwDoVR9 + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A gadget, with overloaded constructors. + + + + + struct + + + 3zLG9UuEqGKZFWzd8wN6AezLMR5B oDEh2FCb1KQ4V3mnjYqi8bWGZ7E 8cLRh9VM4cjgCJAnDXHwZiM62WE + + + + + Gadget + 2constructor-0d + + + + class-name-in-member.cpp + class-name-in-member.cpp + 25 + 5 + + + + class-name-in-member.cpp + class-name-in-member.cpp + 28 + 5 + + + + + overloads + 3zLG9UuEqGKZFWzd8wN6AezLMR5B + public + regular + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + brief + + + text + Constructors + + + + + constructor + 4DhFDtFLmCHRDXksft9nQxbbWdtH 2PdAgNHXkB8SuaiuY91cGrCpuYjU + + + named + + + identifier + void + + + void + + + + + Gadget + 2constructor-0e + + + + class-name-in-member.cpp + class-name-in-member.cpp + 25 + 5 + + + + + function + 4DhFDtFLmCHRDXksft9nQxbbWdtH + public + regular + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + brief + + + text + Construct an empty gadget. + + + + + + + named + + + identifier + void + + + void + + + constructor + + + + Gadget + 2constructor-06 + + + + class-name-in-member.cpp + class-name-in-member.cpp + 28 + 5 + + + + + function + 2PdAgNHXkB8SuaiuY91cGrCpuYjU + public + regular + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + brief + + + text + Construct a gadget of a given size. + + + + + + param + + + text + The value to construct from + + + n + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + n + + + constructor + + + + reset + reset + + + + class-name-in-member.cpp + class-name-in-member.cpp + 34 + 5 + + + + + function + oDEh2FCb1KQ4V3mnjYqi8bWGZ7E + public + regular + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + brief + + + text + Reset it. See + + + reference + Gadget::Gadget + 3zLG9UuEqGKZFWzd8wN6AezLMR5B + + + text + . + + + + + + + named + + + identifier + void + + + void + + + normal + + + + resize + resize + + + + class-name-in-member.cpp + class-name-in-member.cpp + 31 + 5 + + + + + function + 8cLRh9VM4cjgCJAnDXHwZiM62WE + public + regular + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + brief + + + text + Resize it. See + + + reference + Gadget + 6mLSYRat4SHv7d3caNaetwDoVR9 + + + text + . + + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + n + + + normal + + + + Widget + Widget + + + class-name-in-member.cpp + class-name-in-member.cpp + 9 + 1 + + + + record + 4STgDrwLeHv7mqV5anD6cJEd6K4T + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + A widget. + + + + + + reference + make + 2dMgtrNZN9xGT8ghvegdRm7JBrCN + + + reference + use + 4JdcbfveYsXFZiaRFwBbdwwh3YnX + + + + struct + + + 3v9aj3teXbXSWbXxa7kPhxJJVaFn vTLEWimEDGyxwQSKqsZxc7Yd4Ys 2bBfosMrzye7MNonp5wigcm22cxQ + + + + + Widget + 2constructor + + + + class-name-in-member.cpp + class-name-in-member.cpp + 12 + 5 + + + + + function + 3v9aj3teXbXSWbXxa7kPhxJJVaFn + public + regular + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + brief + + + text + Construct an empty widget. + + + + + + + named + + + identifier + void + + + void + + + constructor + + + + reset + reset + + + + class-name-in-member.cpp + class-name-in-member.cpp + 18 + 5 + + + + + function + vTLEWimEDGyxwQSKqsZxc7Yd4Ys + public + regular + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + brief + + + text + Reset it. See + + + reference + Widget::Widget + 3v9aj3teXbXSWbXxa7kPhxJJVaFn + + + text + . + + + + + + + named + + + identifier + void + + + void + + + normal + + + + resize + resize + + + + class-name-in-member.cpp + class-name-in-member.cpp + 15 + 5 + + + + + function + 2bBfosMrzye7MNonp5wigcm22cxQ + public + regular + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + brief + + + text + Resize it. See + + + reference + Widget + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + text + . + + + + + + + named + + + identifier + void + + + void + + + + + + + named + + + identifier + int + + + int + + + n + + + normal + + + + make + make + + + + class-name-in-member.cpp + class-name-in-member.cpp + 44 + 1 + + + + + function + 2dMgtrNZN9xGT8ghvegdRm7JBrCN + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Make one. See + + + reference + WidgetAlias::Widget + 3v9aj3teXbXSWbXxa7kPhxJJVaFn + + + text + and + + + reference + WidgetAlias::WidgetAlias + 3v9aj3teXbXSWbXxa7kPhxJJVaFn + + + text + . + + + + + + returns + + + text + A widget. + + + + + + + reference + Widget + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + + + + named + + + identifier + 4STgDrwLeHv7mqV5anD6cJEd6K4T + Widget + + + + + normal + + + use + use + + + + class-name-in-member.cpp + class-name-in-member.cpp + 38 + 1 + + + + + function + 4JdcbfveYsXFZiaRFwBbdwwh3YnX + regular + 4ZrjxJnU1LA5xSyrWMNuXTvSYKwt + + + brief + + + text + Use one. See + + + reference + Widget + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + text + . + + + + + + param + + + text + A widget. + + + w + + + + + reference + Widget + 4STgDrwLeHv7mqV5anD6cJEd6K4T + + + + + + named + + + identifier + void + + + void + + + + + + + lvalue-reference + + + named + + + identifier + 4STgDrwLeHv7mqV5anD6cJEd6K4T + Widget + + + + + + + w + + + normal + + diff --git a/tests/golden/fixtures/javadoc/ref/class-name-in-member.yml b/tests/golden/fixtures/javadoc/ref/class-name-in-member.yml new file mode 100644 index 00000000000..4507c7d09b6 --- /dev/null +++ b/tests/golden/fixtures/javadoc/ref/class-name-in-member.yml @@ -0,0 +1 @@ +generator: [xml, adoc]