From f17057b414da9cc20937d7b436d85eb710c82421 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 13 May 2023 15:13:00 -0700 Subject: [PATCH] split tranche access to separate vector --- include/mrdox/Corpus.hpp | 12 +- include/mrdox/Metadata/Function.hpp | 41 +++--- include/mrdox/Metadata/Members.hpp | 6 - source/lib/api/AST/ASTVisitor.cpp | 20 ++- source/lib/api/Corpus.cpp | 39 +++--- source/lib/api/Metadata/Interface.cpp | 132 ++++++++++-------- source/lib/api/_XML/XMLWriter.cpp | 22 +-- source/lib/api/_XML/XMLWriter.hpp | 12 +- .../old-tests/nested-private-template.cpp | 12 ++ .../old-tests/nested-private-template.xml | 19 +++ 10 files changed, 183 insertions(+), 132 deletions(-) create mode 100644 test-files/old-tests/nested-private-template.cpp create mode 100644 test-files/old-tests/nested-private-template.xml diff --git a/include/mrdox/Corpus.hpp b/include/mrdox/Corpus.hpp index 0b263558b..5a9d3677b 100644 --- a/include/mrdox/Corpus.hpp +++ b/include/mrdox/Corpus.hpp @@ -108,12 +108,12 @@ class MRDOX_VISIBLE MRDOX_DECL virtual bool visit(EnumInfo const&); MRDOX_DECL virtual bool visit(VarInfo const&); - MRDOX_DECL virtual bool visit(DataMember const&); - MRDOX_DECL virtual bool visit(MemberEnum const&); - MRDOX_DECL virtual bool visit(MemberFunction const&); - MRDOX_DECL virtual bool visit(MemberRecord const&); - MRDOX_DECL virtual bool visit(MemberType const&); - MRDOX_DECL virtual bool visit(StaticDataMember const&); + MRDOX_DECL virtual bool visit(DataMember const&, Access); + MRDOX_DECL virtual bool visit(MemberEnum const&, Access); + MRDOX_DECL virtual bool visit(MemberFunction const&, Access); + MRDOX_DECL virtual bool visit(MemberRecord const&, Access); + MRDOX_DECL virtual bool visit(MemberType const&, Access); + MRDOX_DECL virtual bool visit(StaticDataMember const&, Access); }; /** Traverse the symbol, list, or its children. diff --git a/include/mrdox/Metadata/Function.hpp b/include/mrdox/Metadata/Function.hpp index 31ae436e9..4762c88ac 100644 --- a/include/mrdox/Metadata/Function.hpp +++ b/include/mrdox/Metadata/Function.hpp @@ -35,29 +35,28 @@ union FnFlags0 { BitFieldFullValue raw; - BitFlag<0> isVariadic; - BitFlag<1> isVirtual; - BitFlag<2> isVirtualAsWritten; - BitFlag<3> isPure; - BitFlag<4> isDefaulted; - BitFlag<5> isExplicitlyDefaulted; - BitFlag<6> isDeleted; - BitFlag<7> isDeletedAsWritten; - BitFlag<8> isNoReturn; - - BitFlag<9> hasOverrideAttr; - BitFlag<10> hasTrailingReturn; - BitField<11, 2, ConstexprSpecKind> constexprKind; - BitField<13, 4, ExceptionSpecificationType> exceptionSpecType; - BitField<17, 6, OverloadedOperatorKind> overloadedOperator; - BitField<23, 3, StorageClass> storageClass; - BitFlag<26> isConst; - BitFlag<27> isVolatile; - BitField<28, 2, RefQualifierKind> refQualifier; + BitFlag < 0> isVariadic; + BitFlag < 1> isVirtual; + BitFlag < 2> isVirtualAsWritten; + BitFlag < 3> isPure; + BitFlag < 4> isDefaulted; + BitFlag < 5> isExplicitlyDefaulted; + BitFlag < 6> isDeleted; + BitFlag < 7> isDeletedAsWritten; + BitFlag < 8> isNoReturn; + BitFlag < 9> hasOverrideAttr; + BitFlag <10> hasTrailingReturn; + BitFlag <11> isConst; + BitFlag <12> isVolatile; + BitField<13> isFinal; + + BitField<14, 2, ConstexprSpecKind> constexprKind; + BitField<16, 4, ExceptionSpecificationType> exceptionSpecType; + BitField<20, 6, OverloadedOperatorKind> overloadedOperator; + BitField<26, 3, StorageClass> storageClass; + BitField<29, 2, RefQualifierKind> refQualifier; }; - - /** Bit field used with function specifiers. */ union FnFlags1 diff --git a/include/mrdox/Metadata/Members.hpp b/include/mrdox/Metadata/Members.hpp index 7f7bbe91d..7e4384b0a 100644 --- a/include/mrdox/Metadata/Members.hpp +++ b/include/mrdox/Metadata/Members.hpp @@ -28,42 +28,36 @@ struct DataMember { MemberTypeInfo const* I; RecordInfo const* From; - Access access; }; struct MemberEnum { EnumInfo const* I; RecordInfo const* From; - Access access; }; struct MemberFunction { FunctionInfo const* I; RecordInfo const* From; - Access access; }; struct MemberRecord { RecordInfo const* I; RecordInfo const* From; - Access access; }; struct MemberType { TypedefInfo const* I; RecordInfo const* From; - Access access; }; struct StaticDataMember { VarInfo const* I; RecordInfo const* From; - Access access; }; } // mrdox diff --git a/source/lib/api/AST/ASTVisitor.cpp b/source/lib/api/AST/ASTVisitor.cpp index 31642cc75..633e1f011 100644 --- a/source/lib/api/AST/ASTVisitor.cpp +++ b/source/lib/api/AST/ASTVisitor.cpp @@ -796,6 +796,7 @@ constructFunction( I.specs0.isConst = D->isConst(); I.specs0.isVolatile = D->isVolatile(); I.specs0.refQualifier = D->getRefQualifier(); + I.specs0.isFinal = D->template hasAttr(); //D->isCopyAssignmentOperator() //D->isMoveAssignmentOperator() //D->isOverloadedOperator(); @@ -947,8 +948,25 @@ buildRecord( } } + AccessSpecifier access; + if(auto CT = D->getDescribedClassTemplate()) + { + access = CT->getAccess(); + } + else if(auto MSI = D->getMemberSpecializationInfo()) + { + access = MSI->getInstantiatedFrom()->getAccess(); + } + else if(auto* CTSD = dyn_cast(D)) + { + access = CTSD->getSpecializedTemplate()->getAccess(); + } + else + { + access = D->getAccess(); + } insertBitcode(ex_, writeBitcode(I)); - insertBitcode(ex_, writeParent(std::move(I), D->getAccess())); + insertBitcode(ex_, writeParent(std::move(I), access)); } void diff --git a/source/lib/api/Corpus.cpp b/source/lib/api/Corpus.cpp index b99bf3ddd..5cc61d2e6 100644 --- a/source/lib/api/Corpus.cpp +++ b/source/lib/api/Corpus.cpp @@ -112,39 +112,34 @@ bool Corpus::Visitor::visit(VarInfo const&) //--- -bool Corpus::Visitor::visit(DataMember const&) +bool Corpus::Visitor::visit(DataMember const&, Access) { return true; } -bool Corpus::Visitor::visit(MemberEnum const& I) +bool Corpus::Visitor::visit(MemberEnum const& I, Access) { - return visit(*I.I); -// return true; + return true; } -bool Corpus::Visitor::visit(MemberFunction const& I) +bool Corpus::Visitor::visit(MemberFunction const& I, Access) { - return visit(*I.I); -// return true; + return true; } -bool Corpus::Visitor::visit(MemberRecord const& I) +bool Corpus::Visitor::visit(MemberRecord const& I, Access) { - return visit(*I.I); -// return true; + return true; } -bool Corpus::Visitor::visit(MemberType const& I) +bool Corpus::Visitor::visit(MemberType const& I, Access) { - return visit(*I.I); -// return true; + return true; } -bool Corpus::Visitor::visit(StaticDataMember const& I) +bool Corpus::Visitor::visit(StaticDataMember const& I, Access) { - return visit(*I.I); -// return true; + return true; } @@ -211,30 +206,30 @@ traverse( for(auto const& t : I.Children_.Records) if(! f.visit(MemberRecord{ &get(t.id), - &I, t.access})) + &I}, t.access)) return false; for(auto const& t : I.Children_.Functions) if(! f.visit(MemberFunction{ &get(t.id), - &I, t.access})) + &I}, t.access)) return false; for(auto const& t : I.Children_.Types) if(! f.visit(MemberType{ &get(t.id), - &I, t.access})) + &I}, t.access)) return false; for(auto const& t : I.Children_.Enums) if(! f.visit(MemberEnum{ &get(t.id), - &I, t.access})) + &I}, t.access)) return false; for(auto const& t : I.Children_.Vars) if(! f.visit(StaticDataMember{ &get(t.id), - &I, t.access})) + &I}, t.access)) return false; for(auto const& t : I.Members) - if(! f.visit(DataMember{&t, &I, t.access})) + if(! f.visit(DataMember{&t, &I}, t.access)) return false; return true; } diff --git a/source/lib/api/Metadata/Interface.cpp b/source/lib/api/Metadata/Interface.cpp index 60ffd15cf..9860ad66a 100644 --- a/source/lib/api/Metadata/Interface.cpp +++ b/source/lib/api/Metadata/Interface.cpp @@ -19,16 +19,26 @@ #include #include #include +#include namespace clang { namespace mrdox { +//------------------------------------------------ + class Interface::Build { Interface& I_; Corpus const& corpus_; bool includePrivate_; + std::vector> data_; + std::vector> enums_; + std::vector> functions_; + std::vector> records_; + std::vector> types_; + std::vector> vars_; + public: Build( Interface& I, @@ -38,13 +48,8 @@ class Interface::Build , corpus_(corpus) , includePrivate_(corpus_.config.includePrivate) { - I_.data_.clear(); - I_.enums_.clear(); - I_.functions_.clear(); - I_.records_.clear(); - I_.types_.clear(); - I_.vars_.clear(); append(Access::Public, Derived); + finish(); } @@ -77,50 +82,61 @@ class Interface::Build append(actualAccess, corpus_.get(B.id)); } - // Records + // Data Members if( includePrivate_ || access != Access::Private) { - for(auto const& ref : From.Children_.Records) + for(auto const& J : From.Members) { - auto const& J = corpus_.get(ref.id); + auto actualAccess = effectiveAccess(access, J.access); + data_.push_back({ actualAccess, { &J, &From } }); + } + } + + // Member Enums + if( includePrivate_ || + access != Access::Private) + { + for(auto const& ref : From.Children_.Enums) + { + auto const& J = corpus_.get(ref.id); auto actualAccess = effectiveAccess(access, ref.access); - I_.records_.push_back({ &J, &From, actualAccess }); + enums_.push_back({ actualAccess, { &J, &From } }); } } - // Functions + // Member Functions { - auto const isFinal = From.specs.isFinal.get(); + auto const isRecFinal = From.specs.isFinal.get(); for(auto const& ref : From.Children_.Functions) { auto const& J = corpus_.get(ref.id); auto actualAccess = effectiveAccess(access, ref.access); - // private virtual functions are emitted anyway since - // they are always accessible from derived classes - // unless this class is marked `final`. + //bool isFinal = J.specs0.isFinal; + // private virtual functions are effectively public + // and should be emitted unless the record is final if( includePrivate_ || actualAccess != Access::Private || - ( ! isFinal && J.specs0.isVirtual )) + ( ! isRecFinal && J.specs0.isVirtual )) { - I_.functions_.push_back({ &J, &From, actualAccess }); + functions_.push_back({ actualAccess, { &J, &From }}); } } } - // Enums + // Member Records if( includePrivate_ || access != Access::Private) { - for(auto const& ref : From.Children_.Enums) + for(auto const& ref : From.Children_.Records) { - auto const& J = corpus_.get(ref.id); + auto const& J = corpus_.get(ref.id); auto actualAccess = effectiveAccess(access, ref.access); - I_.enums_.push_back({ &J, &From, actualAccess }); + records_.push_back({ actualAccess, { &J, &From }}); } } - // Typedefs + // Member Types if( includePrivate_ || access != Access::Private) { @@ -128,18 +144,7 @@ class Interface::Build { auto const& J = corpus_.get(ref.id); auto actualAccess = effectiveAccess(access, ref.access); - I_.types_.push_back({ &J, &From, actualAccess }); - } - } - - // Data Members - if( includePrivate_ || - access != Access::Private) - { - for(auto const& J : From.Members) - { - auto actualAccess = effectiveAccess(access, J.access); - I_.data_.push_back({ &J, &From, actualAccess }); + types_.push_back({ actualAccess, { &J, &From }}); } } @@ -151,54 +156,63 @@ class Interface::Build { auto const& J = corpus_.get(ref.id); auto actualAccess = effectiveAccess(access, ref.access); - I_.vars_.push_back({ &J, &From, actualAccess }); + vars_.push_back({ actualAccess, { &J, &From }}); } } } - template + template void sort( std::span Interface::Tranche::*member, - std::vector& list) + std::vector& dest, + std::vector& src) { llvm::stable_sort( - list, - []( auto const& I0, - auto const& I1) noexcept + src, + []( auto const& p0, + auto const& p1) noexcept { return - to_underlying(I0.access) < - to_underlying(I1.access); + to_underlying(p0.first) < + to_underlying(p1.first); }); - auto it0 = list.begin(); + dest.resize(0); + dest.reserve(src.size()); + for(auto const& v : src) + dest.push_back(v.second); + + auto it0 = src.begin(); auto it = std::find_if_not( - it0, list.end(), - [](auto const& I) noexcept + it0, src.end(), + [](auto const& p) noexcept { - return I.access == Access::Public; + return p.first == Access::Public; }); - I_.Public.*member = { it0, it }; + std::size_t const nPublic = it - it0; it0 = it; - it = std::find_if( - it0, list.end(), - [](auto const& I) noexcept + it = std::find_if_not( + it0, src.end(), + [](auto const& p) noexcept { - return I.access == Access::Protected; + return p.first == Access::Protected; }); - I_.Protected.*member = { it0, it }; - I_.Private.*member = { it, list.end() }; + std::size_t const nPrivate = src.end() - it; + + I_.Public.*member = { dest.begin(), dest.begin() + nPublic }; + I_.Protected.*member = { dest.begin() + nPublic, dest.end() - nPrivate }; + I_.Private.*member = { dest.end() - nPrivate, dest.end() }; } void finish() { - sort(&Interface::Tranche::Records, I_.records_); - sort(&Interface::Tranche::Functions, I_.functions_); - sort(&Interface::Tranche::Enums, I_.enums_); - sort(&Interface::Tranche::Types, I_.types_); - sort(&Interface::Tranche::Data, I_.data_); - sort(&Interface::Tranche::Vars, I_.vars_); + sort(&Interface::Tranche::Records, I_.records_, records_); + sort(&Interface::Tranche::Functions, I_.functions_, functions_); + sort(&Interface::Tranche::Enums, I_.enums_, enums_); + sort(&Interface::Tranche::Types, I_.types_, types_); + sort(&Interface::Tranche::Data, I_.data_, data_); + sort(&Interface::Tranche::Vars, I_.vars_, vars_); } }; diff --git a/source/lib/api/_XML/XMLWriter.cpp b/source/lib/api/_XML/XMLWriter.cpp index c57198fea..c1697bd48 100644 --- a/source/lib/api/_XML/XMLWriter.cpp +++ b/source/lib/api/_XML/XMLWriter.cpp @@ -260,7 +260,7 @@ visit( bool XMLWriter:: visit( - DataMember const& I) + DataMember const& I, Access access) { return true; } @@ -268,41 +268,41 @@ visit( bool XMLWriter:: visit( - MemberEnum const& I) + MemberEnum const& I, Access access) { - return writeEnum(*I.I, &I.access); + return writeEnum(*I.I, &access); } bool XMLWriter:: visit( - MemberFunction const& I) + MemberFunction const& I, Access access) { - return writeFunction(*I.I, &I.access); + return writeFunction(*I.I, &access); } bool XMLWriter:: visit( - MemberRecord const& I) + MemberRecord const& I, Access access) { - return writeRecord(*I.I, &I.access); + return writeRecord(*I.I, &access); } bool XMLWriter:: visit( - MemberType const& I) + MemberType const& I, Access access) { - return writeTypedef(*I.I, &I.access); + return writeTypedef(*I.I, &access); } bool XMLWriter:: visit( - StaticDataMember const& I) + StaticDataMember const& I, Access access) { - return writeVar(*I.I, &I.access); + return writeVar(*I.I, &access); } //------------------------------------------------ diff --git a/source/lib/api/_XML/XMLWriter.hpp b/source/lib/api/_XML/XMLWriter.hpp index a85f057b9..ba69880e7 100644 --- a/source/lib/api/_XML/XMLWriter.hpp +++ b/source/lib/api/_XML/XMLWriter.hpp @@ -67,12 +67,12 @@ class XMLWriter bool visit(EnumInfo const&) override; bool visit(VarInfo const&) override; - bool visit(DataMember const&) override; - bool visit(MemberEnum const&) override; - bool visit(MemberFunction const&) override; - bool visit(MemberRecord const&) override; - bool visit(MemberType const&) override; - bool visit(StaticDataMember const&) override; + bool visit(DataMember const&, Access) override; + bool visit(MemberEnum const&, Access) override; + bool visit(MemberFunction const&, Access) override; + bool visit(MemberRecord const&, Access) override; + bool visit(MemberType const&, Access) override; + bool visit(StaticDataMember const&, Access) override; bool writeEnum(EnumInfo const&, Access const* access = nullptr); bool writeFunction(FunctionInfo const&, Access const* access = nullptr); diff --git a/test-files/old-tests/nested-private-template.cpp b/test-files/old-tests/nested-private-template.cpp new file mode 100644 index 000000000..5d758cd27 --- /dev/null +++ b/test-files/old-tests/nested-private-template.cpp @@ -0,0 +1,12 @@ +template +class range +{ + template + struct impl; +}; + +template +template +struct range::impl +{ +}; diff --git a/test-files/old-tests/nested-private-template.xml b/test-files/old-tests/nested-private-template.xml new file mode 100644 index 000000000..e6b5228ca --- /dev/null +++ b/test-files/old-tests/nested-private-template.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + +