From 22e6a261fae1eb57105cc131592026701f283e0e Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Mon, 13 Apr 2026 08:40:40 -0700 Subject: [PATCH] Revert clang-doc arena merging patches (#191668) This is a set of squashed reverts of recent clang doc patches, since its breaking something on Darwin builders: https://lab.llvm.org/buildbot/#/builders/23/builds/19172 Revert "[clang-doc][nfc] Default initialize all StringRef members (#191641)" This reverts commit 155b9b354c1d91661be9f6d0432a96e47cfc2700. Revert "[clang-doc] Initialize StringRef members in Info types (#191637)" This reverts commit 489dab3827b255d21ea38b1e3f45ddb08bd10a87. Revert "[clang-doc] Initialize member variable (#191570)" This reverts commit 5d64a44a84af31f9e99d42cccffa4f01c0be2e0b. Revert "[clang-doc] Merge data into persistent memory (#190056)" This reverts commit 21e0034c69489eff3b09929e5e13ea34b3dd0e5a. Revert "[clang-doc] Support deep copy between arenas for merging (#190055)" This reverts commit c70dae8b0cee46af1411bc4e4ba6fc28e2babf3e. --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 606 ++++++------------ clang-tools-extra/clang-doc/BitcodeReader.h | 20 - clang-tools-extra/clang-doc/JSONGenerator.cpp | 45 +- clang-tools-extra/clang-doc/MDGenerator.cpp | 9 +- clang-tools-extra/clang-doc/Mapper.cpp | 3 - .../clang-doc/Representation.cpp | 337 ++-------- clang-tools-extra/clang-doc/Representation.h | 191 +++--- clang-tools-extra/clang-doc/Serialize.cpp | 204 ++---- clang-tools-extra/clang-doc/Serialize.h | 18 +- clang-tools-extra/clang-doc/YAMLGenerator.cpp | 78 +-- .../benchmarks/ClangDocBenchmark.cpp | 7 +- .../clang-doc/tool/ClangDocMain.cpp | 50 +- .../unittests/clang-doc/BitcodeTest.cpp | 111 ++-- .../unittests/clang-doc/ClangDocTest.cpp | 256 +++----- .../unittests/clang-doc/ClangDocTest.h | 37 +- .../unittests/clang-doc/GeneratorTest.cpp | 6 +- .../unittests/clang-doc/JSONGeneratorTest.cpp | 83 +-- .../unittests/clang-doc/MDGeneratorTest.cpp | 73 +-- .../unittests/clang-doc/MergeTest.cpp | 325 ++++------ .../unittests/clang-doc/SerializeTest.cpp | 435 ++++++------- .../unittests/clang-doc/YAMLGeneratorTest.cpp | 110 ++-- 21 files changed, 1009 insertions(+), 1995 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index c5e848ae4c28..b7f4d6aa7ba2 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -129,15 +129,14 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field, "invalid value for FieldId"); } -static llvm::Error decodeRecord(const Record &R, OwningVec &Field, +static llvm::Error decodeRecord(const Record &R, + llvm::SmallVectorImpl &Field, llvm::StringRef Blob) { if (R[0] > INT_MAX) return llvm::createStringError(llvm::inconvertibleErrorCode(), "integer too large to parse"); - - Field.push_back(*allocatePtr(static_cast(R[0]), - static_cast(R[1]), Blob, - static_cast(R[2]))); + Field.emplace_back(static_cast(R[0]), static_cast(R[1]), Blob, + static_cast(R[2])); return llvm::Error::success(); } @@ -426,99 +425,6 @@ ClangDocBitcodeReader::parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH, } } -template -llvm::Error ClangDocBitcodeReader::parseBlock(unsigned ID, T I, - BlockBeginHandler &&BBH, - BlockEndHandler &&BEH) { - return parseBlock(ID, I, std::forward(BBH), - std::forward(BEH), - [&](unsigned Code) { return readRecord(Code, I); }); -} - -template -llvm::Expected ClangDocBitcodeReader::readSubBlockIfMatch( - unsigned ID, unsigned TargetID, llvm::SmallVectorImpl &V) { - if (ID != TargetID) - return false; - ChildType Val; - if (auto Err = readBlock(ID, &Val)) - return std::move(Err); - V.push_back(std::move(Val)); - return true; -} - -template -static llvm::Error addReference(T I, Reference &&R, FieldId F); - -template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F); -template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F); -template <> -llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F); -template <> -llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F); -template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F); -template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F); -template <> -llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F); -template <> llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F); -template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F); -template <> -llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F); -template <> -llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F); - -template -llvm::Expected ClangDocBitcodeReader::routeReferenceBlock( - unsigned ID, llvm::SmallVectorImpl &Namespaces, InfoT *I, - std::initializer_list Mappings) { - if (ID != BI_REFERENCE_BLOCK_ID) - return false; - Reference R; - if (auto Err = readBlock(ID, &R)) - return std::move(Err); - - for (const auto &Map : Mappings) { - if (CurrentReferenceField == Map.Field) { - Map.Vec->push_back(std::move(R)); - return true; - } - } - - if (CurrentReferenceField == FieldId::F_namespace) { - Namespaces.push_back(std::move(R)); - return true; - } - - if (auto Err = addReference(I, std::move(R), CurrentReferenceField)) - return std::move(Err); - - return true; -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, - TemplateSpecializationInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I); -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I); - template <> llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) { llvm::SmallVector LocalChildren; @@ -542,13 +448,25 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) { if (!LocalChildren.empty()) I->Children = allocateArray(LocalChildren, TransientArena); - if (!AttrKeys.empty()) - I->AttrKeys = allocateArray(AttrKeys, TransientArena); - if (!AttrValues.empty()) - I->AttrValues = allocateArray(AttrValues, TransientArena); - if (!Args.empty()) - I->Args = allocateArray(Args, TransientArena); - + if (!AttrKeys.empty()) { + StringRef *KeysMem = + TransientArena.Allocate(AttrKeys.size()); + std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem); + I->AttrKeys = llvm::ArrayRef(KeysMem, AttrKeys.size()); + } + if (!AttrValues.empty()) { + StringRef *ValuesMem = + TransientArena.Allocate(AttrValues.size()); + std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), + ValuesMem); + I->AttrValues = + llvm::ArrayRef(ValuesMem, AttrValues.size()); + } + if (!Args.empty()) { + StringRef *ArgsMem = TransientArena.Allocate(Args.size()); + std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem); + I->Args = llvm::ArrayRef(ArgsMem, Args.size()); + } return llvm::Error::success(); }, [&](unsigned BlockOrCode) -> llvm::Error { @@ -563,219 +481,6 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) { }); } -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) { - llvm::SmallVector LocalParams; - llvm::SmallVector LocalNamespaces; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID, - LocalParams); - if (!B) - return B.takeError(); - if (*B) - return true; - return routeReferenceBlock(BlockOrCode, LocalNamespaces, I); - }, - [&]() -> llvm::Error { - I->Params = allocateArray(LocalParams, TransientArena); - if (!LocalNamespaces.empty()) - I->Namespace = allocateArray(LocalNamespaces, TransientArena); - return llvm::Error::success(); - }); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I) { - llvm::SmallVector LocalMembers; - llvm::SmallVector LocalNamespaces; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_ENUM_VALUE_BLOCK_ID, - LocalMembers); - if (!B) - return B.takeError(); - if (*B) - return true; - return routeReferenceBlock(BlockOrCode, LocalNamespaces, I); - }, - [&]() -> llvm::Error { - I->Members = allocateArray(LocalMembers, TransientArena); - if (!LocalNamespaces.empty()) - I->Namespace = allocateArray(LocalNamespaces, TransientArena); - return llvm::Error::success(); - }); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I) { - // BaseRecordInfo and FriendInfo are over 256 bytes and require a size. - llvm::SmallVector LocalBases; - llvm::SmallVector LocalFriends; - llvm::SmallVector LocalMembers; - llvm::SmallVector LocalParents; - llvm::SmallVector LocalVirtualParents; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID, - LocalMembers); - if (!B) - return B.takeError(); - if (*B) - return true; - - B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID, - LocalBases); - if (!B) - return B.takeError(); - if (*B) - return true; - - B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends); - if (!B) - return B.takeError(); - if (*B) - return true; - - llvm::SmallVector Dummy; - return routeReferenceBlock( - BlockOrCode, Dummy, I, - {{FieldId::F_parent, &LocalParents}, - {FieldId::F_vparent, &LocalVirtualParents}}); - }, - [&]() -> llvm::Error { - if (!LocalMembers.empty()) - I->Members = allocateArray(LocalMembers, TransientArena); - if (!LocalParents.empty()) - I->Parents = allocateArray(LocalParents, TransientArena); - if (!LocalVirtualParents.empty()) - I->VirtualParents = - allocateArray(LocalVirtualParents, TransientArena); - I->Bases = allocateArray(LocalBases, TransientArena); - I->Friends = allocateArray(LocalFriends, TransientArena); - return llvm::Error::success(); - }); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I) { - llvm::SmallVector LocalBases; - llvm::SmallVector LocalFriends; - llvm::SmallVector LocalMembers; - llvm::SmallVector LocalParents; - llvm::SmallVector LocalVirtualParents; - llvm::SmallVector LocalNamespaces; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID, - LocalMembers); - if (!B) - return B.takeError(); - if (*B) - return true; - - B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID, - LocalBases); - if (!B) - return B.takeError(); - if (*B) - return true; - - B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends); - if (!B) - return B.takeError(); - if (*B) - return true; - - return routeReferenceBlock( - BlockOrCode, LocalNamespaces, I, - {{FieldId::F_parent, &LocalParents}, - {FieldId::F_vparent, &LocalVirtualParents}}); - }, - [&]() -> llvm::Error { - if (!LocalMembers.empty()) - I->Members = allocateArray(LocalMembers, TransientArena); - if (!LocalParents.empty()) - I->Parents = allocateArray(LocalParents, TransientArena); - if (!LocalVirtualParents.empty()) - I->VirtualParents = - allocateArray(LocalVirtualParents, TransientArena); - if (!LocalNamespaces.empty()) - I->Namespace = allocateArray(LocalNamespaces, TransientArena); - I->Bases = allocateArray(LocalBases, TransientArena); - I->Friends = allocateArray(LocalFriends, TransientArena); - return llvm::Error::success(); - }); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I) { - llvm::SmallVector LocalParams; - llvm::SmallVector LocalConstraints; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID, - LocalParams); - if (!B) - return B.takeError(); - if (*B) - return true; - - B = readSubBlockIfMatch(BlockOrCode, BI_CONSTRAINT_BLOCK_ID, - LocalConstraints); - if (!B) - return B.takeError(); - if (*B) - return true; - - return false; - }, - [&]() -> llvm::Error { - I->Params = allocateArray(LocalParams, TransientArena); - I->Constraints = allocateArray(LocalConstraints, TransientArena); - return llvm::Error::success(); - }, - [&](unsigned BlockOrCode) -> llvm::Error { - return readRecord(BlockOrCode, I); - }); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, - TemplateSpecializationInfo *I) { - llvm::SmallVector LocalParams; - - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID, - LocalParams); - if (!B) - return B.takeError(); - if (*B) - return true; - - return false; - }, - [&]() -> llvm::Error { - I->Params = allocateArray(LocalParams, TransientArena); - return llvm::Error::success(); - }, - [&](unsigned BlockOrCode) -> llvm::Error { - return readRecord(BlockOrCode, I); - }); -} - static llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, Reference *I, FieldId &F) { switch (ID) { @@ -874,25 +579,51 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob, "invalid field for Friend"); } -template -struct has_description : std::false_type {}; -template -struct has_description().Description)>> - : std::true_type {}; - template static llvm::Expected getCommentInfo(T I) { - if constexpr (std::is_pointer_v) { - using Pointee = std::remove_pointer_t; - if constexpr (has_description::value) { - auto *NewComment = allocatePtr(); - I->Description.push_back(*NewComment); - return NewComment; - } - } return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain CommentInfo"); } +template <> llvm::Expected getCommentInfo(FunctionInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(NamespaceInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(RecordInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(MemberTypeInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(EnumInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(TypedefInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(EnumValueInfo *I) { + return &I->Description.emplace_back(); +} + +template <> llvm::Expected getCommentInfo(ConceptInfo *I) { + return &I->Description.emplace_back(); +} + +template <> Expected getCommentInfo(VarInfo *I) { + return &I->Description.emplace_back(); +} + +template <> Expected getCommentInfo(FriendInfo *I) { + return &I->Description.emplace_back(); +} + // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on // the parent block to set it. The template specializations define what to do // for each supported parent block. @@ -902,11 +633,26 @@ static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) { "invalid type cannot contain TypeInfo"); } +template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) { + I->Members.emplace_back(std::move(T)); + return llvm::Error::success(); +} + +template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) { + I->Members.emplace_back(std::move(T)); + return llvm::Error::success(); +} + template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) { I->ReturnType = std::move(T); return llvm::Error::success(); } +template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { + I->Params.emplace_back(std::move(T)); + return llvm::Error::success(); +} + template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) { I->ReturnType.emplace(std::move(T)); return llvm::Error::success(); @@ -935,6 +681,9 @@ static llvm::Error addReference(T I, Reference &&R, FieldId F) { template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) { switch (F) { + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); + return llvm::Error::success(); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "VarInfo cannot contain this Reference"); @@ -978,6 +727,9 @@ llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) { template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) { switch (F) { + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); + return llvm::Error::success(); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain Reference"); @@ -986,6 +738,9 @@ template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) { template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) { switch (F) { + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); + return llvm::Error::success(); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain Reference"); @@ -995,13 +750,16 @@ template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) { template <> llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) { switch (F) { - case FieldId::F_child_namespace: - I->Children.Namespaces.push_back( - *allocatePtr(TransientArena, std::move(R))); + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); return llvm::Error::success(); + case FieldId::F_child_namespace: { + Reference *NewR = allocatePtr(TransientArena, std::move(R)); + I->Children.Namespaces.push_back(*NewR); + return llvm::Error::success(); + } case FieldId::F_child_record: - I->Children.Records.push_back( - *allocatePtr(TransientArena, std::move(R))); + I->Children.Records.emplace_back(std::move(R)); return llvm::Error::success(); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -1012,6 +770,9 @@ llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) { template <> llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) { switch (F) { + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); + return llvm::Error::success(); case FieldId::F_parent: I->Parent = std::move(R); return llvm::Error::success(); @@ -1023,9 +784,17 @@ llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) { template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { switch (F) { + case FieldId::F_namespace: + I->Namespace.emplace_back(std::move(R)); + return llvm::Error::success(); + case FieldId::F_parent: + I->Parents.emplace_back(std::move(R)); + return llvm::Error::success(); + case FieldId::F_vparent: + I->VirtualParents.emplace_back(std::move(R)); + return llvm::Error::success(); case FieldId::F_child_record: - I->Children.Records.push_back( - *allocatePtr(TransientArena, std::move(R))); + I->Children.Records.emplace_back(std::move(R)); return llvm::Error::success(); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -1054,42 +823,54 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) { "Friend cannot contain this Reference"); } -static auto &getList(ScopeChildren &C, FunctionInfo *) { return C.Functions; } -static auto &getList(ScopeChildren &C, EnumInfo *) { return C.Enums; } -static auto &getList(ScopeChildren &C, TypedefInfo *) { return C.Typedefs; } -static auto &getList(ScopeChildren &C, ConceptInfo *) { return C.Concepts; } -static auto &getList(ScopeChildren &C, VarInfo *) { return C.Variables; } - -template struct has_children : std::false_type {}; -template -struct has_children().Children)>> - : std::is_same().Children), ScopeChildren> {}; - -template -struct is_valid_child : std::false_type {}; -template -struct is_valid_child< - TargetChild, std::void_t(), - std::declval()))>> - : std::true_type {}; - -template -static void addChild(Target I, Child &&R) { - if constexpr (std::is_pointer_v) { - using Pointee = std::remove_pointer_t; - if constexpr (has_children::value) { - using BareChild = std::remove_cv_t>; - if constexpr (is_valid_child::value) { - auto *Node = allocatePtr(std::move(R)); - getList(I->Children, Node).push_back(*Node); - return; - } - } - } +template +static void addChild(T I, ChildInfoType &&R) { ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid child type for info")); } +// Namespace children: +template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) { + I->Children.Functions.emplace_back(std::move(R)); +} +template <> void addChild(NamespaceInfo *I, EnumInfo &&R) { + I->Children.Enums.emplace_back(std::move(R)); +} +template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { + I->Children.Typedefs.emplace_back(std::move(R)); +} +template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) { + I->Children.Concepts.emplace_back(std::move(R)); +} +template <> void addChild(NamespaceInfo *I, VarInfo &&R) { + I->Children.Variables.emplace_back(std::move(R)); +} + +// Record children: +template <> void addChild(RecordInfo *I, FunctionInfo &&R) { + I->Children.Functions.emplace_back(std::move(R)); +} +template <> void addChild(RecordInfo *I, EnumInfo &&R) { + I->Children.Enums.emplace_back(std::move(R)); +} +template <> void addChild(RecordInfo *I, TypedefInfo &&R) { + I->Children.Typedefs.emplace_back(std::move(R)); +} +template <> void addChild(RecordInfo *I, FriendInfo &&R) { + I->Friends.emplace_back(std::move(R)); +} + +// Other types of children: +template <> void addChild(EnumInfo *I, EnumValueInfo &&R) { + I->Members.emplace_back(std::move(R)); +} +template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) { + I->Bases.emplace_back(std::move(R)); +} +template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) { + I->Children.Functions.emplace_back(std::move(R)); +} + // TemplateParam children. These go into either a TemplateInfo (for template // parameters) or TemplateSpecializationInfo (for the specialization's // parameters). @@ -1098,6 +879,13 @@ template static void addTemplateParam(T I, TemplateParamInfo &&P) { llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid container for template parameter")); } +template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) { + I->Params.emplace_back(std::move(P)); +} +template <> +void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) { + I->Params.emplace_back(std::move(P)); +} // Template info. These apply to either records or functions. template static void addTemplate(T I, TemplateInfo &&P) { @@ -1137,6 +925,9 @@ template static void addConstraint(T I, ConstraintInfo &&C) { ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid container for constraint info")); } +template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) { + I->Constraints.emplace_back(std::move(C)); +} // Read records from bitcode into a given info. template @@ -1161,37 +952,6 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) { } // Read a block of records into a single info. - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I) { - return readBlockWithNamespace(ID, I); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I) { - return readBlockWithNamespace(ID, I); -} - -template <> -llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I) { - return readBlockWithNamespace(ID, I); -} - -template -llvm::Error ClangDocBitcodeReader::readBlockWithNamespace(unsigned ID, T I) { - llvm::SmallVector LocalNamespaces; - return parseBlock( - ID, I, - [&](unsigned BlockOrCode) -> llvm::Expected { - return routeReferenceBlock(BlockOrCode, LocalNamespaces, I); - }, - [&]() -> llvm::Error { - if (!LocalNamespaces.empty()) - I->Namespace = allocateArray(LocalNamespaces, TransientArena); - return llvm::Error::success(); - }); -} - template llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { return parseBlock( @@ -1209,13 +969,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) { return parseBlock( ID, I, [&](unsigned BlockOrCode) -> llvm::Expected { - auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID, - LocalParams); - if (!B) - return B.takeError(); - if (*B) + if (BlockOrCode == BI_FIELD_TYPE_BLOCK_ID) { + FieldTypeInfo FI; + if (auto Err = readBlock(BlockOrCode, &FI)) + return std::move(Err); + LocalParams.push_back(std::move(FI)); return true; - + } return false; }, [&]() -> llvm::Error { @@ -1228,19 +988,27 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) { }); } +// TODO: fix inconsistentent returning of errors in add callbacks. +// Once that's fixed, we only need one handleSubBlock. template llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent, Callback Function) { InfoType Info; if (auto Err = readBlock(ID, &Info)) return Err; - if constexpr (std::is_void_v< - std::invoke_result_t>) { - Function(Parent, std::move(Info)); - return llvm::Error::success(); - } else { - return Function(Parent, std::move(Info)); - } + Function(Parent, std::move(Info)); + return llvm::Error::success(); +} + +template +llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent, + Callback Function) { + InfoType Info; + if (auto Err = readBlock(ID, &Info)) + return Err; + if (auto Err = Function(Parent, std::move(Info))) + return Err; + return llvm::Error::success(); } template @@ -1264,15 +1032,15 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { return llvm::Error::success(); } case BI_TYPE_BLOCK_ID: { - return handleSubBlock(ID, I, - CreateAddFunc(addTypeInfo)); + return handleTypeSubBlock( + ID, I, CreateAddFunc(addTypeInfo)); } case BI_FIELD_TYPE_BLOCK_ID: { - return handleSubBlock( + return handleTypeSubBlock( ID, I, CreateAddFunc(addTypeInfo)); } case BI_MEMBER_TYPE_BLOCK_ID: { - return handleSubBlock( + return handleTypeSubBlock( ID, I, CreateAddFunc(addTypeInfo)); } case BI_REFERENCE_BLOCK_ID: { diff --git a/clang-tools-extra/clang-doc/BitcodeReader.h b/clang-tools-extra/clang-doc/BitcodeReader.h index 4585cb454f40..d3499fdee0f5 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.h +++ b/clang-tools-extra/clang-doc/BitcodeReader.h @@ -44,32 +44,12 @@ private: // Read a block of records into a single Info struct, calls readRecord on each // record found. template llvm::Error readBlock(unsigned ID, T I); - template llvm::Error readBlockWithNamespace(unsigned ID, T I); template llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH, BlockEndHandler &&BEH, RecordHandler &&RH); - template - llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH, - BlockEndHandler &&BEH); - - template - llvm::Expected readSubBlockIfMatch(unsigned ID, unsigned TargetID, - llvm::SmallVectorImpl &V); - - struct ReferenceMap { - FieldId Field; - llvm::SmallVectorImpl *Vec; - }; - - template - llvm::Expected - routeReferenceBlock(unsigned ID, llvm::SmallVectorImpl &Namespaces, - InfoT *I, - std::initializer_list Mappings = {}); - // Step through a block of records to find the next data field. template llvm::Error readSubBlock(unsigned ID, T I); diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 4854c6114b76..e895d641a600 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -27,7 +27,6 @@ class JSONGenerator : public Generator { void serializeCommonChildren( const ScopeChildren &Children, json::Object &Obj, std::optional MDReferenceLambda = std::nullopt); - void serializeContexts(Info *I, llvm::StringMap> &Infos); void serializeInfo(const ConstraintInfo &I, Object &Obj); void serializeInfo(const TemplateInfo &Template, Object &Obj); void serializeInfo(const ConceptInfo &I, Object &Obj); @@ -62,12 +61,10 @@ class JSONGenerator : public Generator { }; } - llvm::DenseMap> ContextsMap; - const ClangDocContext *CDCtx; - bool Markdown; - public: static const char *Format; + const ClangDocContext *CDCtx; + bool Markdown; Error generateDocumentation(StringRef RootDir, llvm::StringMap> Infos, @@ -323,20 +320,13 @@ static Object serializeComment(const CommentInfo &I, Object &Description) { /// Creates Contexts for namespaces and records to allow for navigation. void JSONGenerator::generateContext(const Info &I, Object &Obj) { - Obj["Contexts"] = json::Array(); - Obj["HasContexts"] = true; - - auto It = ContextsMap.find(&I); - if (It == ContextsMap.end() || It->second.empty()) - return; - - auto &ContextArrayRef = *Obj["Contexts"].getAsArray(); - const auto &Contexts = It->second; - ContextArrayRef.reserve(Contexts.size()); + json::Value ContextArray = json::Array(); + auto &ContextArrayRef = *ContextArray.getAsArray(); + ContextArrayRef.reserve(I.Contexts.size()); std::string CurrentRelativePath; bool PreviousRecord = false; - for (const auto &Current : Contexts) { + for (const auto &Current : I.Contexts) { json::Value ContextVal = Object(); Object &Context = *ContextVal.getAsObject(); serializeReference(Current, Context); @@ -382,9 +372,11 @@ void JSONGenerator::generateContext(const Info &I, Object &Obj) { } ContextArrayRef.back().getAsObject()->insert({"End", true}); + Obj["Contexts"] = ContextArray; + Obj["HasContexts"] = true; } -static void serializeDescription(const OwningVec &Description, +static void serializeDescription(llvm::ArrayRef Description, json::Object &Obj, StringRef Key = "") { if (Description.empty()) return; @@ -437,8 +429,7 @@ void JSONGenerator::serializeCommonAttributes(const Info &I, Obj["Location"] = serializeLocation(Symbol->DefLoc.value()); } - auto It = ContextsMap.find(&I); - if (It != ContextsMap.end() && !It->second.empty()) + if (!I.Contexts.empty()) generateContext(I, Obj); } @@ -835,9 +826,9 @@ SmallString<16> JSONGenerator::determineFileName(Info *I, /// \param CDCtxIndex Passed by copy since clang-doc's context is passed to the /// generator as `const` -static std::vector preprocessCDCtxIndex(Index CDCtxIndex) { +static OwningVec preprocessCDCtxIndex(Index CDCtxIndex) { CDCtxIndex.sort(); - std::vector Processed; + OwningVec Processed; Processed.reserve(CDCtxIndex.Children.size()); for (const auto *Idx : CDCtxIndex.getSortedChildren()) { Index NewIdx = *Idx; @@ -857,7 +848,7 @@ Error JSONGenerator::serializeAllFiles(const ClangDocContext &CDCtx, StringRef RootDir) { json::Value ObjVal = Object(); Object &Obj = *ObjVal.getAsObject(); - std::vector IndexCopy = preprocessCDCtxIndex(CDCtx.Idx); + OwningVec IndexCopy = preprocessCDCtxIndex(CDCtx.Idx); serializeArray(IndexCopy, Obj, "Index", serializeReferenceLambda()); SmallString<128> Path; sys::path::append(Path, RootDir, "json", "all_files.json"); @@ -920,12 +911,10 @@ Error JSONGenerator::serializeIndex(StringRef RootDir) { return Error::success(); } -void JSONGenerator::serializeContexts(Info *I, - StringMap> &Infos) { +static void serializeContexts(Info *I, StringMap> &Infos) { if (I->USR == GlobalNamespaceID) return; auto ParentUSR = I->ParentUSR; - auto &LocalContexts = ContextsMap[I]; while (true) { // Infos may not have the ParentUSR, if its been filtered (public or path), @@ -939,12 +928,12 @@ void JSONGenerator::serializeContexts(Info *I, Context GlobalRef(ParentInfo->USR, "Global Namespace", InfoType::IT_namespace, "GlobalNamespace", "", SmallString<16>("index")); - LocalContexts.push_back(GlobalRef); - break; + I->Contexts.push_back(GlobalRef); + return; } Context ParentRef(*ParentInfo); - LocalContexts.push_back(ParentRef); + I->Contexts.push_back(ParentRef); ParentUSR = ParentInfo->ParentUSR; } } diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index 9ccb7a8ccd63..b0253c5d71bf 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -31,7 +31,8 @@ static std::string genEmphasis(const Twine &Text) { return "**" + Text.str() + "**"; } -static std::string genReferenceList(llvm::ArrayRef Refs) { +static std::string +genReferenceList(const llvm::SmallVectorImpl &Refs) { std::string Buffer; llvm::raw_string_ostream Stream(Buffer); for (const auto &R : Refs) { @@ -81,7 +82,7 @@ class TableCommentWriter { public: explicit TableCommentWriter(llvm::raw_ostream &OS) : OS(OS) {} - void write(const OwningVec &Comments) { + void write(llvm::ArrayRef Comments) { for (const auto &C : Comments) writeTableSafeComment(C); @@ -435,7 +436,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) { OS << " for " << CDCtx.ProjectName; OS << "\n\n"; - std::vector Children = CDCtx.Idx.getSortedChildren(); + OwningVec Children = CDCtx.Idx.getSortedChildren(); for (const auto *C : Children) serializeReference(OS, *C, 0); @@ -454,7 +455,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) { FileErr.message()); CDCtx.Idx.sort(); OS << "# " << CDCtx.ProjectName << " C/C++ Reference\n\n"; - std::vector Children = CDCtx.Idx.getSortedChildren(); + OwningVec Children = CDCtx.Idx.getSortedChildren(); for (const auto *C : Children) { if (!C->Children.empty()) { const char *Type; diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 499ab5638b34..583a0fe43b40 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -43,9 +43,6 @@ void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) { if (CDCtx.FTimeTrace) llvm::timeTraceProfilerInitialize(200, "clang-doc"); TraverseDecl(Context.getTranslationUnitDecl()); - - TransientArena.Reset(); - if (CDCtx.FTimeTrace) llvm::timeTraceProfilerFinishThread(); } diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 50c5f9bb1d07..42f85c39655d 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -105,6 +105,17 @@ static llvm::Expected> reduce(OwningPtrArray &Values) { return std::move(Merged); } +// Return the index of the matching child in the vector, or -1 if merge is not +// necessary. +template +static int getChildIndexIfExists(OwningVec &Children, T &ChildToMerge) { + for (unsigned long I = 0; I < Children.size(); I++) { + if (ChildToMerge.USR == Children[I].USR) + return I; + } + return -1; +} + template static void reduceChildren(llvm::simple_ilist &Children, llvm::simple_ilist &&ChildrenToMerge) { @@ -115,145 +126,34 @@ static void reduceChildren(llvm::simple_ilist &Children, auto It = llvm::find_if( Children, [&](const T &C) { return C.USR == ChildToMerge->USR; }); if (It == Children.end()) { - T *NewChild = allocatePtr(PersistentArena, ChildToMerge->USR); - NewChild->merge(std::move(*ChildToMerge)); - Children.push_back(*NewChild); + Children.push_back(*ChildToMerge); } else { It->merge(std::move(*ChildToMerge)); } } } -template <> -void reduceChildren( - llvm::simple_ilist &Children, - llvm::simple_ilist &&ChildrenToMerge) { - while (!ChildrenToMerge.empty()) { - Reference *ChildToMerge = &ChildrenToMerge.front(); - ChildrenToMerge.pop_front(); - - auto It = llvm::find_if(Children, [&](const Reference &C) { - return C.USR == ChildToMerge->USR; - }); - if (It == Children.end()) { - Reference *NewChild = allocatePtr(PersistentArena); - NewChild->USR = ChildToMerge->USR; - NewChild->RefType = ChildToMerge->RefType; - NewChild->merge(std::move(*ChildToMerge)); - Children.push_back(*NewChild); - } else { - It->merge(std::move(*ChildToMerge)); +template +static void reduceChildren(OwningVec &Children, + OwningVec &&ChildrenToMerge) { + for (auto &ChildToMerge : ChildrenToMerge) { + int MergeIdx = getChildIndexIfExists(Children, ChildToMerge); + if (MergeIdx == -1) { + Children.push_back(std::move(ChildToMerge)); + continue; } + Children[MergeIdx].merge(std::move(ChildToMerge)); } } template static void mergeUnkeyed(Container &Target, Container &&Source) { - using T = typename Container::value_type; - while (!Source.empty()) { - auto &Item = Source.front(); - Source.pop_front(); - if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) { - T *NewItem = allocatePtr(PersistentArena, Item); - Target.push_back(*NewItem); - } + for (auto &Item : Source) { + if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) + Target.push_back(std::move(Item)); } } -template <> -void mergeUnkeyed>(OwningVec &Target, - OwningVec &&Source) { - while (!Source.empty()) { - auto &Item = Source.front(); - Source.pop_front(); - if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) { - CommentInfo *NewItem = - allocatePtr(PersistentArena, Item, PersistentArena); - Target.push_back(*NewItem); - } - } -} - -llvm::Error mergeSingleInfo(doc::OwnedPtr &Reduced, - doc::OwnedPtr &&NewInfo, - llvm::BumpPtrAllocator &Arena) { - if (!Reduced) { - switch (NewInfo->IT) { - case InfoType::IT_namespace: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_record: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_enum: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_function: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_typedef: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_concept: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_variable: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - case InfoType::IT_friend: - Reduced = allocatePtr(Arena, NewInfo->USR); - break; - default: - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "unknown info type"); - } - } - - if (Reduced->IT != NewInfo->IT) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "info types mismatch"); - - switch (Reduced->IT) { - case InfoType::IT_namespace: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_record: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_enum: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_function: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_typedef: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_concept: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_variable: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - case InfoType::IT_friend: - static_cast(getPtr(Reduced)) - ->merge(std::move(*static_cast(getPtr(NewInfo)))); - break; - default: - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "unknown info type"); - } - - return llvm::Error::success(); -} - // Dispatch function. llvm::Expected> mergeInfos(OwningPtrArray &Values) { if (Values.empty() || !Values[0]) @@ -284,20 +184,6 @@ llvm::Expected> mergeInfos(OwningPtrArray &Values) { llvm_unreachable("unhandled enumerator"); } -TemplateSpecializationInfo::TemplateSpecializationInfo( - const TemplateSpecializationInfo &Other, llvm::BumpPtrAllocator &Arena) - : SpecializationOf(Other.SpecializationOf) { - Params = allocateArray(Other.Params, Arena); -} - -TemplateInfo::TemplateInfo(const TemplateInfo &Other, - llvm::BumpPtrAllocator &Arena) { - Params = allocateArray(Other.Params, Arena); - if (Other.Specialization) - Specialization = TemplateSpecializationInfo(*Other.Specialization, Arena); - Constraints = allocateArray(Other.Constraints, Arena); -} - bool CommentInfo::operator==(const CommentInfo &Other) const { auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName, SelfClosing, Explicit, AttrKeys, AttrValues, Args); @@ -333,28 +219,6 @@ bool CommentInfo::operator<(const CommentInfo &Other) const { return false; } -CommentInfo::CommentInfo(const CommentInfo &Other, - llvm::BumpPtrAllocator &Arena) { - Kind = Other.Kind; - Direction = Other.Direction; - Name = Other.Name; - ParamName = Other.ParamName; - CloseName = Other.CloseName; - SelfClosing = Other.SelfClosing; - Explicit = Other.Explicit; - Text = Other.Text; - AttrKeys = allocateArray(Other.AttrKeys, Arena); - AttrValues = allocateArray(Other.AttrValues, Arena); - Args = allocateArray(Other.Args, Arena); - if (!Other.Children.empty()) { - CommentInfo *NewArray = Arena.Allocate(Other.Children.size()); - for (size_t Idx = 0; Idx < Other.Children.size(); ++Idx) { - new (NewArray + Idx) CommentInfo(Other.Children[Idx], Arena); - } - Children = llvm::ArrayRef(NewArray, Other.Children.size()); - } -} - static llvm::SmallString<64> calculateRelativeFilePath(const InfoType &Type, const StringRef &Path, const StringRef &Name, const StringRef &CurrentPath) { @@ -411,8 +275,6 @@ void Reference::merge(Reference &&Other) { Name = Other.Name; if (Path.empty()) Path = Other.Path; - if (QualName.empty()) - QualName = Other.QualName; if (DocumentationFileName.empty()) DocumentationFileName = Other.DocumentationFileName; } @@ -427,31 +289,6 @@ void FriendInfo::merge(FriendInfo &&Other) { SymbolInfo::merge(std::move(Other)); } -FriendInfo::FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena) - : SymbolInfo(Other, Arena) { - Ref = Other.Ref; - if (Other.Template) - Template.emplace(*Other.Template, Arena); - if (Other.ReturnType) - ReturnType = Other.ReturnType; - if (!Other.Params.empty()) - Params = allocateArray(Other.Params, Arena); - IsClass = Other.IsClass; -} - -Info::Info(const Info &Other, llvm::BumpPtrAllocator &Arena) - : Path(Other.Path), Name(Other.Name), - DocumentationFileName(Other.DocumentationFileName), USR(Other.USR), - ParentUSR(Other.ParentUSR), IT(Other.IT) { - Namespace = allocateArray(Other.Namespace, Arena); - if (!Other.Description.empty()) { - for (const auto &Desc : Other.Description) { - CommentInfo *NewDesc = allocatePtr(Arena, Desc, Arena); - Description.push_back(*NewDesc); - } - } -} - void Info::mergeBase(Info &&Other) { assert(mergeable(Other)); if (USR == EmptySID) @@ -460,8 +297,8 @@ void Info::mergeBase(Info &&Other) { Name = Other.Name; if (Path == "") Path = Other.Path; - if (Namespace.empty() && !Other.Namespace.empty()) - Namespace = allocateArray(Other.Namespace, PersistentArena); + if (Namespace.empty()) + Namespace = std::move(Other.Namespace); // Unconditionally extend the description, since each decl may have a comment. mergeUnkeyed(Description, std::move(Other.Description)); if (ParentUSR == EmptySID) @@ -474,17 +311,6 @@ bool Info::mergeable(const Info &Other) { return IT == Other.IT && USR == Other.USR; } -SymbolInfo::SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena) - : Info(Other, Arena), DefLoc(Other.DefLoc), MangledName(Other.MangledName), - IsStatic(Other.IsStatic) { - if (!Other.Loc.empty()) { - for (const auto &L : Other.Loc) { - Location *NewL = allocatePtr(Arena, L); - Loc.push_back(*NewL); - } - } -} - void SymbolInfo::merge(SymbolInfo &&Other) { assert(mergeable(Other)); if (!DefLoc) @@ -494,8 +320,6 @@ void SymbolInfo::merge(SymbolInfo &&Other) { mergeBase(std::move(Other)); if (MangledName.empty()) MangledName = std::move(Other.MangledName); - if (!IsStatic) - IsStatic = Other.IsStatic; } NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path) @@ -517,76 +341,37 @@ void NamespaceInfo::merge(NamespaceInfo &&Other) { RecordInfo::RecordInfo(SymbolID USR, StringRef Name, StringRef Path) : SymbolInfo(InfoType::IT_record, USR, Name, Path) {} -// FIXME: This constructor is currently unsafe for cross-arena copies of -// populated records. Because a default copy of ScopeChildren will shallow-copy -// the intrusive pointers, leading to a use-after-free when the TransientArena -// is reset. Subsequent patches will address this by deep-copying children -// individually via reduceChildren. -RecordInfo::RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena) - : SymbolInfo(Other, Arena), TagType(Other.TagType), - IsTypeDef(Other.IsTypeDef) { - Members = deepCopyArray(Other.Members, Arena); - Parents = allocateArray(Other.Parents, Arena); - VirtualParents = allocateArray(Other.VirtualParents, Arena); - Bases = deepCopyArray(Other.Bases, Arena); - Friends = deepCopyArray(Other.Friends, Arena); -} - -MemberTypeInfo::MemberTypeInfo(const MemberTypeInfo &Other, - llvm::BumpPtrAllocator &Arena) - : FieldTypeInfo(Other), Access(Other.Access), IsStatic(Other.IsStatic) { - if (!Other.Description.empty()) { - for (const auto &Desc : Other.Description) { - CommentInfo *NewDesc = allocatePtr(Arena, Desc, Arena); - Description.push_back(*NewDesc); - } - } -} - void RecordInfo::merge(RecordInfo &&Other) { assert(mergeable(Other)); if (!llvm::to_underlying(TagType)) TagType = Other.TagType; IsTypeDef = IsTypeDef || Other.IsTypeDef; - if (Members.empty() && !Other.Members.empty()) - Members = deepCopyArray(Other.Members, PersistentArena); - if (Bases.empty() && !Other.Bases.empty()) - Bases = deepCopyArray(Other.Bases, PersistentArena); - if (Parents.empty() && !Other.Parents.empty()) - Parents = allocateArray(Other.Parents, PersistentArena); - if (VirtualParents.empty() && !Other.VirtualParents.empty()) - VirtualParents = allocateArray(Other.VirtualParents, PersistentArena); - if (Friends.empty() && !Other.Friends.empty()) - Friends = deepCopyArray(Other.Friends, PersistentArena); + if (Members.empty()) + Members = std::move(Other.Members); + if (Bases.empty()) + Bases = std::move(Other.Bases); + if (Parents.empty()) + Parents = std::move(Other.Parents); + if (VirtualParents.empty()) + VirtualParents = std::move(Other.VirtualParents); + if (Friends.empty()) + Friends = std::move(Other.Friends); // Reduce children if necessary. reduceChildren(Children.Records, std::move(Other.Children.Records)); reduceChildren(Children.Functions, std::move(Other.Children.Functions)); reduceChildren(Children.Enums, std::move(Other.Children.Enums)); reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs)); SymbolInfo::merge(std::move(Other)); - if (!Template && Other.Template) - Template = TemplateInfo(*Other.Template, PersistentArena); -} - -EnumValueInfo::EnumValueInfo(const EnumValueInfo &Other, - llvm::BumpPtrAllocator &Arena) - : Name(Other.Name), Value(Other.Value), ValueExpr(Other.ValueExpr) { - if (!Other.Description.empty()) { - for (const auto &Desc : Other.Description) { - CommentInfo *NewDesc = allocatePtr(Arena, Desc, Arena); - Description.push_back(*NewDesc); - } - } + if (!Template) + Template = Other.Template; } void EnumInfo::merge(EnumInfo &&Other) { assert(mergeable(Other)); if (!Scoped) Scoped = Other.Scoped; - if (!BaseType && Other.BaseType) - BaseType = std::move(Other.BaseType); - if (Members.empty() && !Other.Members.empty()) - Members = deepCopyArray(Other.Members, PersistentArena); + if (Members.empty()) + Members = std::move(Other.Members); SymbolInfo::merge(std::move(Other)); } @@ -600,11 +385,11 @@ void FunctionInfo::merge(FunctionInfo &&Other) { ReturnType = std::move(Other.ReturnType); if (Parent.USR == EmptySID && Parent.Name == "") Parent = std::move(Other.Parent); - if (Params.empty() && !Other.Params.empty()) - Params = allocateArray(Other.Params, PersistentArena); + if (Params.empty()) + Params = std::move(Other.Params); SymbolInfo::merge(std::move(Other)); - if (!Template && Other.Template) - Template = TemplateInfo(*Other.Template, PersistentArena); + if (!Template) + Template = Other.Template; } void TypedefInfo::merge(TypedefInfo &&Other) { @@ -613,8 +398,8 @@ void TypedefInfo::merge(TypedefInfo &&Other) { IsUsing = Other.IsUsing; if (Underlying.Type.Name == "") Underlying = Other.Underlying; - if (!Template && Other.Template) - Template = TemplateInfo(*Other.Template, PersistentArena); + if (!Template) + Template = Other.Template; SymbolInfo::merge(std::move(Other)); } @@ -624,11 +409,10 @@ void ConceptInfo::merge(ConceptInfo &&Other) { IsType = Other.IsType; if (ConstraintExpression.empty()) ConstraintExpression = std::move(Other.ConstraintExpression); - if (Template.Constraints.empty() && !Other.Template.Constraints.empty()) - Template.Constraints = - allocateArray(Other.Template.Constraints, PersistentArena); - if (Template.Params.empty() && !Other.Template.Params.empty()) - Template.Params = allocateArray(Other.Template.Params, PersistentArena); + if (Template.Constraints.empty()) + Template.Constraints = std::move(Other.Template.Constraints); + if (Template.Params.empty()) + Template.Params = std::move(Other.Template.Params); SymbolInfo::merge(std::move(Other)); } @@ -643,11 +427,6 @@ void VarInfo::merge(VarInfo &&Other) { BaseRecordInfo::BaseRecordInfo() : RecordInfo() {} -BaseRecordInfo::BaseRecordInfo(const BaseRecordInfo &Other, - llvm::BumpPtrAllocator &Arena) - : RecordInfo(Other, Arena), Access(Other.Access), - IsVirtual(Other.IsVirtual), IsParent(Other.IsParent) {} - BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual, AccessSpecifier Access, bool IsParent) @@ -705,8 +484,8 @@ bool Index::operator<(const Index &Other) const { return Name < Other.Name; } -std::vector Index::getSortedChildren() const { - std::vector SortedChildren; +OwningVec Index::getSortedChildren() const { + OwningVec SortedChildren; SortedChildren.reserve(Children.size()); for (const auto &[_, C] : Children) SortedChildren.push_back(&C); @@ -750,12 +529,12 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, void ScopeChildren::sort() { Namespaces.sort(); - Records.sort(); - Functions.sort(); - Enums.sort(); - Typedefs.sort(); - Concepts.sort(); - Variables.sort(); + llvm::sort(Records); + llvm::sort(Functions); + llvm::sort(Enums); + llvm::sort(Typedefs); + llvm::sort(Concepts); + llvm::sort(Variables); } } // namespace doc } // namespace clang diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 5f404463b012..9208b77fc860 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -52,7 +52,6 @@ private: ConcurrentStringPool &getGlobalStringPool(); extern thread_local llvm::BumpPtrAllocator TransientArena; -extern thread_local llvm::BumpPtrAllocator PersistentArena; inline StringRef internString(const Twine &T) { if (T.isTriviallyEmpty()) @@ -73,8 +72,8 @@ inline StringRef internString(const Twine &T) { } template -llvm::ArrayRef allocateArray(llvm::SmallVectorImpl &V, - llvm::BumpPtrAllocator &Alloc) { +inline llvm::ArrayRef allocateArray(llvm::ArrayRef V, + llvm::BumpPtrAllocator &Alloc) { if (V.empty()) return llvm::ArrayRef(); T *Allocated = (T *)Alloc.Allocate(V.size()); @@ -82,31 +81,9 @@ llvm::ArrayRef allocateArray(llvm::SmallVectorImpl &V, return llvm::ArrayRef(Allocated, V.size()); } -template -llvm::ArrayRef allocateArray(llvm::ArrayRef V, - llvm::BumpPtrAllocator &Alloc) { - if (V.empty()) - return llvm::ArrayRef(); - T *Allocated = (T *)Alloc.Allocate(V.size()); - std::uninitialized_copy(V.begin(), V.end(), Allocated); - return llvm::ArrayRef(Allocated, V.size()); -} - -template -llvm::ArrayRef deepCopyArray(llvm::ArrayRef V, - llvm::BumpPtrAllocator &Alloc) { - if (V.empty()) - return llvm::ArrayRef(); - T *Allocated = (T *)Alloc.Allocate(V.size()); - for (size_t Idx = 0; Idx < V.size(); ++Idx) { - new (Allocated + Idx) T(V[Idx], Alloc); - } - return llvm::ArrayRef(Allocated, V.size()); -} - // An abstraction for owned pointers. Initially mapped to OwnedPtr, // to be eventually transitioned to bare pointers in an arena. -template using OwnedPtr = T *; +template using OwnedPtr = std::unique_ptr; // An abstraction for vectors that are populated and read sequentially. // To be eventually transitioned to llvm::ArrayRef for arena storage. @@ -114,7 +91,7 @@ template using OwningArray = std::vector; // An abstraction for lists that are dynamically managed (inserted/removed). // To be eventually transitioned to llvm::simple_ilist. -template using OwningVec = llvm::simple_ilist; +template using OwningVec = std::vector; // An abstraction for dynamic lists of owned pointers. // To be eventually transitioned to llvm::simple_ilist or similar. @@ -128,10 +105,9 @@ template using OwningPtrArray = std::vector>; // allocation mechanism. template OwnedPtr allocatePtr(Args &&...args) { - return new (TransientArena.Allocate()) T(std::forward(args)...); + return std::make_unique(std::forward(args)...); } -// An overload to explicitly allocate on an arena, returning a bare pointer. template T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) { return new (Alloc.Allocate()) T(std::forward(args)...); @@ -139,7 +115,7 @@ T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) { // A helper function to access the underlying pointer from an owned pointer, // abstracting away the pointer dereferencing mechanism. -template T *getPtr(const OwnedPtr &O) { return O; } +template T *getPtr(const OwnedPtr &O) { return O.get(); } // SHA1'd hash of a USR. using SymbolID = std::array; @@ -193,7 +169,6 @@ struct CommentInfo : public llvm::ilist_node { CommentInfo() = default; CommentInfo(const CommentInfo &Other) = default; CommentInfo &operator=(const CommentInfo &Other) = default; - CommentInfo(const CommentInfo &Other, llvm::BumpPtrAllocator &Arena); CommentInfo(CommentInfo &&Other) = default; CommentInfo &operator=(CommentInfo &&Other) = default; @@ -219,11 +194,11 @@ struct CommentInfo : public llvm::ilist_node { llvm::ArrayRef Children; // List of child comments for this CommentInfo. - StringRef Direction = {}; // Parameter direction (for (T)ParamCommand). - StringRef Name = {}; // Name of the comment (for Verbatim and HTML). - StringRef ParamName = {}; // Parameter name (for (T)ParamCommand). - StringRef CloseName = {}; // Closing tag name (for VerbatimBlock). - StringRef Text = {}; // Text of the comment. + StringRef Direction; // Parameter direction (for (T)ParamCommand). + StringRef Name; // Name of the comment (for Verbatim and HTML). + StringRef ParamName; // Parameter name (for (T)ParamCommand). + StringRef CloseName; // Closing tag name (for VerbatimBlock). + StringRef Text; // Text of the comment. llvm::ArrayRef AttrKeys; // List of attribute keys (for HTML). llvm::ArrayRef AttrValues; // List of attribute values for each key (for HTML). @@ -285,17 +260,17 @@ struct Reference : public llvm::ilist_node { // Name of type (possibly unresolved). Not including namespaces or template // parameters (so for a std::vector this would be "vector"). See also // QualName. - StringRef Name = {}; + StringRef Name; // Full qualified name of this type, including namespaces and template // parameter (for example this could be "std::vector"). Contrast to // Name. - StringRef QualName = {}; + StringRef QualName; // Path of directory where the clang-doc generated file will be saved // (possibly unresolved) - StringRef Path = {}; - StringRef DocumentationFileName = {}; + StringRef Path; + StringRef DocumentationFileName; }; // A Context is a reference that holds a relative path from a certain Info's @@ -305,7 +280,7 @@ struct Context : public Reference { StringRef Path, StringRef DocumentationFileName) : Reference(USR, Name, IT, QualName, Path, DocumentationFileName) {} explicit Context(const Info &I); - StringRef RelativePath = {}; + StringRef RelativePath; }; // Holds the children of a record or namespace. @@ -317,7 +292,7 @@ struct ScopeChildren { // // Namespaces are not syntactically valid as children of records, but making // this general for all possible container types reduces code complexity. - OwningVec Namespaces; + llvm::simple_ilist Namespaces; OwningVec Records; OwningVec Functions; OwningVec Enums; @@ -359,19 +334,15 @@ struct TemplateParamInfo { // The literal contents of the code for that specifies this template parameter // for this declaration. Typical values will be "class T" and // "typename T = int". - StringRef Contents = {}; + StringRef Contents; }; struct TemplateSpecializationInfo { - TemplateSpecializationInfo() = default; - TemplateSpecializationInfo(const TemplateSpecializationInfo &Other, - llvm::BumpPtrAllocator &Arena); - // Indicates the declaration that this specializes. SymbolID SpecializationOf; // Template parameters applying to the specialized record/function. - llvm::ArrayRef Params; + OwningVec Params; }; struct ConstraintInfo { @@ -380,21 +351,18 @@ struct ConstraintInfo { : ConceptRef(USR, Name, InfoType::IT_concept) {} Reference ConceptRef; - StringRef ConstraintExpr = {}; + StringRef ConstraintExpr; }; // Records the template information for a struct or function that is a template // or an explicit template specialization. struct TemplateInfo { - TemplateInfo() = default; - TemplateInfo(const TemplateInfo &Other, llvm::BumpPtrAllocator &Arena); - // May be empty for non-partial specializations. - llvm::ArrayRef Params; + OwningVec Params; // Set when this is a specialization of another record/function. std::optional Specialization; - llvm::ArrayRef Constraints; + OwningVec Constraints; }; // Info for field types. @@ -410,27 +378,24 @@ struct FieldTypeInfo : public TypeInfo { std::tie(Other.Type, Other.Name, Other.DefaultValue); } - StringRef Name = {}; // Name associated with this info. + StringRef Name; // Name associated with this info. // When used for function parameters, contains the string representing the // expression of the default value, if any. - StringRef DefaultValue = {}; + StringRef DefaultValue; }; // Info for member types. struct MemberTypeInfo : public FieldTypeInfo { MemberTypeInfo() = default; - MemberTypeInfo(const MemberTypeInfo &Other, llvm::BumpPtrAllocator &Arena); MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access, bool IsStatic = false) : FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {} bool operator==(const MemberTypeInfo &Other) const { - if (std::tie(Type, Name, Access, IsStatic) != - std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic)) - return false; - return std::equal(Description.begin(), Description.end(), - Other.Description.begin(), Other.Description.end()); + return std::tie(Type, Name, Access, IsStatic, Description) == + std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic, + Other.Description); } OwningVec Description; @@ -465,7 +430,7 @@ struct Location : public llvm::ilist_node { std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); } - StringRef Filename = {}; + StringRef Filename; int StartLineNumber = 0; int EndLineNumber = 0; bool IsFileInRootDir = false; @@ -477,9 +442,9 @@ struct Info { StringRef Name = StringRef(), StringRef Path = StringRef()) : Path(internString(Path)), Name(internString(Name)), USR(USR), IT(IT) {} - Info(const Info &Other, llvm::BumpPtrAllocator &Arena); Info(const Info &Other) = delete; Info(Info &&Other) = default; + virtual ~Info() = default; Info &operator=(Info &&Other) = default; @@ -495,18 +460,18 @@ struct Info { StringRef getFileBaseName() const; // Path of directory where the clang-doc generated file will be saved. - StringRef Path = {}; + StringRef Path; // Unqualified name of the decl. - StringRef Name = {}; + StringRef Name; // The name used for the file that this info is documented in. // In the JSON generator, infos are documented in files with mangled names. // Thus, we keep track of the physical filename for linking purposes. - StringRef DocumentationFileName = {}; + StringRef DocumentationFileName; // List of parent namespaces for this decl. - llvm::ArrayRef Namespace; + llvm::SmallVector Namespace; // Unique identifier for the decl described by this Info. SymbolID USR = SymbolID(); @@ -519,6 +484,8 @@ struct Info { // Comment description of this decl. OwningVec Description; + + SmallVector Contexts; }; inline Context::Context(const Info &I) @@ -540,8 +507,6 @@ struct SymbolInfo : public Info { StringRef Name = StringRef(), StringRef Path = StringRef()) : Info(IT, USR, Name, Path) {} - SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena); - void merge(SymbolInfo &&I); bool operator<(const SymbolInfo &Other) const { @@ -549,9 +514,8 @@ struct SymbolInfo : public Info { // generated in the order of the source code. // If the declaration location is the same, or not present // we sort by defined location otherwise fallback to the extracted name - if (Loc.size() > 0 && Other.Loc.size() > 0 && - Loc.front() != Other.Loc.front()) - return Loc.front() < Other.Loc.front(); + if (Loc.size() > 0 && Other.Loc.size() > 0 && Loc[0] != Other.Loc[0]) + return Loc[0] < Other.Loc[0]; if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc) return *DefLoc < *Other.DefLoc; @@ -560,8 +524,8 @@ struct SymbolInfo : public Info { } std::optional DefLoc; // Location where this decl is defined. - OwningVec Loc; // Locations where this decl is declared. - StringRef MangledName = {}; + llvm::SmallVector Loc; // Locations where this decl is declared. + StringRef MangledName; bool IsStatic = false; }; @@ -571,7 +535,6 @@ struct FriendInfo : public SymbolInfo, public llvm::ilist_node { FriendInfo(const InfoType IT, const SymbolID &USR, const StringRef Name = StringRef()) : SymbolInfo(IT, USR, Name) {} - FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena); bool mergeable(const FriendInfo &Other); void merge(FriendInfo &&Other); @@ -601,8 +564,8 @@ struct FunctionInfo : public SymbolInfo, public llvm::ilist_node { Reference Parent; TypeInfo ReturnType; - llvm::ArrayRef Params; - StringRef Prototype = {}; + llvm::SmallVector Params; + StringRef Prototype; // When present, this function is a template or specialization. std::optional Template; @@ -623,8 +586,6 @@ struct RecordInfo : public SymbolInfo { RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()); - RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena); - void merge(RecordInfo &&I); // Type of this record (struct, class, union, interface). @@ -639,18 +600,18 @@ struct RecordInfo : public SymbolInfo { // When present, this record is a template or specialization. std::optional Template; - llvm::ArrayRef Members; // List of info about record members. - llvm::ArrayRef Parents; // List of base/parent records - // (does not include virtual - // parents). - llvm::ArrayRef + llvm::SmallVector + Members; // List of info about record members. + llvm::SmallVector Parents; // List of base/parent records + // (does not include virtual + // parents). + llvm::SmallVector VirtualParents; // List of virtual base/parent records. - llvm::ArrayRef - Bases; // List of base/parent records; this includes - // inherited methods and attributes + OwningVec Bases; // List of base/parent records; this includes + // inherited methods and attributes - llvm::ArrayRef Friends; + OwningVec Friends; ScopeChildren Children; }; @@ -668,7 +629,7 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node { std::optional Template; // Underlying type declaration - StringRef TypeDeclaration = {}; + StringRef TypeDeclaration; // Indicates if this is a new C++ "using"-style typedef: // using MyVector = std::vector @@ -677,10 +638,8 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node { bool IsUsing = false; }; -struct BaseRecordInfo : public RecordInfo, - public llvm::ilist_node { +struct BaseRecordInfo : public RecordInfo { BaseRecordInfo(); - BaseRecordInfo(const BaseRecordInfo &Other, llvm::BumpPtrAllocator &Arena); BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual, AccessSpecifier Access, bool IsParent); @@ -700,8 +659,6 @@ struct EnumValueInfo { : Name(internString(Name)), Value(internString(Value)), ValueExpr(internString(ValueExpr)) {} - EnumValueInfo(const EnumValueInfo &Other, llvm::BumpPtrAllocator &Arena); - bool operator==(const EnumValueInfo &Other) const { return std::tie(Name, Value, ValueExpr) == std::tie(Other.Name, Other.Value, Other.ValueExpr); @@ -738,7 +695,7 @@ struct EnumInfo : public SymbolInfo, public llvm::ilist_node { // this will be "short". std::optional BaseType; - llvm::ArrayRef Members; // List of enum members. + llvm::SmallVector Members; // List of enum members. }; struct ConceptInfo : public SymbolInfo, public llvm::ilist_node { @@ -747,9 +704,9 @@ struct ConceptInfo : public SymbolInfo, public llvm::ilist_node { void merge(ConceptInfo &&I); - bool IsType = false; + bool IsType; TemplateInfo Template; - StringRef ConstraintExpression = {}; + StringRef ConstraintExpression; }; struct Index : public Reference { @@ -766,7 +723,7 @@ struct Index : public Reference { std::optional JumpToSection; llvm::StringMap Children; - std::vector getSortedChildren() const; + OwningVec getSortedChildren() const; void sort(); }; @@ -777,12 +734,6 @@ struct Index : public Reference { // if they are different. llvm::Expected> mergeInfos(OwningPtrArray &Values); -// Merges a single new Info into an existing Reduced Info (allocating it if -// needed). -llvm::Error mergeSingleInfo(doc::OwnedPtr &Reduced, - doc::OwnedPtr &&NewInfo, - llvm::BumpPtrAllocator &Arena); - struct ClangDocContext { ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName, bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot, @@ -822,26 +773,28 @@ struct ClangDocContext { // Ensure arena allocated types remain safe to allocate in the arena. // Only trivially destructible types are safe, so enforce that at compile-time. static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); -static_assert(std::is_trivially_destructible_v); + +// FIXME: These types need to be trivially destructible for arena allocation. +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); +static_assert(!std::is_trivially_destructible_v); } // namespace doc } // namespace clang diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 4b2f0b5eac3a..ef7fed6cc850 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -182,8 +182,8 @@ StringRef Serializer::getTypeAlias(const TypeAliasDecl *Alias) { // // } // } -StringRef -Serializer::getInfoRelativePath(llvm::ArrayRef Namespaces) { +StringRef Serializer::getInfoRelativePath( + const llvm::SmallVectorImpl &Namespaces) { llvm::SmallString<128> Path; for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R) llvm::sys::path::append(Path, R->Name); @@ -258,7 +258,9 @@ void ClangDocCommentVisitor::visitInlineCommandComment( for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I) Args.push_back(internString(C->getArgText(I).trim())); if (!Args.empty()) { - CurrentCI.Args = allocateArray(Args, TransientArena); + StringRef *ArgsMem = TransientArena.Allocate(Args.size()); + std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem); + CurrentCI.Args = llvm::ArrayRef(ArgsMem, Args.size()); } } @@ -274,10 +276,16 @@ void ClangDocCommentVisitor::visitHTMLStartTagComment( AttrValues.push_back(internString(Attr.Value)); } if (!AttrKeys.empty()) { - CurrentCI.AttrKeys = allocateArray(AttrKeys, TransientArena); + StringRef *KeysMem = TransientArena.Allocate(AttrKeys.size()); + std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem); + CurrentCI.AttrKeys = llvm::ArrayRef(KeysMem, AttrKeys.size()); } if (!AttrValues.empty()) { - CurrentCI.AttrValues = allocateArray(AttrValues, TransientArena); + StringRef *ValuesMem = + TransientArena.Allocate(AttrValues.size()); + std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), ValuesMem); + CurrentCI.AttrValues = + llvm::ArrayRef(ValuesMem, AttrValues.size()); } } @@ -294,7 +302,9 @@ void ClangDocCommentVisitor::visitBlockCommandComment( for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) Args.push_back(internString(C->getArgText(I).trim())); if (!Args.empty()) { - CurrentCI.Args = allocateArray(Args, TransientArena); + StringRef *ArgsMem = TransientArena.Allocate(Args.size()); + std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem); + CurrentCI.Args = llvm::ArrayRef(ArgsMem, Args.size()); } } @@ -465,35 +475,29 @@ void Serializer::InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) { } void Serializer::InsertChild(ScopeChildren &Scope, const RecordInfo &Info) { - Reference *R = allocatePtr( - Info.USR, Info.Name, InfoType::IT_record, Info.Name, - getInfoRelativePath(Info.Namespace), Info.MangledName); - Scope.Records.push_back(*R); + Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record, + Info.Name, getInfoRelativePath(Info.Namespace), + Info.MangledName); } void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) { - EnumInfo *E = allocatePtr(std::move(Info)); - Scope.Enums.push_back(*E); + Scope.Enums.push_back(std::move(Info)); } void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) { - FunctionInfo *F = allocatePtr(std::move(Info)); - Scope.Functions.push_back(*F); + Scope.Functions.push_back(std::move(Info)); } void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) { - TypedefInfo *T = allocatePtr(std::move(Info)); - Scope.Typedefs.push_back(*T); + Scope.Typedefs.push_back(std::move(Info)); } void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) { - ConceptInfo *C = allocatePtr(std::move(Info)); - Scope.Concepts.push_back(*C); + Scope.Concepts.push_back(std::move(Info)); } void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) { - VarInfo *V = allocatePtr(std::move(Info)); - Scope.Variables.push_back(*V); + Scope.Variables.push_back(std::move(Info)); } // Creates a parent of the correct type for the given child and inserts it into @@ -577,18 +581,14 @@ AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS, // record, the access specification of the field depends on the inheritance mode void Serializer::parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly, AccessSpecifier Access) { - SmallVector Members; for (const FieldDecl *F : D->fields()) { if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F)) continue; - populateMemberTypeInfo(Members, Access, F); + populateMemberTypeInfo(I, Access, F); } const auto *CxxRD = dyn_cast(D); - if (!CxxRD) { - if (!Members.empty()) - I.Members = allocateArray(Members, TransientArena); + if (!CxxRD) return; - } for (Decl *CxxDecl : CxxRD->decls()) { auto *VD = dyn_cast(CxxDecl); if (!VD || @@ -596,49 +596,40 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D, continue; if (VD->isStaticDataMember()) - populateMemberTypeInfo(Members, Access, VD, /*IsStatic=*/true); + populateMemberTypeInfo(I, Access, VD, /*IsStatic=*/true); } - if (!Members.empty()) - I.Members = allocateArray(Members, TransientArena); } void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) { - llvm::SmallVector LocalMembers; for (const EnumConstantDecl *E : D->enumerators()) { std::string ValueExpr; if (const Expr *InitExpr = E->getInitExpr()) ValueExpr = getSourceCode(D, InitExpr->getSourceRange()); SmallString<16> ValueStr; E->getInitVal().toString(ValueStr); - EnumValueInfo &Member = LocalMembers.emplace_back( - E->getNameAsString(), ValueStr.str(), ValueExpr); + I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr); ASTContext &Context = E->getASTContext(); if (RawComment *Comment = E->getASTContext().getRawCommentForDeclNoCache(E)) { Comment->setAttached(); if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) { - CommentInfo *NewCI = allocatePtr(); - Member.Description.push_back(*NewCI); + EnumValueInfo &Member = I.Members.back(); + Member.Description.emplace_back(); parseFullComment(Fc, Member.Description.back()); } } } - if (!LocalMembers.empty()) - I.Members = allocateArray(LocalMembers, TransientArena); } void Serializer::parseParameters(FunctionInfo &I, const FunctionDecl *D) { - llvm::SmallVector LocalParams; auto &LO = D->getLangOpts(); for (const ParmVarDecl *P : D->parameters()) { - FieldTypeInfo &FieldInfo = LocalParams.emplace_back( + FieldTypeInfo &FieldInfo = I.Params.emplace_back( getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString()); if (std::optional DefaultValue = getSourceCode(D, P->getDefaultArgRange())) FieldInfo.DefaultValue = *DefaultValue; } - if (!LocalParams.empty()) - I.Params = allocateArray(LocalParams, TransientArena); } // TODO: Remove the serialization of Parents and VirtualParents, this @@ -648,36 +639,28 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D) { if (!D->isThisDeclarationADefinition()) return; - llvm::SmallVector LocalParents; for (const CXXBaseSpecifier &B : D->bases()) { if (B.isVirtual()) continue; if (const auto *Ty = B.getType()->getAs()) { const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl(); - LocalParents.emplace_back(getUSRForDecl(D), B.getType().getAsString(), - InfoType::IT_record, B.getType().getAsString()); + I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(), + InfoType::IT_record, B.getType().getAsString()); } else if (const RecordDecl *P = getRecordDeclForType(B.getType())) - LocalParents.emplace_back( - getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record, - P->getQualifiedNameAsString(), internString(getInfoRelativePath(P))); + I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(), + InfoType::IT_record, P->getQualifiedNameAsString(), + internString(getInfoRelativePath(P))); else - LocalParents.emplace_back(SymbolID(), B.getType().getAsString()); + I.Parents.emplace_back(SymbolID(), B.getType().getAsString()); } - if (!LocalParents.empty()) - I.Parents = allocateArray(LocalParents, TransientArena); - - llvm::SmallVector LocalVirtualParents; for (const CXXBaseSpecifier &B : D->vbases()) { if (const RecordDecl *P = getRecordDeclForType(B.getType())) - LocalVirtualParents.emplace_back( + I.VirtualParents.emplace_back( getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record, P->getQualifiedNameAsString(), internString(getInfoRelativePath(P))); else - LocalVirtualParents.emplace_back(SymbolID(), B.getType().getAsString()); + I.VirtualParents.emplace_back(SymbolID(), B.getType().getAsString()); } - if (!LocalVirtualParents.empty()) - I.VirtualParents = - allocateArray(LocalVirtualParents, TransientArena); } template @@ -725,13 +708,10 @@ void Serializer::populateTemplateParameters( if (!TemplateInfo) { TemplateInfo.emplace(); } - llvm::SmallVector LocalParams; for (const NamedDecl *ND : *ParamList) { - LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange())); + TemplateInfo->Params.emplace_back( + getSourceCode(ND, ND->getSourceRange())); } - if (!LocalParams.empty()) - TemplateInfo->Params = - allocateArray(LocalParams, TransientArena); } } @@ -794,14 +774,9 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C, ConversionDecl->getConversionType().getAsString()); else I.Name = internString(D->getNameAsString()); - llvm::SmallVector LocalNamespaces; - populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace); - if (!LocalNamespaces.empty()) - I.Namespace = allocateArray(LocalNamespaces, TransientArena); + populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace); if (C) { - - CommentInfo *NewCI = allocatePtr(); - I.Description.push_back(*NewCI); + I.Description.emplace_back(); parseFullComment(C, I.Description.back()); } } @@ -813,10 +788,8 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D, populateInfo(I, D, C, IsInAnonymousNamespace); if (D->isThisDeclarationADefinition()) I.DefLoc = Loc; - else { - Location *NewL = allocatePtr(Loc); - I.Loc.push_back(*NewL); - } + else + I.Loc.emplace_back(Loc); auto *Mangler = ItaniumMangleContext::create( D->getASTContext(), D->getASTContext().getDiagnostics()); @@ -838,8 +811,7 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D, } void Serializer::handleCompoundConstraints( - const Expr *Constraint, - llvm::SmallVectorImpl &ConstraintInfos) { + const Expr *Constraint, OwningVec &ConstraintInfos) { if (Constraint->getStmtClass() == Stmt::ParenExprClass) { handleCompoundConstraints(dyn_cast(Constraint)->getSubExpr(), ConstraintInfos); @@ -863,7 +835,6 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) { SmallVector AssociatedConstraints; D->getAssociatedConstraints(AssociatedConstraints); - SmallVector LocalConstraints; for (const auto &Constraint : AssociatedConstraints) { if (!Constraint) continue; @@ -875,14 +846,11 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) { ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()), ConstraintExpr->getNamedConcept()->getNameAsString()); CI.ConstraintExpr = internString(exprToString(ConstraintExpr)); - LocalConstraints.push_back(std::move(CI)); + I.Constraints.push_back(std::move(CI)); } else { - handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints); + handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints); } } - if (!LocalConstraints.empty()) - I.Constraints = - allocateArray(LocalConstraints, TransientArena); } void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, @@ -911,13 +879,9 @@ void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, // Template parameters to the specialization. if (FTSI->TemplateArguments) { - SmallVector LocalParams; for (const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) { - LocalParams.push_back(convertTemplateArgToInfo(D, Arg)); + Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg)); } - if (!LocalParams.empty()) - Specialization.Params = - allocateArray(LocalParams, TransientArena); } } } @@ -937,28 +901,26 @@ void Serializer::populateMemberTypeInfo(T &I, const Decl *D) { Comment->setAttached(); if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) { - CommentInfo *NewCI = allocatePtr(); - I.Description.push_back(*NewCI); + I.Description.emplace_back(); parseFullComment(Fc, I.Description.back()); } } -void Serializer::populateMemberTypeInfo( - SmallVectorImpl &Members, AccessSpecifier &Access, - const DeclaratorDecl *D, bool IsStatic) { +void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, + const DeclaratorDecl *D, + bool IsStatic) { // Use getAccessUnsafe so that we just get the default AS_none if it's not // valid, as opposed to an assert. - MemberTypeInfo &NewMember = Members.emplace_back( + MemberTypeInfo &NewMember = I.Members.emplace_back( getTypeInfoForType(D->getTypeSourceInfo()->getType(), D->getLangOpts()), D->getNameAsString(), getFinalAccessSpecifier(Access, D->getAccessUnsafe()), IsStatic); populateMemberTypeInfo(NewMember, D); } -void Serializer::parseBases(llvm::SmallVectorImpl &Bases, - const CXXRecordDecl *D, bool IsFileInRootDir, - bool PublicOnly, bool IsParent, - AccessSpecifier ParentAccess) { +void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D, + bool IsFileInRootDir, bool PublicOnly, + bool IsParent, AccessSpecifier ParentAccess) { // Don't parse bases if this isn't a definition. if (!D->isThisDeclarationADefinition()) return; @@ -997,15 +959,14 @@ void Serializer::parseBases(llvm::SmallVectorImpl &Bases, IsInAnonymousNamespace); FI.Access = getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe()); - FunctionInfo *FIPtr = allocatePtr(std::move(FI)); - BI.Children.Functions.push_back(*FIPtr); + BI.Children.Functions.emplace_back(std::move(FI)); } - Bases.emplace_back(std::move(BI)); + I.Bases.emplace_back(std::move(BI)); // Call this function recursively to get the inherited classes of // this base; these new bases will also get stored in the original // RecordInfo: I. - parseBases(Bases, Base, IsFileInRootDir, PublicOnly, false, - Bases.back().Access); + parseBases(I, Base, IsFileInRootDir, PublicOnly, false, + I.Bases.back().Access); } } } @@ -1034,8 +995,6 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) { if (!D->hasDefinition() || !D->hasFriends()) return; - llvm::SmallVector LocalFriends; - for (const FriendDecl *FD : D->friends()) { if (FD->isUnsupportedFriend()) continue; @@ -1057,12 +1016,9 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) { if (isa(ActualTD->getTemplatedDecl())) F.IsClass = true; F.Template.emplace(); - llvm::SmallVector LocalParams; for (const auto *Param : ActualTD->getTemplateParameters()->asArray()) - LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange())); - if (!LocalParams.empty()) - F.Template->Params = - allocateArray(LocalParams, TransientArena); + F.Template->Params.emplace_back( + getSourceCode(Param, Param->getSourceRange())); ActualDecl = ActualTD->getTemplatedDecl(); } @@ -1080,10 +1036,8 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) { getInfoRelativePath(ActualDecl)); populateMemberTypeInfo(F, ActualDecl); - LocalFriends.push_back(std::move(F)); + RI.Friends.push_back(std::move(F)); } - if (!LocalFriends.empty()) - RI.Friends = allocateArray(LocalFriends, TransientArena); } std::pair, OwnedPtr> @@ -1107,11 +1061,7 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, } // TODO: remove first call to parseBases, that function should be deleted parseBases(*RI, C); - llvm::SmallVector LocalBases; - parseBases(LocalBases, C, /*IsFileInRootDir=*/true, PublicOnly, - /*IsParent=*/true); - if (!LocalBases.empty()) - RI->Bases = allocateArray(LocalBases, TransientArena); + parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true); parseFriends(*RI, C); } RI->Path = internString(getInfoRelativePath(RI->Namespace)); @@ -1144,23 +1094,15 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, dyn_cast(D)) { if (const ASTTemplateArgumentListInfo *AsWritten = CTPSD->getTemplateArgsAsWritten()) { - llvm::SmallVector LocalParams; for (unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) { - LocalParams.emplace_back( + Specialization.Params.emplace_back( getSourceCode(D, (*AsWritten)[Idx].getSourceRange())); } - if (!LocalParams.empty()) - Specialization.Params = - allocateArray(LocalParams, TransientArena); } } else { - llvm::SmallVector LocalParams; for (const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) { - LocalParams.push_back(convertTemplateArgToInfo(D, Arg)); + Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg)); } - if (!LocalParams.empty()) - Specialization.Params = - allocateArray(LocalParams, TransientArena); } } @@ -1222,9 +1164,8 @@ void Serializer::extractCommentFromDecl(const Decl *D, TypedefInfo &Info) { Comment->setAttached(); if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) { - CommentInfo *NewCI = allocatePtr(); - Info.Description.push_back(*NewCI); - parseFullComment(Fc, *NewCI); + Info.Description.emplace_back(); + parseFullComment(Fc, Info.Description.back()); } } @@ -1317,13 +1258,10 @@ Serializer::emitInfo(const ConceptDecl *D, const FullComment *FC, Concept.ConstraintExpression = exprToString(D->getConstraintExpr()); if (auto *ConceptParams = D->getTemplateParameters()) { - llvm::SmallVector LocalParams; for (const auto *Param : ConceptParams->asArray()) { - LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange())); + Concept.Template.Params.emplace_back( + getSourceCode(Param, Param->getSourceRange())); } - if (!LocalParams.empty()) - Concept.Template.Params = - allocateArray(LocalParams, TransientArena); } if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) diff --git a/clang-tools-extra/clang-doc/Serialize.h b/clang-tools-extra/clang-doc/Serialize.h index 3d53514d0756..04891bea3322 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -94,7 +94,8 @@ private: StringRef getTypeAlias(const TypeAliasDecl *Alias); - StringRef getInfoRelativePath(llvm::ArrayRef Namespaces); + StringRef + getInfoRelativePath(const llvm::SmallVectorImpl &Namespaces); StringRef getInfoRelativePath(const Decl *D); @@ -138,9 +139,8 @@ private: void parseBases(RecordInfo &I, const CXXRecordDecl *D); - void parseBases(llvm::SmallVectorImpl &Bases, - const CXXRecordDecl *D, bool IsFileInRootDir, bool PublicOnly, - bool IsParent, + void parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, + bool PublicOnly, bool IsParent, AccessSpecifier ParentAccess = AccessSpecifier::AS_public); template @@ -165,9 +165,8 @@ private: void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, Location Loc, bool &IsInAnonymousNamespace); - void handleCompoundConstraints( - const Expr *Constraint, - llvm::SmallVectorImpl &ConstraintInfos); + void handleCompoundConstraints(const Expr *Constraint, + OwningVec &ConstraintInfos); void populateConstraints(TemplateInfo &I, const TemplateDecl *D); @@ -177,9 +176,8 @@ private: template void populateMemberTypeInfo(T &I, const Decl *D); - void populateMemberTypeInfo(llvm::SmallVectorImpl &Members, - AccessSpecifier &Access, const DeclaratorDecl *D, - bool IsStatic = false); + void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, + const DeclaratorDecl *D, bool IsStatic = false); void parseFriends(RecordInfo &RI, const CXXRecordDecl *D); diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index b5c43837f950..9e3bca84877e 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -31,70 +31,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(OwnedPtr) namespace llvm { - -template -bool operator==(const llvm::simple_ilist &LHS, - const llvm::simple_ilist &RHS) { - auto LIt = LHS.begin(), LEnd = LHS.end(); - auto RIt = RHS.begin(), REnd = RHS.end(); - for (; LIt != LEnd && RIt != REnd; ++LIt, ++RIt) { - if (!(*LIt == *RIt)) - return false; - } - return LIt == LEnd && RIt == REnd; -} - -template -bool operator!=(const llvm::simple_ilist &LHS, - const llvm::simple_ilist &RHS) { - return !(LHS == RHS); -} - namespace yaml { -// Provide SequenceTraits for ArrayRef since YAMLTraits only provides it for -// MutableArrayRef -template struct SequenceTraits> { - static size_t size(IO &io, ArrayRef &seq) { return seq.size(); } - static T *&element(IO &io, ArrayRef &seq, size_t index) { - // ArrayRef is not mutable, but YAML output only reads the value. - return const_cast(seq[index]); - } -}; - -template struct SequenceTraits> { - static size_t size(IO &io, llvm::simple_ilist &seq) { return seq.size(); } - static T &element(IO &io, llvm::simple_ilist &seq, size_t index) { - return *std::next(seq.begin(), index); - } -}; - -// Map pointers to the value mappings as clang-doc only does output -// serialization. -template struct PointerMappingTraits { - static void mapping(IO &IO, T *&Val) { - if (Val) - MappingTraits::mapping(IO, *Val); - } -}; - -template <> -struct MappingTraits - : PointerMappingTraits {}; -template <> -struct MappingTraits - : PointerMappingTraits {}; -template <> -struct MappingTraits - : PointerMappingTraits {}; -template <> -struct MappingTraits - : PointerMappingTraits {}; -template <> -struct MappingTraits - : PointerMappingTraits {}; - -template struct SequenceTraits> { +template struct SequenceTraits> { static size_t size(IO &io, llvm::ArrayRef &seq) { return seq.size(); } static T &element(IO &io, llvm::ArrayRef &seq, size_t index) { return const_cast(seq[index]); @@ -252,7 +191,7 @@ static void infoMapping(IO &IO, Info &I) { static void symbolInfoMapping(IO &IO, SymbolInfo &I) { infoMapping(IO, I); IO.mapOptional("DefLocation", I.DefLoc, std::optional()); - IO.mapOptional("Location", I.Loc); + IO.mapOptional("Location", I.Loc, llvm::SmallVector()); } static void recordInfoMapping(IO &IO, RecordInfo &I) { @@ -261,10 +200,10 @@ static void recordInfoMapping(IO &IO, RecordInfo &I) { IO.mapOptional("IsTypeDef", I.IsTypeDef, false); IO.mapOptional("Members", I.Members); IO.mapOptional("Bases", I.Bases); - IO.mapOptional("Parents", I.Parents, SmallVector()); + IO.mapOptional("Parents", I.Parents, llvm::SmallVector()); IO.mapOptional("VirtualParents", I.VirtualParents, llvm::SmallVector()); - IO.mapOptional("ChildRecords", I.Children.Records); + IO.mapOptional("ChildRecords", I.Children.Records, OwningVec()); IO.mapOptional("ChildFunctions", I.Children.Functions); IO.mapOptional("ChildEnums", I.Children.Enums); IO.mapOptional("ChildTypedefs", I.Children.Typedefs); @@ -400,7 +339,7 @@ template <> struct MappingTraits { for (const auto &N : I.Children.Namespaces) TempNamespaces.push_back(N); IO.mapOptional("ChildNamespaces", TempNamespaces, std::vector()); - IO.mapOptional("ChildRecords", I.Children.Records); + IO.mapOptional("ChildRecords", I.Children.Records, OwningVec()); IO.mapOptional("ChildFunctions", I.Children.Functions); IO.mapOptional("ChildEnums", I.Children.Enums); IO.mapOptional("ChildTypedefs", I.Children.Typedefs); @@ -502,6 +441,13 @@ template <> struct MappingTraits { static void mapping(IO &IO, CommentInfo &I) { commentInfoMapping(IO, I); } }; +template <> struct MappingTraits> { + static void mapping(IO &IO, OwnedPtr &I) { + if (I) + commentInfoMapping(IO, *I); + } +}; + } // end namespace yaml } // end namespace llvm diff --git a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp index c610c5772264..f96cfc9426f1 100644 --- a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp +++ b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp @@ -184,10 +184,9 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) { auto NI = allocatePtr(); NI->Name = "GlobalNamespace"; for (int i = 0; i < NumRecords; ++i) { - Reference *R = new (TransientArena.Allocate()) - Reference(SymbolID{(uint8_t)(i & 0xFF)}, "Record" + std::to_string(i), - InfoType::IT_record); - NI->Children.Records.push_back(*R); + NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)}, + "Record" + std::to_string(i), + InfoType::IT_record); } IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 3c38901f4a0f..f627ee588752 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -29,7 +29,6 @@ #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" @@ -359,22 +358,15 @@ Example usage for a project using a compile commands database: llvm::hardware_concurrency(ExecutorConcurrency)); { llvm::TimeTraceScope TS("Reduce"); - for (const auto &Group : USRToBitcode) { - StringRef Key = Group.getKey(); - std::vector Bitcodes = Group.getValue(); - Pool.async([Key, Bitcodes, &CDCtx, &Diags, &USRToInfo, &USRToInfoMutex, - &IndexMutex, &DiagMutex, &Error, DiagIDBitcodeReading, - DiagIDBitcodeMerging]() { - if (CDCtx.FTimeTrace) + for (auto &Group : USRToBitcode) { + Pool.async([&, &Diags = Diags]() { // time trace decoding bitcode + if (FTimeTrace) llvm::timeTraceProfilerInitialize(200, "clang-doc"); - doc::OwnedPtr Reduced = nullptr; + doc::OwningPtrVec Infos; { - llvm::TimeTraceScope Red("decoding and merging bitcode"); - for (const auto &Bitcode : Bitcodes) { - - llvm::scope_exit ArenaGuard( - [] { clang::doc::TransientArena.Reset(); }); + llvm::TimeTraceScope Red("decoding bitcode"); + for (auto &Bitcode : Group.getValue()) { llvm::BitstreamCursor Stream(Bitcode); doc::ClangDocBitcodeReader Reader(Stream, Diags); auto ReadInfos = Reader.readBitcode(); @@ -386,17 +378,25 @@ Example usage for a project using a compile commands database: Error = true; return; } - for (auto &I : *ReadInfos) { - if (auto Err = doc::mergeSingleInfo( - Reduced, std::move(I), clang::doc::PersistentArena)) { - std::lock_guard Guard(DiagMutex); - Diags.Report(DiagIDBitcodeMerging) - << toString(std::move(Err)); - return; - } - } + std::move(ReadInfos->begin(), ReadInfos->end(), + std::back_inserter(Infos)); } - } // time trace decoding and merging bitcode + } // time trace decoding bitcode + + doc::OwnedPtr Reduced; + + { + llvm::TimeTraceScope Merge("merging bitcode"); + auto ExpReduced = doc::mergeInfos(Infos); + + if (!ExpReduced) { + std::lock_guard Guard(DiagMutex); + Diags.Report(DiagIDBitcodeMerging) + << toString(ExpReduced.takeError()); + return; + } + Reduced = std::move(*ExpReduced); + } // time trace merging bitcode // Add a reference to this Info in the Index { @@ -408,7 +408,7 @@ Example usage for a project using a compile commands database: { llvm::TimeTraceScope Merge("USRToInfo"); std::lock_guard Guard(USRToInfoMutex); - USRToInfo[Key] = std::move(Reduced); + USRToInfo[Group.getKey()] = std::move(Reduced); } if (CDCtx.FTimeTrace) diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp index 81de4ff2f638..6bdf53801230 100644 --- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp @@ -56,6 +56,7 @@ static OwningPtrVec readInfo(StringRef Bitcode, size_t NumInfos, llvm::BitstreamCursor Stream(Bitcode); doc::ClangDocBitcodeReader Reader(Stream, Diags); auto Infos = Reader.readBitcode(); + // Check that there was no error in the read. assert(Infos); EXPECT_EQ(Infos.get().size(), NumInfos); @@ -67,43 +68,39 @@ class BitcodeTest : public ClangDocContextTest {}; TEST_F(BitcodeTest, emitNamespaceInfoBitcode) { NamespaceInfo I; I.Name = "r"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace); I.Children.Namespaces.push_back(NewNamespace); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record); - I.Children.Records.push_back(ChildStruct); - FunctionInfo FI; - I.Children.Functions.push_back(FI); - EnumInfo EI; - I.Children.Enums.push_back(EI); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); + I.Children.Functions.emplace_back(); + I.Children.Enums.emplace_back(); std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0])); + CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get())); } TEST_F(BitcodeTest, emitRecordInfoBitcode) { RecordInfo I; I.Name = "r"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private); + I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private); I.TagType = TagTypeKind::Class; I.IsTypeDef = true; - BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public, - true); - FunctionInfo FI; - B.Children.Functions.push_back(FI); - MemberTypeInfo BM(TypeInfo("int"), "X", AccessSpecifier::AS_private); + I.Bases.emplace_back(EmptySID, "F", "path/to/F", true, + AccessSpecifier::AS_public, true); + I.Bases.back().Children.Functions.emplace_back(); + I.Bases.back().Members.emplace_back(TypeInfo("int"), "X", + AccessSpecifier::AS_private); + I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record); + I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); // Documentation for the data member. CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {}, @@ -112,47 +109,29 @@ TEST_F(BitcodeTest, emitRecordInfoBitcode) { CommentInfo TopCommentChildren[] = { CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)}; CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren); - BM.Description.push_back(TopComment); - MemberTypeInfo BMem[] = {std::move(BM)}; - B.Members = llvm::ArrayRef(BMem); - BaseRecordInfo Bases[] = {std::move(B)}; - I.Bases = llvm::ArrayRef(Bases); + I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment)); - MemberTypeInfo Mem[] = {std::move(M)}; - I.Members = llvm::ArrayRef(Mem); - Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)}; - I.Parents = llvm::ArrayRef(Parents); - Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)}; - I.VirtualParents = llvm::ArrayRef(VParents); - - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record); - I.Children.Records.push_back(ChildStruct); - FunctionInfo FI2; - I.Children.Functions.push_back(FI2); - EnumInfo EI; - I.Children.Enums.push_back(EI); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); + I.Children.Functions.emplace_back(); + I.Children.Enums.emplace_back(); std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckRecordInfo(&I, InfoAsRecord(ReadResults[0])); + CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get())); } TEST_F(BitcodeTest, emitFunctionInfoBitcode) { FunctionInfo I; I.Name = "f"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); I.ReturnType = TypeInfo("void"); - FieldTypeInfo P(TypeInfo("int"), "P"); - FieldTypeInfo Params[] = {std::move(P)}; - I.Params = llvm::ArrayRef(Params); + I.Params.emplace_back(TypeInfo("int"), "P"); I.Access = AccessSpecifier::AS_none; @@ -160,23 +139,19 @@ TEST_F(BitcodeTest, emitFunctionInfoBitcode) { EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0])); + CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); } TEST_F(BitcodeTest, emitMethodInfoBitcode) { FunctionInfo I; I.Name = "f"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); I.ReturnType = TypeInfo("void"); - FieldTypeInfo P(TypeInfo("int"), "P"); - FieldTypeInfo Params[] = {std::move(P)}; - I.Params = llvm::ArrayRef(Params); + I.Params.emplace_back(TypeInfo("int"), "P"); I.IsMethod = true; I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); @@ -186,36 +161,31 @@ TEST_F(BitcodeTest, emitMethodInfoBitcode) { EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0])); + CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); } TEST_F(BitcodeTest, emitEnumInfoBitcode) { EnumInfo I; I.Name = "e"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - EnumValueInfo EV("X"); - EnumValueInfo Mems[] = {std::move(EV)}; - I.Members = llvm::ArrayRef(Mems); + I.Members.emplace_back("X"); I.Scoped = true; std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckEnumInfo(&I, InfoAsEnum(ReadResults[0])); + CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get())); } TEST_F(BitcodeTest, emitTypedefInfoBitcode) { TypedefInfo I; I.Name = "MyInt"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); I.Underlying = TypeInfo("unsigned"); @@ -226,13 +196,13 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) { CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)}; CommentInfo Top(CommentKind::CK_FullComment, TopChildren); - I.Description.push_back(Top); + I.Description.emplace_back(std::move(Top)); std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0])); + CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0].get())); // Check one with no IsUsing set, no description, and no definition location. TypedefInfo I2; @@ -243,7 +213,7 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) { WriteResult = writeInfo(&I2, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0])); + CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0].get())); } TEST_F(BitcodeTest, emitInfoWithCommentBitcode) { @@ -251,8 +221,7 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) { F.Name = "F"; F.ReturnType = TypeInfo("void"); F.DefLoc = Location(0, 0, "test.cpp"); - FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I")}; - F.Params = llvm::ArrayRef(PI); + F.Params.emplace_back(TypeInfo("int"), "I"); // BlankLine CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)}; @@ -324,13 +293,13 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) { Verbatim, ParamOut, ParamIn, Return}; CommentInfo Top(CommentKind::CK_FullComment, TopChildren); - F.Description.push_back(Top); + F.Description.emplace_back(std::move(Top)); std::string WriteResult = writeInfo(&F, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); OwningPtrVec ReadResults = readInfo(WriteResult, 1, this->Diags); - CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0])); + CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get())); } } // namespace doc diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp index 2e5466c172a1..92127da53b7b 100644 --- a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp @@ -54,10 +54,10 @@ TypedefInfo *InfoAsTypedef(Info *I) { return static_cast(I); } -void CheckCommentInfo(ArrayRef Expected, - ArrayRef Actual); -void CheckCommentInfo(const OwningVec &Expected, - const OwningVec &Actual); +void CheckCommentInfo(const std::vector &Expected, + const std::vector &Actual); +void CheckCommentInfo(const std::vector> &Expected, + const std::vector> &Actual); void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) { EXPECT_EQ(Expected.Kind, Actual.Kind); @@ -84,71 +84,52 @@ void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) { CheckCommentInfo(Expected.Children, Actual.Children); } -void CheckCommentInfo(ArrayRef Expected, - ArrayRef Actual) { - auto ItE = Expected.begin(); - auto ItA = Actual.begin(); - while (ItE != Expected.end() && ItA != Actual.end()) { - CheckCommentInfo(*ItE, *ItA); - ++ItE; - ++ItA; - } - EXPECT_TRUE(ItE == Expected.end() && ItA == Actual.end()); +void CheckCommentInfo(const std::vector &Expected, + const std::vector &Actual) { + ASSERT_EQ(Expected.size(), Actual.size()); + for (size_t Idx = 0; Idx < Actual.size(); ++Idx) + CheckCommentInfo(Expected[Idx], Actual[Idx]); } -void CheckCommentInfo(const OwningVec &Expected, - const OwningVec &Actual) { - auto ItE = Expected.begin(); - auto ItA = Actual.begin(); - while (ItE != Expected.end() && ItA != Actual.end()) { - CheckCommentInfo(*ItE, *ItA); - ++ItE; - ++ItA; - } - EXPECT_TRUE(ItE == Expected.end() && ItA == Actual.end()); +void CheckCommentInfo(const std::vector> &Expected, + const std::vector> &Actual) { + ASSERT_EQ(Expected.size(), Actual.size()); + for (size_t Idx = 0; Idx < Actual.size(); ++Idx) + CheckCommentInfo(*Expected[Idx], *Actual[Idx]); } -void CheckReference(const Reference &Expected, const Reference &Actual) { +void CheckReference(Reference &Expected, Reference &Actual) { EXPECT_EQ(Expected.Name, Actual.Name); EXPECT_EQ(Expected.RefType, Actual.RefType); EXPECT_EQ(Expected.Path, Actual.Path); } -void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual) { +void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) { CheckReference(Expected->Type, Actual->Type); } -void CheckFieldTypeInfo(const FieldTypeInfo *Expected, - const FieldTypeInfo *Actual) { +void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) { CheckTypeInfo(Expected, Actual); EXPECT_EQ(Expected->Name, Actual->Name); } -void CheckMemberTypeInfo(const MemberTypeInfo *Expected, - const MemberTypeInfo *Actual) { +void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) { CheckFieldTypeInfo(Expected, Actual); EXPECT_EQ(Expected->Access, Actual->Access); CheckCommentInfo(Expected->Description, Actual->Description); } -void CheckBaseInfo(const Info *Expected, const Info *Actual) { +void CheckBaseInfo(Info *Expected, Info *Actual) { EXPECT_EQ(size_t(20), Actual->USR.size()); EXPECT_EQ(Expected->Name, Actual->Name); EXPECT_EQ(Expected->Path, Actual->Path); - auto ItN_E = Expected->Namespace.begin(); - auto ItN_A = Actual->Namespace.begin(); - while (ItN_E != Expected->Namespace.end() && - ItN_A != Actual->Namespace.end()) { - CheckReference(*ItN_E, *ItN_A); - ++ItN_E; - ++ItN_A; - } - EXPECT_TRUE(ItN_E == Expected->Namespace.end() && - ItN_A == Actual->Namespace.end()); + ASSERT_EQ(Expected->Namespace.size(), Actual->Namespace.size()); + for (size_t Idx = 0; Idx < Actual->Namespace.size(); ++Idx) + CheckReference(Expected->Namespace[Idx], Actual->Namespace[Idx]); CheckCommentInfo(Expected->Description, Actual->Description); } -void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) { +void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) { CheckBaseInfo(Expected, Actual); EXPECT_EQ(Expected->DefLoc.has_value(), Actual->DefLoc.has_value()); if (Expected->DefLoc && Actual->DefLoc.has_value()) { @@ -157,186 +138,109 @@ void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) { EXPECT_EQ(Expected->DefLoc->EndLineNumber, Actual->DefLoc->EndLineNumber); EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename); } - auto ItE = Expected->Loc.begin(); - auto ItA = Actual->Loc.begin(); - while (ItE != Expected->Loc.end() && ItA != Actual->Loc.end()) { - EXPECT_EQ(*ItE, *ItA); - ++ItE; - ++ItA; - } - EXPECT_TRUE(ItE == Expected->Loc.end() && ItA == Actual->Loc.end()); + ASSERT_EQ(Expected->Loc.size(), Actual->Loc.size()); + for (size_t Idx = 0; Idx < Actual->Loc.size(); ++Idx) + EXPECT_EQ(Expected->Loc[Idx], Actual->Loc[Idx]); } -void CheckFunctionInfo(const FunctionInfo *Expected, - const FunctionInfo *Actual) { +void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual) { CheckSymbolInfo(Expected, Actual); EXPECT_EQ(Expected->IsMethod, Actual->IsMethod); CheckReference(Expected->Parent, Actual->Parent); CheckTypeInfo(&Expected->ReturnType, &Actual->ReturnType); - for (size_t Idx = 0; Idx < Expected->Params.size(); ++Idx) { + ASSERT_EQ(Expected->Params.size(), Actual->Params.size()); + for (size_t Idx = 0; Idx < Actual->Params.size(); ++Idx) EXPECT_EQ(Expected->Params[Idx], Actual->Params[Idx]); - } EXPECT_EQ(Expected->Access, Actual->Access); } -void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual) { +void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual) { CheckSymbolInfo(Expected, Actual); EXPECT_EQ(Expected->Scoped, Actual->Scoped); - auto ItM_E = Expected->Members.begin(); - auto ItM_A = Actual->Members.begin(); - while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) { - EXPECT_EQ(*ItM_E, *ItM_A); - ++ItM_E; - ++ItM_A; - } - EXPECT_TRUE(ItM_E == Expected->Members.end() && - ItM_A == Actual->Members.end()); + ASSERT_EQ(Expected->Members.size(), Actual->Members.size()); + for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx) + EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]); } -void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual) { +void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual) { CheckSymbolInfo(Expected, Actual); EXPECT_EQ(Expected->IsUsing, Actual->IsUsing); CheckTypeInfo(&Expected->Underlying, &Actual->Underlying); } -void CheckNamespaceInfo(const NamespaceInfo *Expected, - const NamespaceInfo *Actual) { +void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual) { CheckBaseInfo(Expected, Actual); ASSERT_EQ(Expected->Children.Namespaces.size(), Actual->Children.Namespaces.size()); - auto ItN_E = Expected->Children.Namespaces.begin(); - auto ItN_A = Actual->Children.Namespaces.begin(); - while (ItN_E != Expected->Children.Namespaces.end() && - ItN_A != Actual->Children.Namespaces.end()) { - CheckReference(*ItN_E, *ItN_A); - ++ItN_E; - ++ItN_A; + auto ItExpected = Expected->Children.Namespaces.begin(); + auto ItActual = Actual->Children.Namespaces.begin(); + while (ItExpected != Expected->Children.Namespaces.end()) { + CheckReference(*ItExpected, *ItActual); + ++ItExpected; + ++ItActual; } - EXPECT_TRUE(ItN_E == Expected->Children.Namespaces.end() && - ItN_A == Actual->Children.Namespaces.end()); - auto ItR_E = Expected->Children.Records.begin(); - auto ItR_A = Actual->Children.Records.begin(); - while (ItR_E != Expected->Children.Records.end() && - ItR_A != Actual->Children.Records.end()) { - CheckReference(*ItR_E, *ItR_A); - ++ItR_E; - ++ItR_A; - } - EXPECT_TRUE(ItR_E == Expected->Children.Records.end() && - ItR_A == Actual->Children.Records.end()); + ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size()); + for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx) + CheckReference(Expected->Children.Records[Idx], + Actual->Children.Records[Idx]); - auto ItF_E = Expected->Children.Functions.begin(); - auto ItF_A = Actual->Children.Functions.begin(); - while (ItF_E != Expected->Children.Functions.end() && - ItF_A != Actual->Children.Functions.end()) { - CheckFunctionInfo(&(*ItF_E), &(*ItF_A)); - ++ItF_E; - ++ItF_A; - } - EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() && - ItF_A == Actual->Children.Functions.end()); + ASSERT_EQ(Expected->Children.Functions.size(), + Actual->Children.Functions.size()); + for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx) + CheckFunctionInfo(&Expected->Children.Functions[Idx], + &Actual->Children.Functions[Idx]); - auto ItEnum_E = Expected->Children.Enums.begin(); - auto ItEnum_A = Actual->Children.Enums.begin(); - while (ItEnum_E != Expected->Children.Enums.end() && - ItEnum_A != Actual->Children.Enums.end()) { - CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A)); - ++ItEnum_E; - ++ItEnum_A; - } - EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() && - ItEnum_A == Actual->Children.Enums.end()); + ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size()); + for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx) + CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]); } -void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual) { +void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual) { CheckSymbolInfo(Expected, Actual); EXPECT_EQ(Expected->TagType, Actual->TagType); EXPECT_EQ(Expected->IsTypeDef, Actual->IsTypeDef); - auto ItM_E = Expected->Members.begin(); - auto ItM_A = Actual->Members.begin(); - while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) { - EXPECT_EQ(*ItM_E, *ItM_A); - ++ItM_E; - ++ItM_A; - } - EXPECT_TRUE(ItM_E == Expected->Members.end() && - ItM_A == Actual->Members.end()); + ASSERT_EQ(Expected->Members.size(), Actual->Members.size()); + for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx) + EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]); - auto ItP_E = Expected->Parents.begin(); - auto ItP_A = Actual->Parents.begin(); - while (ItP_E != Expected->Parents.end() && ItP_A != Actual->Parents.end()) { - CheckReference(*ItP_E, *ItP_A); - ++ItP_E; - ++ItP_A; - } - EXPECT_TRUE(ItP_E == Expected->Parents.end() && - ItP_A == Actual->Parents.end()); + ASSERT_EQ(Expected->Parents.size(), Actual->Parents.size()); + for (size_t Idx = 0; Idx < Actual->Parents.size(); ++Idx) + CheckReference(Expected->Parents[Idx], Actual->Parents[Idx]); - auto ItVP_E = Expected->VirtualParents.begin(); - auto ItVP_A = Actual->VirtualParents.begin(); - while (ItVP_E != Expected->VirtualParents.end() && - ItVP_A != Actual->VirtualParents.end()) { - CheckReference(*ItVP_E, *ItVP_A); - ++ItVP_E; - ++ItVP_A; - } - EXPECT_TRUE(ItVP_E == Expected->VirtualParents.end() && - ItVP_A == Actual->VirtualParents.end()); + ASSERT_EQ(Expected->VirtualParents.size(), Actual->VirtualParents.size()); + for (size_t Idx = 0; Idx < Actual->VirtualParents.size(); ++Idx) + CheckReference(Expected->VirtualParents[Idx], Actual->VirtualParents[Idx]); - auto ItB_E = Expected->Bases.begin(); - auto ItB_A = Actual->Bases.begin(); - while (ItB_E != Expected->Bases.end() && ItB_A != Actual->Bases.end()) { - CheckBaseRecordInfo(&(*ItB_E), &(*ItB_A)); - ++ItB_E; - ++ItB_A; - } - EXPECT_TRUE(ItB_E == Expected->Bases.end() && ItB_A == Actual->Bases.end()); + ASSERT_EQ(Expected->Bases.size(), Actual->Bases.size()); + for (size_t Idx = 0; Idx < Actual->Bases.size(); ++Idx) + CheckBaseRecordInfo(&Expected->Bases[Idx], &Actual->Bases[Idx]); - auto ItR_E = Expected->Children.Records.begin(); - auto ItR_A = Actual->Children.Records.begin(); - while (ItR_E != Expected->Children.Records.end() && - ItR_A != Actual->Children.Records.end()) { - CheckReference(*ItR_E, *ItR_A); - ++ItR_E; - ++ItR_A; - } - EXPECT_TRUE(ItR_E == Expected->Children.Records.end() && - ItR_A == Actual->Children.Records.end()); + ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size()); + for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx) + CheckReference(Expected->Children.Records[Idx], + Actual->Children.Records[Idx]); - auto ItF_E = Expected->Children.Functions.begin(); - auto ItF_A = Actual->Children.Functions.begin(); - while (ItF_E != Expected->Children.Functions.end() && - ItF_A != Actual->Children.Functions.end()) { - CheckFunctionInfo(&(*ItF_E), &(*ItF_A)); - ++ItF_E; - ++ItF_A; - } - EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() && - ItF_A == Actual->Children.Functions.end()); + ASSERT_EQ(Expected->Children.Functions.size(), + Actual->Children.Functions.size()); + for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx) + CheckFunctionInfo(&Expected->Children.Functions[Idx], + &Actual->Children.Functions[Idx]); - auto ItEnum_E = Expected->Children.Enums.begin(); - auto ItEnum_A = Actual->Children.Enums.begin(); - while (ItEnum_E != Expected->Children.Enums.end() && - ItEnum_A != Actual->Children.Enums.end()) { - CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A)); - ++ItEnum_E; - ++ItEnum_A; - } - EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() && - ItEnum_A == Actual->Children.Enums.end()); + ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size()); + for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx) + CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]); } -void CheckBaseRecordInfo(const BaseRecordInfo *Expected, - const BaseRecordInfo *Actual) { +void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual) { CheckRecordInfo(Expected, Actual); EXPECT_EQ(Expected->IsVirtual, Actual->IsVirtual); @@ -344,7 +248,7 @@ void CheckBaseRecordInfo(const BaseRecordInfo *Expected, EXPECT_EQ(Expected->IsParent, Actual->IsParent); } -void CheckIndex(const Index &Expected, const Index &Actual) { +void CheckIndex(Index &Expected, Index &Actual) { CheckReference(Expected, Actual); ASSERT_EQ(Expected.Children.size(), Actual.Children.size()); for (auto &[_, C] : Expected.Children) diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.h b/clang-tools-extra/unittests/clang-doc/ClangDocTest.h index 1525b1ed382c..9b1a26af0cdf 100644 --- a/clang-tools-extra/unittests/clang-doc/ClangDocTest.h +++ b/clang-tools-extra/unittests/clang-doc/ClangDocTest.h @@ -31,32 +31,25 @@ FunctionInfo *InfoAsFunction(Info *I); EnumInfo *InfoAsEnum(Info *I); TypedefInfo *InfoAsTypedef(Info *I); -void CheckCommentInfo(ArrayRef Expected, - ArrayRef Actual); -void CheckCommentInfo(const OwningVec &Expected, - const OwningVec &Actual); -void CheckReference(const Reference &Expected, const Reference &Actual); -void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual); -void CheckFieldTypeInfo(const FieldTypeInfo *Expected, - const FieldTypeInfo *Actual); -void CheckMemberTypeInfo(const MemberTypeInfo *Expected, - const MemberTypeInfo *Actual); +// Unlike the operator==, these functions explicitly does not check USRs, as +// that may change and it would be better to not rely on its implementation. +void CheckReference(Reference &Expected, Reference &Actual); +void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual); +void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual); +void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual); // This function explicitly does not check USRs, as that may change and it would // be better to not rely on its implementation. -void CheckBaseInfo(const Info *Expected, const Info *Actual); -void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual); -void CheckFunctionInfo(const FunctionInfo *Expected, - const FunctionInfo *Actual); -void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual); -void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual); -void CheckNamespaceInfo(const NamespaceInfo *Expected, - const NamespaceInfo *Actual); -void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual); -void CheckBaseRecordInfo(const BaseRecordInfo *Expected, - const BaseRecordInfo *Actual); +void CheckBaseInfo(Info *Expected, Info *Actual); +void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual); +void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual); +void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual); +void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual); +void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual); +void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual); +void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual); -void CheckIndex(const Index &Expected, const Index &Actual); +void CheckIndex(Index &Expected, Index &Actual); class ClangDocContextTest : public ::testing::Test { protected: diff --git a/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp index e352abbe0801..38f37bd53523 100644 --- a/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp @@ -28,8 +28,7 @@ TEST_F(GeneratorTest, emitIndex) { InfoC->USR = serialize::hashUSR("3"); Reference RefB = Reference(SymbolID(), "B"); RefB.USR = serialize::hashUSR("2"); - Reference NsC[] = {std::move(RefB)}; - InfoC->Namespace = llvm::ArrayRef(NsC); + InfoC->Namespace = {std::move(RefB)}; Generator::addInfoToIndex(Idx, InfoC.get()); auto InfoD = std::make_unique(); InfoD->Name = "D"; @@ -41,8 +40,7 @@ TEST_F(GeneratorTest, emitIndex) { RefD.USR = serialize::hashUSR("4"); Reference RefE = Reference(SymbolID(), "E"); RefE.USR = serialize::hashUSR("5"); - Reference NsF[] = {std::move(RefE), std::move(RefD)}; - InfoF->Namespace = llvm::ArrayRef(NsF); + InfoF->Namespace = {std::move(RefE), std::move(RefD)}; Generator::addInfoToIndex(Idx, InfoF.get()); auto InfoG = std::make_unique(InfoType::IT_namespace); Generator::addInfoToIndex(Idx, InfoG.get()); diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp index 509699f20aa0..6edd303dbc32 100644 --- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp @@ -19,54 +19,39 @@ TEST_F(JSONGeneratorTest, emitRecordJSON) { RecordInfo I; I.Name = "Foo"; I.IsTypeDef = false; - Reference Ns[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "GlobalNamespace", InfoType::IT_namespace); I.Path = "GlobalNamespace"; I.DefLoc = Location(1, 1, "main.cpp"); I.TagType = TagTypeKind::Class; I.Template = TemplateInfo(); - TemplateParamInfo TParams[] = {TemplateParamInfo("class T")}; - I.Template->Params = llvm::ArrayRef(TParams); + I.Template->Params.emplace_back("class T"); - EnumInfo E; - E.Name = "Color"; - E.Scoped = false; - EnumValueInfo EV[] = {EnumValueInfo("RED", "0")}; - E.Members = llvm::ArrayRef(EV); - I.Children.Enums.push_back(E); + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "Color"; + I.Children.Enums.back().Scoped = false; + I.Children.Enums.back().Members.emplace_back(); + I.Children.Enums.back().Members.back().Name = "RED"; + I.Children.Enums.back().Members.back().Value = "0"; - MemberTypeInfo M[] = { - MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_protected)}; - I.Members = llvm::ArrayRef(M); + I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_protected); - BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public, - true); - FunctionInfo F; - F.Name = "InheritedFunctionOne"; - B.Children.Functions.push_back(F); - MemberTypeInfo BM[] = { - MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_public)}; - B.Members = llvm::ArrayRef(BM); - - BaseRecordInfo Bases[] = {std::move(B)}; - I.Bases = llvm::ArrayRef(Bases); + I.Bases.emplace_back(EmptySID, "F", "path/to/F", true, + AccessSpecifier::AS_public, true); + I.Bases.back().Children.Functions.emplace_back(); + I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne"; + I.Bases.back().Members.emplace_back(TypeInfo("int"), "N", + AccessSpecifier::AS_public); // F is in the global namespace - Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")}; - I.Parents = llvm::ArrayRef(Parents); - Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record, - "path::to::G::G", "path/to/G")}; - I.VirtualParents = llvm::ArrayRef(VParents); + I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, ""); + I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record, + "path::to::G::G", "path/to/G"); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record, - "path::to::A::r::ChildStruct", "path/to/A/r"); - I.Children.Records.push_back(ChildStruct); - - FunctionInfo F2; - F2.Name = "OneFunction"; - I.Children.Functions.push_back(F2); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, + "path::to::A::r::ChildStruct", "path/to/A/r"); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; auto G = getJSONGenerator(); assert(G); @@ -212,26 +197,20 @@ TEST_F(JSONGeneratorTest, emitNamespaceJSON) { NamespaceInfo I; I.Name = "Namespace"; I.Path = "path/to/A"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace, "path::to::A::Namespace::ChildNamespace", "path/to/A/Namespace"); I.Children.Namespaces.push_back(NewNamespace); - - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record, - "path::to::A::Namespace::ChildStruct", - "path/to/A/Namespace"); - I.Children.Records.push_back(ChildStruct); - FunctionInfo F; - F.Name = "OneFunction"; - F.Access = AccessSpecifier::AS_none; - I.Children.Functions.push_back(F); - - EnumInfo E; - E.Name = "OneEnum"; - I.Children.Enums.push_back(E); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, + "path::to::A::Namespace::ChildStruct", + "path/to/A/Namespace"); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "OneEnum"; auto G = getJSONGenerator(); assert(G); diff --git a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp index 2dc472a352fd..666136004988 100644 --- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp @@ -26,22 +26,16 @@ class MDGeneratorTest : public ClangDocContextTest {}; TEST_F(MDGeneratorTest, emitNamespaceMD) { NamespaceInfo I; I.Name = "Namespace"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace); I.Children.Namespaces.push_back(NewNamespace); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record); - I.Children.Records.push_back(ChildStruct); - - FunctionInfo F; - F.Name = "OneFunction"; - F.Access = AccessSpecifier::AS_none; - I.Children.Functions.push_back(F); - - EnumInfo E; - E.Name = "OneEnum"; - I.Children.Enums.push_back(E); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "OneEnum"; auto G = getMDGenerator(); assert(G); @@ -85,31 +79,21 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) { TEST_F(MDGeneratorTest, emitRecordMD) { RecordInfo I; I.Name = "r"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - MemberTypeInfo M[] = { - MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)}; - I.Members = llvm::ArrayRef(M); + I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private); I.TagType = TagTypeKind::Class; - Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)}; - I.Parents = llvm::ArrayRef(Parents); - Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)}; - I.VirtualParents = llvm::ArrayRef(VParents); + I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record); + I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record); - I.Children.Records.push_back(ChildStruct); - FunctionInfo F; - F.Name = "OneFunction"; - I.Children.Functions.push_back(F); - - EnumInfo E; - E.Name = "OneEnum"; - I.Children.Enums.push_back(E); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "OneEnum"; auto G = getMDGenerator(); assert(G); @@ -159,18 +143,15 @@ ChildStruct TEST_F(MDGeneratorTest, emitFunctionMD) { FunctionInfo I; I.Name = "f"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); I.Access = AccessSpecifier::AS_none; I.ReturnType = TypeInfo("void"); - FieldTypeInfo P[] = {FieldTypeInfo(TypeInfo("int"), "P")}; - I.Params = llvm::ArrayRef(P); + I.Params.emplace_back(TypeInfo("int"), "P"); I.IsMethod = true; I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); @@ -194,15 +175,12 @@ TEST_F(MDGeneratorTest, emitFunctionMD) { TEST_F(MDGeneratorTest, emitEnumMD) { EnumInfo I; I.Name = "e"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - EnumValueInfo EV[] = {EnumValueInfo("X")}; - I.Members = llvm::ArrayRef(EV); + I.Members.emplace_back("X"); I.Scoped = true; auto G = getMDGenerator(); @@ -230,9 +208,8 @@ TEST_F(MDGeneratorTest, emitCommentMD) { I.DefLoc = Location(10, 10, "test.cpp"); I.ReturnType = TypeInfo("void"); - FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I"), - FieldTypeInfo(TypeInfo("int"), "J")}; - I.Params = llvm::ArrayRef(PI); + I.Params.emplace_back(TypeInfo("int"), "I"); + I.Params.emplace_back(TypeInfo("int"), "J"); I.Access = AccessSpecifier::AS_none; CommentInfo Top; diff --git a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp index 50374743681e..15b791a044d2 100644 --- a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp @@ -18,200 +18,150 @@ class MergeTest : public ClangDocContextTest {}; TEST_F(MergeTest, mergeNamespaceInfos) { NamespaceInfo One; One.Name = "Namespace"; - Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - One.Namespace = llvm::ArrayRef(Ns1); + One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference RA(NonEmptySID, "ChildNamespace", InfoType::IT_namespace); One.Children.Namespaces.push_back(RA); - Reference RC1(NonEmptySID, "ChildStruct", InfoType::IT_record); - One.Children.Records.push_back(RC1); - - FunctionInfo F1; - F1.Name = "OneFunction"; - F1.USR = NonEmptySID; - One.Children.Functions.push_back(F1); - - EnumInfo E1; - E1.Name = "OneEnum"; - E1.USR = NonEmptySID; - One.Children.Enums.push_back(E1); + One.Children.Records.emplace_back(NonEmptySID, "ChildStruct", + InfoType::IT_record); + One.Children.Functions.emplace_back(); + One.Children.Functions.back().Name = "OneFunction"; + One.Children.Functions.back().USR = NonEmptySID; + One.Children.Enums.emplace_back(); + One.Children.Enums.back().Name = "OneEnum"; + One.Children.Enums.back().USR = NonEmptySID; NamespaceInfo Two; Two.Name = "Namespace"; - Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Two.Namespace = llvm::ArrayRef(Ns2); + Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference RB(EmptySID, "OtherChildNamespace", InfoType::IT_namespace); Two.Children.Namespaces.push_back(RB); - Reference RC2(EmptySID, "OtherChildStruct", InfoType::IT_record); - Two.Children.Records.push_back(RC2); - - FunctionInfo F2; - F2.Name = "TwoFunction"; - Two.Children.Functions.push_back(F2); - - EnumInfo E2; - E2.Name = "TwoEnum"; - Two.Children.Enums.push_back(E2); + Two.Children.Records.emplace_back(EmptySID, "OtherChildStruct", + InfoType::IT_record); + Two.Children.Functions.emplace_back(); + Two.Children.Functions.back().Name = "TwoFunction"; + Two.Children.Enums.emplace_back(); + Two.Children.Enums.back().Name = "TwoEnum"; OwningPtrVec Infos; - Infos.push_back(&One); - Infos.push_back(&Two); + Infos.emplace_back(allocatePtr(std::move(One))); + Infos.emplace_back(allocatePtr(std::move(Two))); - NamespaceInfo Expected; - Expected.Name = "Namespace"; - Reference NsExpected[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Expected.Namespace = llvm::ArrayRef(NsExpected); + auto Expected = allocatePtr(); + Expected->Name = "Namespace"; + Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference RC(NonEmptySID, "ChildNamespace", InfoType::IT_namespace); - Expected.Children.Namespaces.push_back(RC); - Reference RCE1(NonEmptySID, "ChildStruct", InfoType::IT_record); - Expected.Children.Records.push_back(RCE1); + Expected->Children.Namespaces.push_back(RC); + Expected->Children.Records.emplace_back(NonEmptySID, "ChildStruct", + InfoType::IT_record); Reference RD(EmptySID, "OtherChildNamespace", InfoType::IT_namespace); - Expected.Children.Namespaces.push_back(RD); - Reference RCE2(EmptySID, "OtherChildStruct", InfoType::IT_record); - Expected.Children.Records.push_back(RCE2); - - FunctionInfo FE1; - FE1.Name = "OneFunction"; - FE1.USR = NonEmptySID; - Expected.Children.Functions.push_back(FE1); - - FunctionInfo FE2; - FE2.Name = "TwoFunction"; - Expected.Children.Functions.push_back(FE2); - - EnumInfo EE1; - EE1.Name = "OneEnum"; - EE1.USR = NonEmptySID; - Expected.Children.Enums.push_back(EE1); - - EnumInfo EE2; - EE2.Name = "TwoEnum"; - Expected.Children.Enums.push_back(EE2); + Expected->Children.Namespaces.push_back(RD); + Expected->Children.Records.emplace_back(EmptySID, "OtherChildStruct", + InfoType::IT_record); + Expected->Children.Functions.emplace_back(); + Expected->Children.Functions.back().Name = "OneFunction"; + Expected->Children.Functions.back().USR = NonEmptySID; + Expected->Children.Functions.emplace_back(); + Expected->Children.Functions.back().Name = "TwoFunction"; + Expected->Children.Enums.emplace_back(); + Expected->Children.Enums.back().Name = "OneEnum"; + Expected->Children.Enums.back().USR = NonEmptySID; + Expected->Children.Enums.emplace_back(); + Expected->Children.Enums.back().Name = "TwoEnum"; auto Actual = mergeInfos(Infos); assert(Actual); - CheckNamespaceInfo(InfoAsNamespace(&Expected), InfoAsNamespace(Actual.get())); + CheckNamespaceInfo(InfoAsNamespace(Expected.get()), + InfoAsNamespace(Actual.get().get())); } TEST_F(MergeTest, mergeRecordInfos) { RecordInfo One; One.Name = "r"; One.IsTypeDef = true; - Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - One.Namespace = llvm::ArrayRef(Ns1); + One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); One.DefLoc = Location(10, 10, "test.cpp"); - MemberTypeInfo M1[] = { - MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)}; - One.Members = llvm::ArrayRef(M1); + One.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private); One.TagType = TagTypeKind::Class; - Reference P1[] = {Reference(EmptySID, "F", InfoType::IT_record)}; - One.Parents = llvm::ArrayRef(P1); - Reference VP1[] = {Reference(EmptySID, "G", InfoType::IT_record)}; - One.VirtualParents = llvm::ArrayRef(VP1); + One.Parents.emplace_back(EmptySID, "F", InfoType::IT_record); + One.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); - BaseRecordInfo B1[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true, - AccessSpecifier::AS_protected, true)}; - One.Bases = llvm::ArrayRef(B1); - Reference RCShared1(NonEmptySID, "SharedChildStruct", InfoType::IT_record); - One.Children.Records.push_back(RCShared1); - - FunctionInfo F1; - F1.Name = "OneFunction"; - F1.USR = NonEmptySID; - One.Children.Functions.push_back(F1); - - EnumInfo E1; - E1.Name = "OneEnum"; - E1.USR = NonEmptySID; - One.Children.Enums.push_back(E1); + One.Bases.emplace_back(EmptySID, "F", "path/to/F", true, + AccessSpecifier::AS_protected, true); + One.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct", + InfoType::IT_record); + One.Children.Functions.emplace_back(); + One.Children.Functions.back().Name = "OneFunction"; + One.Children.Functions.back().USR = NonEmptySID; + One.Children.Enums.emplace_back(); + One.Children.Enums.back().Name = "OneEnum"; + One.Children.Enums.back().USR = NonEmptySID; RecordInfo Two; Two.Name = "r"; - Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Two.Namespace = llvm::ArrayRef(Ns2); + Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Location Loc2(12, 12, "test.cpp"); - Two.Loc.push_back(Loc2); + Two.Loc.emplace_back(12, 12, "test.cpp"); Two.TagType = TagTypeKind::Class; - Reference RCShared2(NonEmptySID, "SharedChildStruct", InfoType::IT_record, - "path"); - Two.Children.Records.push_back(RCShared2); - - FunctionInfo F2; - F2.Name = "TwoFunction"; - Two.Children.Functions.push_back(F2); - - EnumInfo E2; - E2.Name = "TwoEnum"; - Two.Children.Enums.push_back(E2); + Two.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct", + InfoType::IT_record, "path"); + Two.Children.Functions.emplace_back(); + Two.Children.Functions.back().Name = "TwoFunction"; + Two.Children.Enums.emplace_back(); + Two.Children.Enums.back().Name = "TwoEnum"; OwningPtrVec Infos; - Infos.push_back(&One); - Infos.push_back(&Two); + Infos.emplace_back(allocatePtr(std::move(One))); + Infos.emplace_back(allocatePtr(std::move(Two))); - RecordInfo Expected; - Expected.Name = "r"; - Expected.IsTypeDef = true; - Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Expected.Namespace = llvm::ArrayRef(NsE); + auto Expected = allocatePtr(); + Expected->Name = "r"; + Expected->IsTypeDef = true; + Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Expected.DefLoc = Location(10, 10, "test.cpp"); - Location LocE(12, 12, "test.cpp"); - Expected.Loc.push_back(LocE); + Expected->DefLoc = Location(10, 10, "test.cpp"); + Expected->Loc.emplace_back(12, 12, "test.cpp"); - MemberTypeInfo ME[] = { - MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)}; - Expected.Members = llvm::ArrayRef(ME); - Expected.TagType = TagTypeKind::Class; - Reference PE[] = {Reference(EmptySID, "F", InfoType::IT_record)}; - Expected.Parents = llvm::ArrayRef(PE); - Reference VPE[] = {Reference(EmptySID, "G", InfoType::IT_record)}; - Expected.VirtualParents = llvm::ArrayRef(VPE); - BaseRecordInfo BE[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true, - AccessSpecifier::AS_protected, true)}; - Expected.Bases = llvm::ArrayRef(BE); + Expected->Members.emplace_back(TypeInfo("int"), "X", + AccessSpecifier::AS_private); + Expected->TagType = TagTypeKind::Class; + Expected->Parents.emplace_back(EmptySID, "F", InfoType::IT_record); + Expected->VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); + Expected->Bases.emplace_back(EmptySID, "F", "path/to/F", true, + AccessSpecifier::AS_protected, true); - Reference RCSharedE(NonEmptySID, "SharedChildStruct", InfoType::IT_record, - "path"); - Expected.Children.Records.push_back(RCSharedE); - FunctionInfo FE1; - FE1.Name = "OneFunction"; - FE1.USR = NonEmptySID; - Expected.Children.Functions.push_back(FE1); - - FunctionInfo FE2; - FE2.Name = "TwoFunction"; - Expected.Children.Functions.push_back(FE2); - - EnumInfo EE1; - EE1.Name = "OneEnum"; - EE1.USR = NonEmptySID; - Expected.Children.Enums.push_back(EE1); - - EnumInfo EE2; - EE2.Name = "TwoEnum"; - Expected.Children.Enums.push_back(EE2); + Expected->Children.Records.emplace_back(NonEmptySID, "SharedChildStruct", + InfoType::IT_record, "path"); + Expected->Children.Functions.emplace_back(); + Expected->Children.Functions.back().Name = "OneFunction"; + Expected->Children.Functions.back().USR = NonEmptySID; + Expected->Children.Functions.emplace_back(); + Expected->Children.Functions.back().Name = "TwoFunction"; + Expected->Children.Enums.emplace_back(); + Expected->Children.Enums.back().Name = "OneEnum"; + Expected->Children.Enums.back().USR = NonEmptySID; + Expected->Children.Enums.emplace_back(); + Expected->Children.Enums.back().Name = "TwoEnum"; auto Actual = mergeInfos(Infos); assert(Actual); - CheckRecordInfo(InfoAsRecord(&Expected), InfoAsRecord(Actual.get())); + CheckRecordInfo(InfoAsRecord(Expected.get()), + InfoAsRecord(Actual.get().get())); } TEST_F(MergeTest, mergeFunctionInfos) { FunctionInfo One; One.Name = "f"; - Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - One.Namespace = llvm::ArrayRef(Ns1); + One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); One.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - One.Loc.push_back(Loc1); + One.Loc.emplace_back(12, 12, "test.cpp"); One.IsMethod = true; One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace); @@ -220,106 +170,89 @@ TEST_F(MergeTest, mergeFunctionInfos) { CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")}; CommentInfo OnePara[] = { CommentInfo(CommentKind::CK_ParagraphComment, OneText)}; - CommentInfo TopOne(CommentKind::CK_FullComment, OnePara); - One.Description.push_back(TopOne); + One.Description.emplace_back(CommentKind::CK_FullComment, OnePara); FunctionInfo Two; Two.Name = "f"; - Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Two.Namespace = llvm::ArrayRef(Ns2); + Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Location Loc2(12, 12, "test.cpp"); - Two.Loc.push_back(Loc2); + Two.Loc.emplace_back(12, 12, "test.cpp"); Two.ReturnType = TypeInfo("void"); - FieldTypeInfo P2(TypeInfo("int"), "P"); - FieldTypeInfo Params2[] = {std::move(P2)}; - Two.Params = llvm::ArrayRef(Params2); + Two.Params.emplace_back(TypeInfo("int"), "P"); CommentInfo TwoText[] = { CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")}; CommentInfo TwoPara[] = { CommentInfo(CommentKind::CK_ParagraphComment, TwoText)}; - CommentInfo TopTwo(CommentKind::CK_FullComment, TwoPara); - Two.Description.push_back(TopTwo); + Two.Description.emplace_back(CommentKind::CK_FullComment, TwoPara); OwningPtrVec Infos; - Infos.push_back(&One); - Infos.push_back(&Two); + Infos.emplace_back(allocatePtr(std::move(One))); + Infos.emplace_back(allocatePtr(std::move(Two))); - FunctionInfo Expected; - Expected.Name = "f"; - Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Expected.Namespace = llvm::ArrayRef(NsE); + auto Expected = allocatePtr(); + Expected->Name = "f"; + Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Expected.DefLoc = Location(10, 10, "test.cpp"); - Location LocE(12, 12, "test.cpp"); - Expected.Loc.push_back(LocE); + Expected->DefLoc = Location(10, 10, "test.cpp"); + Expected->Loc.emplace_back(12, 12, "test.cpp"); - Expected.ReturnType = TypeInfo("void"); - FieldTypeInfo PE(TypeInfo("int"), "P"); - FieldTypeInfo ParamsE[] = {std::move(PE)}; - Expected.Params = llvm::ArrayRef(ParamsE); - Expected.IsMethod = true; - Expected.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace); + Expected->ReturnType = TypeInfo("void"); + Expected->Params.emplace_back(TypeInfo("int"), "P"); + Expected->IsMethod = true; + Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace); CommentInfo ExpectedText[] = { CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")}; CommentInfo ExpectedPara[] = { CommentInfo(CommentKind::CK_ParagraphComment, ExpectedText)}; - CommentInfo TopE(CommentKind::CK_FullComment, ExpectedPara); - Expected.Description.push_back(TopE); + Expected->Description.emplace_back(CommentKind::CK_FullComment, ExpectedPara); auto Actual = mergeInfos(Infos); assert(Actual); - CheckFunctionInfo(InfoAsFunction(&Expected), InfoAsFunction(Actual.get())); + CheckFunctionInfo(InfoAsFunction(Expected.get()), + InfoAsFunction(Actual.get().get())); } TEST_F(MergeTest, mergeEnumInfos) { EnumInfo One; One.Name = "e"; - Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - One.Namespace = llvm::ArrayRef(Ns1); + One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); One.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - One.Loc.push_back(Loc1); + One.Loc.emplace_back(12, 12, "test.cpp"); One.Scoped = true; EnumInfo Two; Two.Name = "e"; - Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Two.Namespace = llvm::ArrayRef(Ns2); + Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Location Loc2(20, 20, "test.cpp"); - Two.Loc.push_back(Loc2); + Two.Loc.emplace_back(20, 20, "test.cpp"); - EnumValueInfo EV2[] = {EnumValueInfo("X"), EnumValueInfo("Y")}; - Two.Members = llvm::ArrayRef(EV2); + Two.Members.emplace_back("X"); + Two.Members.emplace_back("Y"); OwningPtrVec Infos; - Infos.push_back(&One); - Infos.push_back(&Two); + Infos.emplace_back(allocatePtr(std::move(One))); + Infos.emplace_back(allocatePtr(std::move(Two))); - EnumInfo Expected; - Expected.Name = "e"; - Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - Expected.Namespace = llvm::ArrayRef(NsE); + auto Expected = allocatePtr(); + Expected->Name = "e"; + Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - Expected.DefLoc = Location(10, 10, "test.cpp"); - Location LocE1(12, 12, "test.cpp"); - Expected.Loc.push_back(LocE1); - Location LocE2(20, 20, "test.cpp"); - Expected.Loc.push_back(LocE2); + Expected->DefLoc = Location(10, 10, "test.cpp"); + Expected->Loc.emplace_back(12, 12, "test.cpp"); + Expected->Loc.emplace_back(20, 20, "test.cpp"); - EnumValueInfo EV_E[] = {EnumValueInfo("X"), EnumValueInfo("Y")}; - Expected.Members = llvm::ArrayRef(EV_E); - Expected.Scoped = true; + Expected->Members.emplace_back("X"); + Expected->Members.emplace_back("Y"); + Expected->Scoped = true; auto Actual = mergeInfos(Infos); assert(Actual); - CheckEnumInfo(InfoAsEnum(&Expected), InfoAsEnum(Actual.get())); + CheckEnumInfo(InfoAsEnum(Expected.get()), InfoAsEnum(Actual.get().get())); } } // namespace doc diff --git a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp index 371efab1b308..4e963fd64f11 100644 --- a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp @@ -117,27 +117,25 @@ TEST_F(SerializeTest, emitNamespaceInfo) { extractInfosFromCode("namespace A { namespace B { void f() {} } }", 5, /*Public=*/false, Infos, this->Diags); - NamespaceInfo *A = InfoAsNamespace(Infos[0]); + NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedA(EmptySID, "A"); CheckNamespaceInfo(&ExpectedA, A); - NamespaceInfo *B = InfoAsNamespace(Infos[2]); + NamespaceInfo *B = InfoAsNamespace(Infos[2].get()); NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A"); - Reference NsB[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - ExpectedB.Namespace = llvm::ArrayRef(NsB); + ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); CheckNamespaceInfo(&ExpectedB, B); - NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4]); + NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); FunctionInfo F; F.Name = "f"; F.ReturnType = TypeInfo("void"); F.DefLoc = Location(0, 0, "test.cpp"); - Reference NsF[] = {Reference(EmptySID, "B", InfoType::IT_namespace), - Reference(EmptySID, "A", InfoType::IT_namespace)}; - F.Namespace = llvm::ArrayRef(NsF); + F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace); + F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); F.Access = AccessSpecifier::AS_none; - ExpectedBWithFunction.Children.Functions.push_back(F); + ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F)); CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } @@ -146,7 +144,7 @@ TEST_F(SerializeTest, emitAnonymousNamespaceInfo) { extractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos, this->Diags); - NamespaceInfo *A = InfoAsNamespace(Infos[0]); + NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedA(EmptySID); ExpectedA.Name = "@nonymous_namespace"; CheckNamespaceInfo(&ExpectedA, A); @@ -172,103 +170,95 @@ void F::TemplateMethod(); typedef struct {} G;)raw", 10, /*Public=*/false, Infos, this->Diags); - RecordInfo *E = InfoAsRecord(Infos[0]); + RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); - Reference NsE[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedE.Namespace = llvm::ArrayRef(NsE); + ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedE.TagType = TagTypeKind::Class; ExpectedE.DefLoc = Location(0, 0, "test.cpp"); - MemberTypeInfo MemE[] = { - MemberTypeInfo(TypeInfo("int"), "value", AccessSpecifier::AS_public)}; - ExpectedE.Members = llvm::ArrayRef(MemE); + ExpectedE.Members.emplace_back(TypeInfo("int"), "value", + AccessSpecifier::AS_public); // TODO the data member should have the docstring on it: //ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs")); CheckRecordInfo(&ExpectedE, E); - RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2]); + RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get()); RecordInfo ExpectedRecordWithEConstructor(EmptySID); FunctionInfo EConstructor; EConstructor.Name = "E"; EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record); EConstructor.ReturnType = TypeInfo("void"); EConstructor.DefLoc = Location(0, 0, "test.cpp"); - Reference NsEC[] = { - Reference(EmptySID, "E", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - EConstructor.Namespace = llvm::ArrayRef(NsEC); + EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); + EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); EConstructor.Access = AccessSpecifier::AS_public; EConstructor.IsMethod = true; - ExpectedRecordWithEConstructor.Children.Functions.push_back(EConstructor); + ExpectedRecordWithEConstructor.Children.Functions.emplace_back( + std::move(EConstructor)); CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor); - RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3]); + RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get()); RecordInfo ExpectedRecordWithMethod(EmptySID); FunctionInfo Method; Method.Name = "ProtectedMethod"; Method.Parent = Reference(EmptySID, "E", InfoType::IT_record); Method.ReturnType = TypeInfo("void"); - Location LMethod(0, 0, "test.cpp"); - Method.Loc.push_back(LMethod); - Reference NsMethod[] = { - Reference(EmptySID, "E", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - Method.Namespace = llvm::ArrayRef(NsMethod); + Method.Loc.emplace_back(0, 0, "test.cpp"); + Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); + Method.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); Method.Access = AccessSpecifier::AS_protected; Method.IsMethod = true; - ExpectedRecordWithMethod.Children.Functions.push_back(Method); + ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method)); CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod); - RecordInfo *F = InfoAsRecord(Infos[4]); + RecordInfo *F = InfoAsRecord(Infos[4].get()); RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace"); - Reference NsF3[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedF.Namespace = llvm::ArrayRef(NsF3); + ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedF.TagType = TagTypeKind::Struct; ExpectedF.DefLoc = Location(0, 0, "test.cpp"); CheckRecordInfo(&ExpectedF, F); - RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6]); + RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get()); RecordInfo ExpectedRecordWithTemplateMethod(EmptySID); FunctionInfo TemplateMethod; TemplateMethod.Name = "TemplateMethod"; TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record); TemplateMethod.ReturnType = TypeInfo("void"); - Location LTemp1(0, 0, "test.cpp"); - TemplateMethod.Loc.push_back(LTemp1); - Reference NsT1[] = { - Reference(EmptySID, "F", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - TemplateMethod.Namespace = llvm::ArrayRef(NsT1); + TemplateMethod.Loc.emplace_back(0, 0, "test.cpp"); + TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); + TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); TemplateMethod.Access = AccessSpecifier::AS_public; TemplateMethod.IsMethod = true; - ExpectedRecordWithTemplateMethod.Children.Functions.push_back(TemplateMethod); + ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back( + std::move(TemplateMethod)); CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod); - RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7]); + RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get()); RecordInfo ExpectedTemplatedRecord(EmptySID); FunctionInfo SpecializedTemplateMethod; SpecializedTemplateMethod.Name = "TemplateMethod"; SpecializedTemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record); SpecializedTemplateMethod.ReturnType = TypeInfo("void"); - Location LTemp2(0, 0, "test.cpp"); - SpecializedTemplateMethod.Loc.push_back(LTemp2); - Reference NsT2[] = { - Reference(EmptySID, "F", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - SpecializedTemplateMethod.Namespace = llvm::ArrayRef(NsT2); + SpecializedTemplateMethod.Loc.emplace_back(0, 0, "test.cpp"); + SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F", + InfoType::IT_record); + SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); SpecializedTemplateMethod.Access = AccessSpecifier::AS_public; SpecializedTemplateMethod.IsMethod = true; - ExpectedTemplatedRecord.Children.Functions.push_back( - SpecializedTemplateMethod); + ExpectedTemplatedRecord.Children.Functions.emplace_back( + std::move(SpecializedTemplateMethod)); CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord); - RecordInfo *G = InfoAsRecord(Infos[8]); + RecordInfo *G = InfoAsRecord(Infos[8].get()); RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace"); - Reference NsG[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedG.Namespace = llvm::ArrayRef(NsG); + ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedG.TagType = TagTypeKind::Struct; ExpectedG.DefLoc = Location(0, 0, "test.cpp"); ExpectedG.IsTypeDef = true; @@ -281,25 +271,25 @@ TEST_F(SerializeTest, emitEnumInfo) { extractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2, /*Public=*/false, Infos, this->Diags); - NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0]); + NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedNamespaceWithEnum(EmptySID); EnumInfo E; E.Name = "E"; E.DefLoc = Location(0, 0, "test.cpp"); - EnumValueInfo EMem[] = {EnumValueInfo("X", "0"), EnumValueInfo("Y", "1")}; - E.Members = llvm::ArrayRef(EMem); - ExpectedNamespaceWithEnum.Children.Enums.push_back(E); + E.Members.emplace_back("X", "0"); + E.Members.emplace_back("Y", "1"); + ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E)); CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum); - NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1]); + NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID); EnumInfo G; G.Name = "G"; G.Scoped = true; G.DefLoc = Location(0, 0, "test.cpp"); - EnumValueInfo GMem[] = {EnumValueInfo("A", "0"), EnumValueInfo("B", "1")}; - G.Members = llvm::ArrayRef(GMem); - ExpectedNamespaceWithScopedEnum.Children.Enums.push_back(G); + G.Members.emplace_back("A", "0"); + G.Members.emplace_back("B", "1"); + ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G)); CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum); } @@ -307,14 +297,12 @@ TEST_F(SerializeTest, emitUndefinedRecordInfo) { EmittedInfoList Infos; extractInfosFromCode("class E;", 2, /*Public=*/false, Infos, this->Diags); - RecordInfo *E = InfoAsRecord(Infos[0]); + RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); - Reference NsE[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedE.Namespace = llvm::ArrayRef(NsE); + ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedE.TagType = TagTypeKind::Class; - Location LE(0, 0, "test.cpp"); - ExpectedE.Loc.push_back(LE); + ExpectedE.Loc.emplace_back(0, 0, "test.cpp"); CheckRecordInfo(&ExpectedE, E); } @@ -323,16 +311,14 @@ TEST_F(SerializeTest, emitRecordMemberInfo) { extractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos, this->Diags); - RecordInfo *E = InfoAsRecord(Infos[0]); + RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); - Reference NsE[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedE.Namespace = llvm::ArrayRef(NsE); + ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedE.TagType = TagTypeKind::Struct; ExpectedE.DefLoc = Location(0, 0, "test.cpp"); - MemberTypeInfo MemE[] = { - MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_public)}; - ExpectedE.Members = llvm::ArrayRef(MemE); + ExpectedE.Members.emplace_back(TypeInfo("int"), "I", + AccessSpecifier::AS_public); CheckRecordInfo(&ExpectedE, E); } @@ -341,25 +327,23 @@ TEST_F(SerializeTest, emitInternalRecordInfo) { extractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos, this->Diags); - RecordInfo *E = InfoAsRecord(Infos[0]); + RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); - Reference NsE[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedE.Namespace = llvm::ArrayRef(NsE); + ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedE.DefLoc = Location(0, 0, "test.cpp"); ExpectedE.TagType = TagTypeKind::Class; CheckRecordInfo(&ExpectedE, E); - RecordInfo *G = InfoAsRecord(Infos[2]); + RecordInfo *G = InfoAsRecord(Infos[2].get()); llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E"); llvm::sys::path::native(ExpectedGPath); RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath); ExpectedG.DefLoc = Location(0, 0, "test.cpp"); ExpectedG.TagType = TagTypeKind::Class; - Reference NsG[] = { - Reference(EmptySID, "E", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedG.Namespace = llvm::ArrayRef(NsG); + ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record); + ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); CheckRecordInfo(&ExpectedG, G); } @@ -374,14 +358,14 @@ TEST_F(SerializeTest, emitPublicFunctionInternalInfo) { extractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true, Infos, this->Diags); - NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]); + NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); FunctionInfo F; F.Name = "F"; F.ReturnType = TypeInfo("int"); F.DefLoc = Location(0, 0, "test.cpp"); F.Access = AccessSpecifier::AS_none; - ExpectedBWithFunction.Children.Functions.push_back(F); + ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F)); CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } @@ -390,16 +374,15 @@ TEST_F(SerializeTest, emitInlinedFunctionInfo) { extractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos, this->Diags); - NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]); + NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); FunctionInfo F; F.Name = "F"; F.ReturnType = TypeInfo("void"); F.DefLoc = Location(0, 0, "test.cpp"); - FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I")}; - F.Params = llvm::ArrayRef(Params); + F.Params.emplace_back(TypeInfo("int"), "I"); F.Access = AccessSpecifier::AS_none; - ExpectedBWithFunction.Children.Functions.push_back(F); + ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F)); CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } @@ -414,169 +397,132 @@ class I {} ; class J : public I {} ;)raw", 14, /*Public=*/false, Infos, this->Diags); - RecordInfo *F = InfoAsRecord(Infos[0]); + RecordInfo *F = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace"); - Reference NsF[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedF.Namespace = llvm::ArrayRef(NsF); + ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace, ""); ExpectedF.TagType = TagTypeKind::Class; ExpectedF.DefLoc = Location(0, 0, "test.cpp"); CheckRecordInfo(&ExpectedF, F); - RecordInfo *G = InfoAsRecord(Infos[3]); + RecordInfo *G = InfoAsRecord(Infos[3].get()); RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace"); - Reference NsG[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedG.Namespace = llvm::ArrayRef(NsG); + ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedG.TagType = TagTypeKind::Class; ExpectedG.DefLoc = Location(0, 0, "test.cpp"); - MemberTypeInfo MemG[] = { - MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_protected)}; - ExpectedG.Members = llvm::ArrayRef(MemG); + ExpectedG.Members.emplace_back(TypeInfo("int"), "I", + AccessSpecifier::AS_protected); CheckRecordInfo(&ExpectedG, G); - RecordInfo *E = InfoAsRecord(Infos[6]); + RecordInfo *E = InfoAsRecord(Infos[6].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); - Reference NsE[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedE.Namespace = llvm::ArrayRef(NsE); - Reference ParE[] = {Reference(EmptySID, /*Name=*/"F", InfoType::IT_record, - /*QualName=*/"", /*Path=*/"GlobalNamespace")}; - ExpectedE.Parents = llvm::ArrayRef(ParE); - Reference VParE[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record, - /*QualName=*/"G", - /*Path=*/"GlobalNamespace")}; - ExpectedE.VirtualParents = llvm::ArrayRef(VParE); - BaseRecordInfo BaseF(EmptySID, /*Name=*/"F", - /*Path=*/"GlobalNamespace", false, - AccessSpecifier::AS_public, true); + ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); + ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record, + /*QualName=*/"", /*Path*=*/"GlobalNamespace"); + ExpectedE.VirtualParents.emplace_back(EmptySID, /*Name=*/"G", + InfoType::IT_record, /*QualName=*/"G", + /*Path*=*/"GlobalNamespace"); + ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F", + /*Path=*/"GlobalNamespace", false, + AccessSpecifier::AS_public, true); FunctionInfo FunctionSet; FunctionSet.Name = "set"; FunctionSet.ReturnType = TypeInfo("void"); - Location LSet; - FunctionSet.Loc.push_back(LSet); - FieldTypeInfo ParamsSet[] = {FieldTypeInfo(TypeInfo("int"), "N")}; - FunctionSet.Params = llvm::ArrayRef(ParamsSet); - Reference NsSet[] = { - Reference(EmptySID, "F", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - FunctionSet.Namespace = llvm::ArrayRef(NsSet); - FunctionSet.Access = - AccessSpecifier::AS_none; // Wait, previous had AS_protected, but wait, - // F.Access was AS_protected. FunctionSet.Access - // should be AS_protected if it was so. In the - // original it was AS_protected. + FunctionSet.Loc.emplace_back(); + FunctionSet.Params.emplace_back(TypeInfo("int"), "N"); + FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); + FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); FunctionSet.Access = AccessSpecifier::AS_protected; FunctionSet.IsMethod = true; - BaseF.Children.Functions.push_back(FunctionSet); - - BaseRecordInfo BaseG(EmptySID, /*Name=*/"G", - /*Path=*/"GlobalNamespace", true, - AccessSpecifier::AS_private, true); + ExpectedE.Bases.back().Children.Functions.emplace_back( + std::move(FunctionSet)); + ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G", + /*Path=*/"GlobalNamespace", true, + AccessSpecifier::AS_private, true); FunctionInfo FunctionGet; FunctionGet.Name = "get"; FunctionGet.ReturnType = TypeInfo("int"); - Location LGet; - FunctionGet.DefLoc = LGet; - Reference NsGet[] = { - Reference(EmptySID, "G", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - FunctionGet.Namespace = llvm::ArrayRef(NsGet); + FunctionGet.DefLoc = Location(); + FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record); + FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); FunctionGet.Access = AccessSpecifier::AS_private; FunctionGet.IsMethod = true; - BaseG.Children.Functions.push_back(FunctionGet); - MemberTypeInfo MemG2[] = { - MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)}; - BaseG.Members = llvm::ArrayRef(MemG2); - - BaseRecordInfo BasesE[] = {std::move(BaseF), std::move(BaseG)}; - ExpectedE.Bases = llvm::ArrayRef(BasesE); + ExpectedE.Bases.back().Children.Functions.emplace_back( + std::move(FunctionGet)); + ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I", + AccessSpecifier::AS_private); ExpectedE.DefLoc = Location(0, 0, "test.cpp"); ExpectedE.TagType = TagTypeKind::Class; CheckRecordInfo(&ExpectedE, E); - RecordInfo *H = InfoAsRecord(Infos[8]); + RecordInfo *H = InfoAsRecord(Infos[8].get()); RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace"); - Reference NsH[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedH.Namespace = llvm::ArrayRef(NsH); + ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedH.TagType = TagTypeKind::Class; ExpectedH.DefLoc = Location(0, 0, "test.cpp"); - Reference ParH[] = {Reference(EmptySID, /*Name=*/"E", InfoType::IT_record, - /*QualName=*/"E", /*Path=*/"GlobalNamespace")}; - ExpectedH.Parents = llvm::ArrayRef(ParH); - Reference VParH[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record, - /*QualName=*/"G", - /*Path=*/"GlobalNamespace")}; - ExpectedH.VirtualParents = llvm::ArrayRef(VParH); - - BaseRecordInfo BaseHE(EmptySID, /*Name=*/"E", - /*Path=*/"GlobalNamespace", false, - AccessSpecifier::AS_private, true); - - BaseRecordInfo BaseHF(EmptySID, /*Name=*/"F", - /*Path=*/"GlobalNamespace", false, - AccessSpecifier::AS_private, false); + ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record, + /*QualName=*/"E", /*Path=*/"GlobalNamespace"); + ExpectedH.VirtualParents.emplace_back(EmptySID, /*Name=*/"G", + InfoType::IT_record, /*QualName=*/"G", + /*Path=*/"GlobalNamespace"); + ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E", + /*Path=*/"GlobalNamespace", false, + AccessSpecifier::AS_private, true); + ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F", + /*Path=*/"GlobalNamespace", false, + AccessSpecifier::AS_private, false); FunctionInfo FunctionSetNew; FunctionSetNew.Name = "set"; FunctionSetNew.ReturnType = TypeInfo("void"); - Location LSetNew; - FunctionSetNew.Loc.push_back(LSetNew); - FieldTypeInfo ParamsSetNew[] = {FieldTypeInfo(TypeInfo("int"), "N")}; - FunctionSetNew.Params = llvm::ArrayRef(ParamsSetNew); - Reference NsSetNew[] = { - Reference(EmptySID, "F", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - FunctionSetNew.Namespace = llvm::ArrayRef(NsSetNew); + FunctionSetNew.Loc.emplace_back(); + FunctionSetNew.Params.emplace_back(TypeInfo("int"), "N"); + FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record); + FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); FunctionSetNew.Access = AccessSpecifier::AS_private; FunctionSetNew.IsMethod = true; - BaseHF.Children.Functions.push_back(FunctionSetNew); - BaseRecordInfo BaseHG(EmptySID, /*Name=*/"G", - /*Path=*/"GlobalNamespace", true, - AccessSpecifier::AS_private, false); + ExpectedH.Bases.back().Children.Functions.emplace_back( + std::move(FunctionSetNew)); + ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G", + /*Path=*/"GlobalNamespace", true, + AccessSpecifier::AS_private, false); FunctionInfo FunctionGetNew; FunctionGetNew.Name = "get"; FunctionGetNew.ReturnType = TypeInfo("int"); - Location LGetNew; - FunctionGetNew.DefLoc = LGetNew; - Reference NsGetNew[] = { - Reference(EmptySID, "G", InfoType::IT_record), - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - FunctionGetNew.Namespace = llvm::ArrayRef(NsGetNew); + FunctionGetNew.DefLoc = Location(); + FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record); + FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); FunctionGetNew.Access = AccessSpecifier::AS_private; FunctionGetNew.IsMethod = true; - BaseHG.Children.Functions.push_back(FunctionGetNew); - MemberTypeInfo MemHG[] = { - MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)}; - BaseHG.Members = llvm::ArrayRef(MemHG); - - BaseRecordInfo BasesH[] = {std::move(BaseHE), std::move(BaseHF), - std::move(BaseHG)}; - ExpectedH.Bases = llvm::ArrayRef(BasesH); - + ExpectedH.Bases.back().Children.Functions.emplace_back( + std::move(FunctionGetNew)); + ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I", + AccessSpecifier::AS_private); CheckRecordInfo(&ExpectedH, H); - RecordInfo *I = InfoAsRecord(Infos[10]); + RecordInfo *I = InfoAsRecord(Infos[10].get()); RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace"); - Reference NsI[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedI.Namespace = llvm::ArrayRef(NsI); + ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); ExpectedI.TagType = TagTypeKind::Class; ExpectedI.DefLoc = Location(0, 0, "test.cpp"); CheckRecordInfo(&ExpectedI, I); - RecordInfo *J = InfoAsRecord(Infos[12]); + RecordInfo *J = InfoAsRecord(Infos[12].get()); RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace"); - Reference NsJ[] = { - Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)}; - ExpectedJ.Namespace = llvm::ArrayRef(NsJ); - Reference ParJ[] = { - Reference(EmptySID, /*Name=*/"I", InfoType::IT_record)}; - ExpectedJ.Parents = llvm::ArrayRef(ParJ); - BaseRecordInfo BasesJ[] = {BaseRecordInfo(EmptySID, /*Name=*/"I", - /*Path=*/"GlobalNamespace", false, - AccessSpecifier::AS_public, true)}; - ExpectedJ.Bases = llvm::ArrayRef(BasesJ); + ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace", + InfoType::IT_namespace); + ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I", + InfoType::IT_record); + ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I", + /*Path=*/"GlobalNamespace", false, + AccessSpecifier::AS_public, true); ExpectedJ.DefLoc = Location(0, 0, "test.cpp"); ExpectedJ.TagType = TagTypeKind::Class; CheckRecordInfo(&ExpectedJ, J); @@ -592,33 +538,30 @@ static int staticModuleFunction(int x); export double exportedModuleFunction(double y);)raw", 2, /*Public=*/true, Infos, Args, this->Diags); - NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]); + NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); FunctionInfo F; F.Name = "moduleFunction"; F.ReturnType = TypeInfo("int"); - Location LF1(0, 0, "test.cpp"); - F.Loc.push_back(LF1); - FieldTypeInfo ParamsF[] = {FieldTypeInfo(TypeInfo("int"), "x"), - FieldTypeInfo(TypeInfo("double"), "d")}; - ParamsF[1].DefaultValue = "3.2 - 1.0"; - F.Params = llvm::ArrayRef(ParamsF); + F.Loc.emplace_back(0, 0, "test.cpp"); + F.Params.emplace_back(TypeInfo("int"), "x"); + F.Params.emplace_back(TypeInfo("double"), "d"); + F.Params.back().DefaultValue = "3.2 - 1.0"; F.Access = AccessSpecifier::AS_none; - ExpectedBWithFunction.Children.Functions.push_back(F); + ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F)); CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); - NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1]); + NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedBWithExportedFunction(EmptySID); FunctionInfo ExportedF; ExportedF.Name = "exportedModuleFunction"; ExportedF.ReturnType = TypeInfo(Reference(EmptySID, "double", InfoType::IT_default)); - Location LF2(0, 0, "test.cpp"); - ExportedF.Loc.push_back(LF2); - FieldTypeInfo ParamsExportedF[] = {FieldTypeInfo(TypeInfo("double"), "y")}; - ExportedF.Params = llvm::ArrayRef(ParamsExportedF); + ExportedF.Loc.emplace_back(0, 0, "test.cpp"); + ExportedF.Params.emplace_back(TypeInfo("double"), "y"); ExportedF.Access = AccessSpecifier::AS_none; - ExpectedBWithExportedFunction.Children.Functions.push_back(ExportedF); + ExpectedBWithExportedFunction.Children.Functions.emplace_back( + std::move(ExportedF)); CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction); } @@ -628,24 +571,24 @@ TEST_F(SerializeTest, emitChildRecords) { extractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8, /*Public=*/false, Infos, this->Diags); - NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]); + NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedParentA(EmptySID); - Reference RA(EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace"); - ExpectedParentA.Children.Records.push_back(RA); + ExpectedParentA.Children.Records.emplace_back( + EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace"); CheckNamespaceInfo(&ExpectedParentA, ParentA); - RecordInfo *ParentB = InfoAsRecord(Infos[3]); + RecordInfo *ParentB = InfoAsRecord(Infos[3].get()); RecordInfo ExpectedParentB(EmptySID); llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A"); llvm::sys::path::native(ExpectedParentBPath); - Reference RB(EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath); - ExpectedParentB.Children.Records.push_back(RB); + ExpectedParentB.Children.Records.emplace_back( + EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath); CheckRecordInfo(&ExpectedParentB, ParentB); - NamespaceInfo *ParentC = InfoAsNamespace(Infos[7]); + NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get()); NamespaceInfo ExpectedParentC(EmptySID); - Reference RC(EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace"); - ExpectedParentC.Children.Records.push_back(RC); + ExpectedParentC.Children.Records.emplace_back( + EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace"); CheckNamespaceInfo(&ExpectedParentC, ParentC); } @@ -655,13 +598,13 @@ TEST_F(SerializeTest, emitChildNamespaces) { extractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false, Infos, this->Diags); - NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]); + NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedParentA(EmptySID); Reference RA(EmptySID, "A", InfoType::IT_namespace); ExpectedParentA.Children.Namespaces.push_back(RA); CheckNamespaceInfo(&ExpectedParentA, ParentA); - NamespaceInfo *ParentB = InfoAsNamespace(Infos[3]); + NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get()); NamespaceInfo ExpectedParentB(EmptySID); Reference RB(EmptySID, "B", InfoType::IT_namespace, "A::B", "A"); ExpectedParentB.Children.Namespaces.push_back(RB); @@ -674,10 +617,10 @@ TEST_F(SerializeTest, emitTypedefs) { /*Public=*/false, Infos, this->Diags); // First info will be the global namespace with the typedef in it. - NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]); + NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get()); ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size()); - const TypedefInfo &FirstTD = *GlobalNS1->Children.Typedefs.begin(); + const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0]; EXPECT_EQ("MyInt", FirstTD.Name); EXPECT_FALSE(FirstTD.IsUsing); EXPECT_EQ("int", FirstTD.Underlying.Type.Name); @@ -685,11 +628,11 @@ TEST_F(SerializeTest, emitTypedefs) { // The second will be another global namespace with the using in it (the // global namespace is duplicated because the items haven't been merged at the // serialization phase of processing). - NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]); + NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get()); ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size()); // Second is the "using" typedef. - const TypedefInfo &SecondTD = *GlobalNS2->Children.Typedefs.begin(); + const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0]; EXPECT_EQ("MyDouble", SecondTD.Name); EXPECT_TRUE(SecondTD.IsUsing); EXPECT_EQ("double", SecondTD.Underlying.Type.Name); @@ -704,10 +647,10 @@ TEST_F(SerializeTest, emitFunctionTemplate) { /*Public=*/false, Infos, this->Diags); // First info will be the global namespace. - NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]); + NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get()); ASSERT_EQ(1u, GlobalNS1->Children.Functions.size()); - const FunctionInfo &Func1 = *GlobalNS1->Children.Functions.begin(); + const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0]; EXPECT_EQ("GetFoo", Func1.Name); ASSERT_TRUE(Func1.Template); EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization. @@ -719,11 +662,11 @@ TEST_F(SerializeTest, emitFunctionTemplate) { // The second will be another global namespace with the function in it (the // global namespace is duplicated because the items haven't been merged at the // serialization phase of processing). - NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]); + NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get()); ASSERT_EQ(1u, GlobalNS2->Children.Functions.size()); // This one is a template specialization. - const FunctionInfo &Func2 = *GlobalNS2->Children.Functions.begin(); + const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0]; EXPECT_EQ("GetFoo", Func2.Name); ASSERT_TRUE(Func2.Template); EXPECT_TRUE(Func2.Template->Params.empty()); // No template params. @@ -751,7 +694,7 @@ TEST_F(SerializeTest, emitClassTemplate) { /*Public=*/false, Infos, this->Diags); // First record. - const RecordInfo *Rec1 = InfoAsRecord(Infos[0]); + const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get()); EXPECT_EQ("MyTemplate", Rec1->Name); ASSERT_TRUE(Rec1->Template); EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization. @@ -761,7 +704,7 @@ TEST_F(SerializeTest, emitClassTemplate) { EXPECT_EQ("int I", Rec1->Template->Params[0].Contents); // Second record. - const RecordInfo *Rec2 = InfoAsRecord(Infos[2]); + const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get()); EXPECT_EQ("MyTemplate", Rec2->Name); ASSERT_TRUE(Rec2->Template); EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params. @@ -773,7 +716,7 @@ TEST_F(SerializeTest, emitClassTemplate) { EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf); // Third record. - const RecordInfo *Rec3 = InfoAsRecord(Infos[4]); + const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get()); EXPECT_EQ("OtherTemplate", Rec3->Name); ASSERT_TRUE(Rec3->Template); @@ -783,7 +726,7 @@ TEST_F(SerializeTest, emitClassTemplate) { EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents); // Fourth record. - const RecordInfo *Rec4 = InfoAsRecord(Infos[6]); + const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get()); EXPECT_EQ("OtherTemplate", Rec3->Name); ASSERT_TRUE(Rec4->Template); ASSERT_TRUE(Rec4->Template->Specialization); diff --git a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp index 6f4b724bd942..a7f8629b926c 100644 --- a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp @@ -28,25 +28,20 @@ TEST_F(YAMLGeneratorTest, emitNamespaceYAML) { NamespaceInfo I; I.Name = "Namespace"; I.Path = "path/to/A"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace, "path::to::A::Namespace::ChildNamespace", "path/to/A/Namespace"); I.Children.Namespaces.push_back(NewNamespace); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record, - "path::to::A::Namespace::ChildStruct", - "path/to/A/Namespace"); - I.Children.Records.push_back(ChildStruct); - FunctionInfo F; - F.Name = "OneFunction"; - F.Access = AccessSpecifier::AS_none; - I.Children.Functions.push_back(F); - - EnumInfo E; - E.Name = "OneEnum"; - I.Children.Enums.push_back(E); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, + "path::to::A::Namespace::ChildStruct", + "path/to/A/Namespace"); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "OneEnum"; auto G = getYAMLGenerator(); assert(G); @@ -90,14 +85,12 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) { I.Name = "r"; I.Path = "path/to/A"; I.IsTypeDef = true; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private); + I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private); // Member documentation. CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {}, @@ -106,39 +99,26 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) { CommentInfo TopCommentChildren[] = { CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)}; CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren); - M.Description.push_back(TopComment); - MemberTypeInfo MemArr[] = {std::move(M)}; - I.Members = llvm::ArrayRef(MemArr); + I.Members.back().Description.push_back(std::move(TopComment)); I.TagType = TagTypeKind::Class; - BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public, - true); - FunctionInfo F; - F.Name = "InheritedFunctionOne"; - B.Children.Functions.push_back(F); - MemberTypeInfo BMem[] = { - MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_private)}; - B.Members = llvm::ArrayRef(BMem); - BaseRecordInfo Bases[] = {std::move(B)}; - I.Bases = llvm::ArrayRef(Bases); - + I.Bases.emplace_back(EmptySID, "F", "path/to/F", true, + AccessSpecifier::AS_public, true); + I.Bases.back().Children.Functions.emplace_back(); + I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne"; + I.Bases.back().Members.emplace_back(TypeInfo("int"), "N", + AccessSpecifier::AS_private); // F is in the global namespace - Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")}; - I.Parents = llvm::ArrayRef(Parents); - Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record, - "path::to::G::G", "path/to/G")}; - I.VirtualParents = llvm::ArrayRef(VParents); + I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, ""); + I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record, + "path::to::G::G", "path/to/G"); - Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record, - "path::to::A::r::ChildStruct", "path/to/A/r"); - I.Children.Records.push_back(ChildStruct); - FunctionInfo F2; - F2.Name = "OneFunction"; - I.Children.Functions.push_back(F2); - - EnumInfo E; - E.Name = "OneEnum"; - I.Children.Enums.push_back(E); + I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, + "path::to::A::r::ChildStruct", "path/to/A/r"); + I.Children.Functions.emplace_back(); + I.Children.Functions.back().Name = "OneFunction"; + I.Children.Enums.emplace_back(); + I.Children.Enums.back().Name = "OneEnum"; auto G = getYAMLGenerator(); assert(G); @@ -225,22 +205,17 @@ ChildEnums: TEST_F(YAMLGeneratorTest, emitFunctionYAML) { FunctionInfo I; I.Name = "f"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); I.Access = AccessSpecifier::AS_none; I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default)); - - FieldTypeInfo P1(TypeInfo("int"), "P"); - FieldTypeInfo D(TypeInfo("double"), "D"); - D.DefaultValue = "2.0 * M_PI"; - FieldTypeInfo Params[] = {std::move(P1), std::move(D)}; - I.Params = llvm::ArrayRef(Params); + I.Params.emplace_back(TypeInfo("int"), "P"); + I.Params.emplace_back(TypeInfo("double"), "D"); + I.Params.back().DefaultValue = "2.0 * M_PI"; I.IsMethod = true; I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); @@ -295,15 +270,12 @@ ReturnType: TEST_F(YAMLGeneratorTest, emitSimpleEnumYAML) { EnumInfo I; I.Name = "e"; - Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)}; - I.Namespace = llvm::ArrayRef(Ns); + I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, 10, "test.cpp"); - Location Loc1(12, 12, "test.cpp"); - I.Loc.push_back(Loc1); + I.Loc.emplace_back(12, 12, "test.cpp"); - EnumValueInfo EV[] = {EnumValueInfo("X")}; - I.Members = llvm::ArrayRef(EV); + I.Members.emplace_back("X"); I.Scoped = false; auto G = getYAMLGenerator(); @@ -340,8 +312,7 @@ TEST_F(YAMLGeneratorTest, enumTypedScopedEnumYAML) { EnumInfo I; I.Name = "e"; - EnumValueInfo EV[] = {EnumValueInfo("X", "-9876", "FOO_BAR + 2")}; - I.Members = llvm::ArrayRef(EV); + I.Members.emplace_back("X", "-9876", "FOO_BAR + 2"); I.Scoped = true; I.BaseType = TypeInfo("short"); @@ -399,9 +370,8 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) { I.Name = "f"; I.DefLoc = Location(10, 10, "test.cpp"); I.ReturnType = TypeInfo("void"); - FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I"), - FieldTypeInfo(TypeInfo("int"), "J")}; - I.Params = llvm::ArrayRef(Params); + I.Params.emplace_back(TypeInfo("int"), "I"); + I.Params.emplace_back(TypeInfo("int"), "J"); I.Access = AccessSpecifier::AS_none; // BlankLine @@ -474,7 +444,7 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) { Verbatim, ParamOut, ParamIn, Return}; CommentInfo Top(CommentKind::CK_FullComment, TopChildren); - I.Description.push_back(Top); + I.Description.emplace_back(std::move(Top)); auto G = getYAMLGenerator(); assert(G);