From 31a646646999d3ff117be71a0f08553d2b020790 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 11 Jul 2023 11:14:32 -0400 Subject: [PATCH] chore: add TParamKeyKind, use TArg to store default template arguments closes #196 --- .../asciidoc/partials/template-arg.adoc.hbs | 8 + .../asciidoc/partials/template-args.adoc.hbs | 4 +- .../asciidoc/partials/tparam-nontype.adoc.hbs | 2 +- .../partials/tparam-template.adoc.hbs | 2 +- .../asciidoc/partials/tparam-type.adoc.hbs | 4 +- include/mrdox/Metadata/Template.hpp | 54 +++--- lib/-XML/CXXTags.hpp | 12 +- lib/AST/ASTVisitor.cpp | 183 ++++++++++-------- lib/AST/AnyBlock.hpp | 42 ++-- lib/AST/BitcodeIDs.hpp | 2 +- lib/AST/BitcodeWriter.cpp | 19 +- lib/Metadata/DomMetadata.cpp | 20 +- lib/Metadata/Template.cpp | 56 ++++-- 13 files changed, 227 insertions(+), 181 deletions(-) create mode 100644 addons/generator/asciidoc/partials/template-arg.adoc.hbs diff --git a/addons/generator/asciidoc/partials/template-arg.adoc.hbs b/addons/generator/asciidoc/partials/template-arg.adoc.hbs new file mode 100644 index 000000000..3503da48a --- /dev/null +++ b/addons/generator/asciidoc/partials/template-arg.adoc.hbs @@ -0,0 +1,8 @@ +{{#if (eq kind "type")~}} +{{~>declarator type decl-name=""~}} +{{else if (eq kind "non-type")~}} +{{~value~}} +{{else if (eq kind "template")~}} +{{#if template}}xref:{{template}}[{{name~}}]{{else~}}{{name~}}{{/if~}} +{{/if~}} +{{~#if is-pack}}...{{/if~}} diff --git a/addons/generator/asciidoc/partials/template-args.adoc.hbs b/addons/generator/asciidoc/partials/template-args.adoc.hbs index 2fa30dda6..8596dc941 100644 --- a/addons/generator/asciidoc/partials/template-args.adoc.hbs +++ b/addons/generator/asciidoc/partials/template-args.adoc.hbs @@ -1,4 +1,4 @@ <{{~#each args~}} - {{value}} - {{~#if (not @last)}}, {{/if}} +{{~>template-arg .~}} +{{~#if (not @last)}}, {{/if~}} {{~/each~}}> \ No newline at end of file diff --git a/addons/generator/asciidoc/partials/tparam-nontype.adoc.hbs b/addons/generator/asciidoc/partials/tparam-nontype.adoc.hbs index b8122ce62..a42f8c188 100644 --- a/addons/generator/asciidoc/partials/tparam-nontype.adoc.hbs +++ b/addons/generator/asciidoc/partials/tparam-nontype.adoc.hbs @@ -1,4 +1,4 @@ {{>declarator type decl-name=""}} {{~#if is-pack}}...{{/if}} {{~#if name}} {{name}}{{/if}} -{{~#if default}} = {{default}}{{/if~}} +{{~#if default}} = {{>template-arg default~}}{{/if~}} diff --git a/addons/generator/asciidoc/partials/tparam-template.adoc.hbs b/addons/generator/asciidoc/partials/tparam-template.adoc.hbs index 5bfca0228..385684173 100644 --- a/addons/generator/asciidoc/partials/tparam-template.adoc.hbs +++ b/addons/generator/asciidoc/partials/tparam-template.adoc.hbs @@ -2,4 +2,4 @@ typename {{~#if is-pack}}...{{/if}} {{~#if name}} {{name}}{{/if}} -{{~#if default}} = {{default}}{{/if~}} +{{~#if default}} = {{>template-arg default~}}{{/if~}} diff --git a/addons/generator/asciidoc/partials/tparam-type.adoc.hbs b/addons/generator/asciidoc/partials/tparam-type.adoc.hbs index 0a6d5229a..0cc149c17 100644 --- a/addons/generator/asciidoc/partials/tparam-type.adoc.hbs +++ b/addons/generator/asciidoc/partials/tparam-type.adoc.hbs @@ -1,4 +1,4 @@ -typename +{{key}} {{~#if is-pack}}...{{/if}} {{~#if name}} {{name}}{{/if}} -{{~#if default}} = {{>declarator default decl-name=""}}{{~/if~}} +{{~#if default}} = {{>template-arg default~}}{{~/if~}} diff --git a/include/mrdox/Metadata/Template.hpp b/include/mrdox/Metadata/Template.hpp index 835b8a297..1f9871827 100644 --- a/include/mrdox/Metadata/Template.hpp +++ b/include/mrdox/Metadata/Template.hpp @@ -34,7 +34,7 @@ enum class TArgKind : int Template }; -MRDOX_DECL dom::String toString(TArgKind kind) noexcept; +MRDOX_DECL std::string_view toString(TArgKind kind) noexcept; struct TArg { @@ -131,6 +131,8 @@ visit( } } +MRDOX_DECL std::string toString(const TArg& arg) noexcept; + // ---------------------------------------------------------------- enum class TParamKind : int @@ -143,20 +145,23 @@ enum class TParamKind : int Template }; -MRDOX_DECL dom::String toString(TParamKind kind) noexcept; +MRDOX_DECL std::string_view toString(TParamKind kind) noexcept; struct TParam { - /** The kind of template parameter this is. */ + /** The kind of template parameter this is */ TParamKind Kind; /** The template parameters name, if any */ std::string Name; - /** Whether this template parameter is a parameter pack. */ + /** Whether this template parameter is a parameter pack */ bool IsParameterPack = false; - constexpr virtual ~TParam() = default; + /** The default template argument, if any */ + std::unique_ptr Default; + + virtual ~TParam() = default; constexpr bool isType() const noexcept { return Kind == TParamKind::Type; } constexpr bool isNonType() const noexcept { return Kind == TParamKind::NonType; } @@ -188,11 +193,22 @@ struct IsTParam : TParam } }; +/** The keyword a template parameter was declared with */ +enum class TParamKeyKind : int +{ + Class = 0, + Typename +}; + +MRDOX_DECL std::string_view toString(TParamKeyKind kind) noexcept; + struct TypeTParam : IsTParam { - /** Default type for the type template parameter */ - std::unique_ptr Default; + /** Keyword (class/typename) the parameter uses **/ + TParamKeyKind KeyKind = TParamKeyKind::Class; + /** Type template parameter default argument (if any) */ + // std::unique_ptr Default; }; struct NonTypeTParam @@ -200,8 +216,9 @@ struct NonTypeTParam { /** Type of the non-type template parameter */ std::unique_ptr Type; - // Non-type template parameter default value (if any) - Optional Default; + /** Non-type template parameter default argument (if any) */ + // std::unique_ptr Default; + // Optional Default; }; struct TemplateTParam @@ -209,8 +226,9 @@ struct TemplateTParam { /** Template parameters for the template template parameter */ std::vector> Params; - /** Non-type template parameter default value (if any) */ - Optional Default; + /** Template template parameter default argument (if any) */ + // std::unique_ptr Default; + // Optional Default; }; template< @@ -246,20 +264,6 @@ visit( // ---------------------------------------------------------------- -#if 0 -struct TArg -{ - std::string Value; - - TArg() = default; - - MRDOX_DECL - TArg(std::string&& value); -}; -#endif - -// ---------------------------------------------------------------- - enum class TemplateSpecKind { Primary = 0, // for bitstream diff --git a/lib/-XML/CXXTags.hpp b/lib/-XML/CXXTags.hpp index 82e79fbd7..c8c8fc406 100644 --- a/lib/-XML/CXXTags.hpp +++ b/lib/-XML/CXXTags.hpp @@ -335,17 +335,7 @@ inline void writeTemplateParam(const TParam& I, XMLTags& tags) attrs.push({"type", toString(*P.Type)}); if(P.Default) - { - std::string default_val; - if constexpr(T::isType()) - default_val = toString(*P.Default); - else if constexpr(T::isNonType()) - default_val = *P.Default; - else if constexpr(T::isTemplate()) - default_val = *P.Default; - - attrs.push({"default", std::move(default_val)}); - } + attrs.push({"default", toString(*P.Default)}); if constexpr(T::isTemplate()) { diff --git a/lib/AST/ASTVisitor.cpp b/lib/AST/ASTVisitor.cpp index a41c1605b..f64053b25 100644 --- a/lib/AST/ASTVisitor.cpp +++ b/lib/AST/ASTVisitor.cpp @@ -1298,10 +1298,15 @@ class ASTVisitor if constexpr(kind == Decl::TemplateTypeParm) { auto R = std::make_unique(); + if(P->wasDeclaredWithTypename()) + R->KeyKind = TParamKeyKind::Typename; if(P->hasDefaultArgument()) { - R->Default = buildTypeInfo( - P->getDefaultArgument()); + QualType QT = P->getDefaultArgument(); + R->Default = buildTemplateArg( + TemplateArgument(QT, QT.isNull(), true)); + // R->Default = buildTypeInfo( + // P->getDefaultArgument()); } return R; } @@ -1312,8 +1317,10 @@ class ASTVisitor P->getType()); if(P->hasDefaultArgument()) { - R->Default.emplace(getSourceCode( - P->getDefaultArgumentLoc())); + R->Default = buildTemplateArg( + TemplateArgument(P->getDefaultArgument(), true)); + // R->Default.emplace(getSourceCode( + // P->getDefaultArgumentLoc())); } return R; } @@ -1328,8 +1335,10 @@ class ASTVisitor if(P->hasDefaultArgument()) { - R->Default.emplace(getSourceCode( - P->getDefaultArgumentLoc())); + R->Default = buildTemplateArg( + P->getDefaultArgument().getArgument()); + // R->Default.emplace(getSourceCode( + // P->getDefaultArgumentLoc())); } return R; } @@ -1345,11 +1354,9 @@ class ASTVisitor return TP; } - template - void - buildTemplateArgs( - std::vector>& result, - Range&& range) + std::unique_ptr + buildTemplateArg( + const TemplateArgument& A) { // TypePrinter generates an internal placeholder name (e.g. type-parameter-0-0) // for template type parameters used as arguments. it also cannonicalizes @@ -1360,55 +1367,47 @@ class ASTVisitor // the argument as written when it is not dependent and is a type. // FIXME: constant folding behavior should be consistent with that of other // constructs, e.g. noexcept specifiers & explicit specifiers - const auto& policy = context_.getPrintingPolicy(); - for(const TemplateArgument& arg : range) + switch(A.getKind()) { - switch(arg.getKind()) - { - // empty template argument (e.g. not yet deduced) - case TemplateArgument::Null: - break; + // empty template argument (e.g. not yet deduced) + case TemplateArgument::Null: + break; - // a template argument pack (any kind) - case TemplateArgument::Pack: - { - // KRYSTIAN NOTE: is this correct? should we have a - // separate TArgKind for packs instead of "unlaminating" - // them as we are doing here? - buildTemplateArgs(result, arg.pack_elements()); - break; - } - // type - case TemplateArgument::Type: + // a template argument pack (any kind) + case TemplateArgument::Pack: + { + // we should never a TemplateArgument::Pack here + MRDOX_UNREACHABLE(); + break; + } + // type + case TemplateArgument::Type: + { + auto R = std::make_unique(); + QualType QT = A.getAsType(); + MRDOX_ASSERT(! QT.isNull()); + // if the template argument is a pack expansion, + // use the expansion pattern as the type & mark + // the template argument as a pack expansion + if(const Type* T = QT.getTypePtr(); + auto* PT = dyn_cast(T)) { - auto R = std::make_unique(); - QualType QT = arg.getAsType(); - MRDOX_ASSERT(! QT.isNull()); - // if the template argument is a pack expansion, - // use the expansion pattern as the type & mark - // the template argument as a pack expansion - if(const Type* T = QT.getTypePtr(); - auto* PT = dyn_cast(T)) - { - R->IsPackExpansion = true; - QT = PT->getPattern(); - } - R->Type = buildTypeInfo(QT); - - result.emplace_back(std::move(R)); - break; + R->IsPackExpansion = true; + QT = PT->getPattern(); } - // pack expansion of a template name - case TemplateArgument::TemplateExpansion: - // template name - case TemplateArgument::Template: + R->Type = buildTypeInfo(QT); + return R; + } + // pack expansion of a template name + case TemplateArgument::TemplateExpansion: + // template name + case TemplateArgument::Template: + { + auto R = std::make_unique(); + R->IsPackExpansion = A.isPackExpansion(); + TemplateName TN = A.getAsTemplateOrTemplatePattern(); + if(auto* TD = TN.getAsTemplateDecl()) { - auto R = std::make_unique(); - R->IsPackExpansion = arg.isPackExpansion(); - TemplateName TN = arg.getAsTemplateOrTemplatePattern(); - TemplateDecl* TD = cast( - getInstantiatedFrom(TN.getAsTemplateDecl())); - MRDOX_ASSERT(TD); if(auto* II = TD->getIdentifier()) R->Name = II->getName(); // do not extract a SymbolID or build Info if @@ -1417,38 +1416,56 @@ class ASTVisitor if(! isa(TD) && ! isa(TD)) { - extractSymbolID(TD, R->Template); - getOrBuildInfo(TD); + Decl* D = getInstantiatedFrom(TD); + extractSymbolID(D, R->Template); + getOrBuildInfo(D); } - result.emplace_back(std::move(R)); - break; } - // nullptr value - case TemplateArgument::NullPtr: - // expression referencing a declaration - case TemplateArgument::Declaration: - // integral expression - case TemplateArgument::Integral: - // expression - case TemplateArgument::Expression: - { - auto R = std::make_unique(); - R->IsPackExpansion = arg.isPackExpansion(); - // if this is a pack expansion, use the template argument - // expansion pattern in place of the template argument pack - const TemplateArgument& adjusted = - R->IsPackExpansion ? - arg.getPackExpansionPattern() : arg; + return R; + } + // nullptr value + case TemplateArgument::NullPtr: + // expression referencing a declaration + case TemplateArgument::Declaration: + // integral expression + case TemplateArgument::Integral: + // expression + case TemplateArgument::Expression: + { + auto R = std::make_unique(); + R->IsPackExpansion = A.isPackExpansion(); + // if this is a pack expansion, use the template argument + // expansion pattern in place of the template argument pack + const TemplateArgument& adjusted = + R->IsPackExpansion ? + A.getPackExpansionPattern() : A; - llvm::raw_string_ostream stream(R->Value.Written); - adjusted.print(policy, stream, false); + llvm::raw_string_ostream stream(R->Value.Written); + adjusted.print(context_.getPrintingPolicy(), stream, false); - result.emplace_back(std::move(R)); - break; - } - default: - MRDOX_UNREACHABLE(); - } + return R; + } + default: + MRDOX_UNREACHABLE(); + } + return nullptr; + } + + template + void + buildTemplateArgs( + std::vector>& result, + Range&& range) + { + for(const TemplateArgument& arg : range) + { + // KRYSTIAN NOTE: is this correct? should we have a + // separate TArgKind for packs instead of "unlaminating" + // them as we are doing here? + if(arg.getKind() == TemplateArgument::Pack) + buildTemplateArgs(result, arg.pack_elements()); + else + result.emplace_back(buildTemplateArg(arg)); } } diff --git a/lib/AST/AnyBlock.hpp b/lib/AST/AnyBlock.hpp index 86221229e..9e19fd460 100644 --- a/lib/AST/AnyBlock.hpp +++ b/lib/AST/AnyBlock.hpp @@ -743,17 +743,12 @@ class TemplateParamBlock { return decodeRecord(R, I_->IsParameterPack, Blob); } - case TEMPLATE_PARAM_DEFAULT: + case TEMPLATE_PARAM_KEY_KIND: { - return visit(*I_, [&](T& P) - { - if constexpr(T::isType()) - return formatError( - "invalid template parameter kind"); - else - return decodeRecord(R, - P.Default.emplace(), Blob); - }); + if(! I_->isType()) + return formatError("only TypeTParams have a key kind"); + return decodeRecord(R, static_cast< + TypeTParam&>(*I_.get()).KeyKind, Blob); } default: return AnyBlock::parseRecord(R, ID, Blob); @@ -770,26 +765,23 @@ class TemplateParamBlock { if(! I_->isTemplate()) return formatError("only TemplateTParam may have template parameters"); - TemplateParamBlock P( + TemplateParamBlock B( static_cast( *I_.get()).Params.emplace_back(), br_); - return br_.readBlock(P, ID); + return br_.readBlock(B, ID); + } + case BI_TEMPLATE_ARG_BLOCK_ID: + { + TemplateArgBlock B(I_->Default, br_); + return br_.readBlock(B, ID); } case BI_TYPEINFO_BLOCK_ID: { - return visit(*I_, [&](T& P) - { - if constexpr(T::isTemplate()) - return formatError("invalid TypeInfo block in TParam"); - - std::unique_ptr* R = nullptr; - if constexpr(T::isType()) - R = &P.Default; - else if constexpr(T::isNonType()) - R = &P.Type; - TypeInfoBlock B(*R, br_); - return br_.readBlock(B, ID); - }); + if(! I_->isNonType()) + return formatError("only NonTypeTParams may have a type"); + TypeInfoBlock B(static_cast< + NonTypeTParam&>(*I_.get()).Type, br_); + return br_.readBlock(B, ID); } default: return AnyBlock::readSubBlock(ID); diff --git a/lib/AST/BitcodeIDs.hpp b/lib/AST/BitcodeIDs.hpp index f5e58664f..46fb5186f 100644 --- a/lib/AST/BitcodeIDs.hpp +++ b/lib/AST/BitcodeIDs.hpp @@ -132,10 +132,10 @@ enum RecordID TEMPLATE_ARG_IS_PACK, TEMPLATE_ARG_TEMPLATE, TEMPLATE_ARG_NAME, - TEMPLATE_PARAM_DEFAULT, TEMPLATE_PARAM_IS_PACK, TEMPLATE_PARAM_KIND, TEMPLATE_PARAM_NAME, + TEMPLATE_PARAM_KEY_KIND, TEMPLATE_PRIMARY_USR, SPECIALIZATION_PRIMARY, SPECIALIZATION_MEMBERS, diff --git a/lib/AST/BitcodeWriter.cpp b/lib/AST/BitcodeWriter.cpp index a60e78b20..e2637a6df 100644 --- a/lib/AST/BitcodeWriter.cpp +++ b/lib/AST/BitcodeWriter.cpp @@ -296,7 +296,7 @@ RecordIDNameMap = []() {TEMPLATE_PARAM_KIND, {"Kind", &Integer32Abbrev}}, {TEMPLATE_PARAM_NAME, {"Name", &StringAbbrev}}, {TEMPLATE_PARAM_IS_PACK, {"IsPack", &BoolAbbrev}}, - {TEMPLATE_PARAM_DEFAULT, {"Default", &StringAbbrev}}, + {TEMPLATE_PARAM_KEY_KIND,{"TParamKeyKind", &Integer32Abbrev}}, {TYPEINFO_KIND, {"TypeinfoKind", &Integer32Abbrev}}, {TYPEINFO_ID, {"TypeinfoID", &SymbolIDAbbrev}}, {TYPEINFO_NAME, {"TypeinfoName", &StringAbbrev}}, @@ -379,7 +379,7 @@ RecordsByBlock{ // TParam {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_KIND, TEMPLATE_PARAM_NAME, - TEMPLATE_PARAM_IS_PACK, TEMPLATE_PARAM_DEFAULT}}, + TEMPLATE_PARAM_IS_PACK, TEMPLATE_PARAM_KEY_KIND}}, // SpecializationInfo {BI_SPECIALIZATION_BLOCK_ID, {SPECIALIZATION_PRIMARY, SPECIALIZATION_MEMBERS}}, @@ -1062,20 +1062,21 @@ emitBlock( emitRecord(P.Name, TEMPLATE_PARAM_NAME); emitRecord(P.IsParameterPack, TEMPLATE_PARAM_IS_PACK); - if constexpr(T::isType()) + if(P.Default) emitBlock(P.Default); - else if constexpr(T::isNonType()) + + if constexpr(T::isType()) + { + emitRecord(P.KeyKind, TEMPLATE_PARAM_KEY_KIND); + } + if constexpr(T::isNonType()) { emitBlock(P.Type); - if(P.Default) - emitRecord(*P.Default, TEMPLATE_PARAM_DEFAULT); } - else if constexpr(T::isTemplate()) + if constexpr(T::isTemplate()) { for(const auto& P : P.Params) emitBlock(P); - if(P.Default) - emitRecord(*P.Default, TEMPLATE_PARAM_DEFAULT); } }); } diff --git a/lib/Metadata/DomMetadata.cpp b/lib/Metadata/DomMetadata.cpp index 7870ec402..e4e727fb3 100644 --- a/lib/Metadata/DomMetadata.cpp +++ b/lib/Metadata/DomMetadata.cpp @@ -283,12 +283,12 @@ domCreate( entries.emplace_back("type", domCreate(t.Type, domCorpus)); } - else if constexpr(T::isNonType()) + if constexpr(T::isNonType()) { entries.emplace_back("value", t.Value.Written); } - else if constexpr(T::isTemplate()) + if constexpr(T::isTemplate()) { entries.emplace_back("name", t.Name); @@ -317,25 +317,25 @@ domCreate( }; visit(*I, [&](const T& t) { - if constexpr(T::isType()) - { + if(t.Default) entries.emplace_back("default", domCreate(t.Default, domCorpus)); + + if constexpr(T::isType()) + { + entries.emplace_back("key", + toString(t.KeyKind)); } - else if constexpr(T::isNonType()) + if constexpr(T::isNonType()) { entries.emplace_back("type", domCreate(t.Type, domCorpus)); - entries.emplace_back("default", - t.Default); } - else if constexpr(T::isTemplate()) + if constexpr(T::isTemplate()) { entries.emplace_back("params", dom::newArray( t.Params, domCorpus)); - entries.emplace_back("default", - t.Default); } }); return dom::Object(std::move(entries)); diff --git a/lib/Metadata/Template.cpp b/lib/Metadata/Template.cpp index c6e55ad3d..7c560ace6 100644 --- a/lib/Metadata/Template.cpp +++ b/lib/Metadata/Template.cpp @@ -15,16 +15,7 @@ namespace clang { namespace mrdox { -#if 0 -TArg:: -TArg( - std::string&& value) - : Value(std::move(value)) -{ -} -#endif - -dom::String +std::string_view toString( TArgKind kind) noexcept { @@ -41,7 +32,7 @@ toString( } } -dom::String +std::string_view toString( TParamKind kind) noexcept { @@ -58,6 +49,21 @@ toString( } } +std::string_view +toString( + TParamKeyKind kind) noexcept +{ + switch(kind) + { + case TParamKeyKind::Class: + return "class"; + case TParamKeyKind::Typename: + return "typename"; + default: + MRDOX_UNREACHABLE(); + } +} + std::string_view toString( TemplateSpecKind kind) @@ -75,5 +81,33 @@ toString( } } +std::string +toString( + const TArg& arg) noexcept +{ + return visit(arg, + [](const T& t) + { + std::string result; + if constexpr(T::isType()) + { + if(t.Type) + result += toString(*t.Type); + } + if constexpr(T::isNonType()) + { + result += t.Value.Written; + } + if constexpr(T::isTemplate()) + { + result += t.Name; + } + + if(t.IsPackExpansion) + result += "..."; + return result; + }); +} + } // mrdox } // clang