[llvm-branch-commits] [clang-tools-extra] [clang-doc] Move Info types into arenas (PR #190054)
Paul Kirth via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Apr 3 14:12:12 PDT 2026
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/190054
>From 479a4cc3260f4b85aaeba7c4aa5334b55496851d Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Sat, 28 Mar 2026 07:54:24 +0000
Subject: [PATCH] [clang-doc] Move Info types into arenas
Info types used to own significant chunks of data. As we move these into
local arenas, these types must be trivially destructible, to avoid
leaking resources when the arena is reset. Unfortunaly, there isn't a
good way to transition all the data types one at a time, since most of
them are tied together in some way. Further, as they're now allocated in
the arenas, they often cannot be treated the same way, and even the
aliases and interfaces put in pLace to simplify the transition cannot
cover the full range of changes required.
We also use some SFINAE tricks to avoid adding boilerplate for helper
APIs, we'd otherwise ahve to support
Though it introduces some additional churn, we also try to keep tests
from using arena allocation as much as possible, since this is not
required to test the implementation of the library. As much of the test
code needed to be rewritten anyway, we take the opportunity to
transition now.
We see a large improvement in overall memory use, dropping by 15% over
the previous patches, and taking the total savings down to almost 54%.
Performance numbers stay mostly flat, but merging is vastly improved,
seeing a reduction of 40+% over the previous patch, and a 90% reduction
overall.
| Metric | Baseline | Prev | This | Culm% | Seq% |
| :--- | :--- | :--- | :--- | :--- | :--- |
| Time | 920.5s | 1013.6s | 1014.5s | +10.2% | +0.1% |
| Memory | 86.0G | 47.3G | 39.9G | -53.6% | -15.6% |
| Benchmark | Baseline | Prev | This | Culm% | Seq% |
| :--- | :--- | :--- | :--- | :--- | :--- |
| BM_BitcodeReader_Scale/10 | 67.9us | 69.1us | 73.0us | +7.5% | +5.8% |
| BM_BitcodeReader_Scale/10000 | 70.5ms | 24.5ms | 17.1ms | -75.8% | -30.4% |
| BM_BitcodeReader_Scale/4096 | 23.2ms | 4.5ms | 6.5ms | -71.9% | +45.1% |
| BM_BitcodeReader_Scale/512 | 509.4us | 540.3us | 850.1us | +66.9% | +57.4% |
| BM_BitcodeReader_Scale/64 | 114.8us | 117.3us | 140.6us | +22.5% | +19.9% |
| BM_EmitInfoFunction | 1.6us | 1.6us | 1.8us | +12.9% | +15.0% |
| BM_Index_Insertion/10 | 2.3us | 4.2us | 4.1us | +79.5% | -1.1% |
| BM_Index_Insertion/10000 | 3.1ms | 5.2ms | 5.4ms | +71.1% | +3.7% |
| BM_Index_Insertion/4096 | 1.3ms | 2.1ms | 2.1ms | +64.9% | +2.0% |
| BM_Index_Insertion/512 | 153.6us | 244.7us | 252.9us | +64.7% | +3.3% |
| BM_Index_Insertion/64 | 18.1us | 29.1us | 30.4us | +68.3% | +4.4% |
| BM_JSONGenerator_Scale/10 | 36.8us | 38.3us | 38.1us | +3.5% | -0.4% |
| BM_JSONGenerator_Scale/10000 | 89.6ms | 90.8ms | 84.2ms | -6.0% | -7.2% |
| BM_JSONGenerator_Scale/4096 | 33.7ms | 35.9ms | 32.1ms | -4.7% | -10.5% |
| BM_JSONGenerator_Scale/512 | 1.9ms | 2.0ms | 2.0ms | +3.1% | +0.4% |
| BM_JSONGenerator_Scale/64 | 222.4us | 231.9us | 232.5us | +4.5% | +0.2% |
| BM_Mapper_Scale/10000 | 104.3ms | 104.9ms | 102.1ms | -2.1% | -2.7% |
| BM_Mapper_Scale/4096 | 44.3ms | 44.4ms | 46.5ms | +4.9% | +4.9% |
| BM_Mapper_Scale/512 | 7.6ms | 7.6ms | 7.4ms | -2.1% | -1.8% |
| BM_Mapper_Scale/64 | 3.1ms | 3.0ms | 3.0ms | -1.3% | -0.0% |
| BM_MergeInfos_Scale/10000 | 12.2ms | 1.9ms | 931.2us | -92.4% | -49.8% |
| BM_MergeInfos_Scale/2 | 1.9us | 1.7us | 1.8us | -4.5% | +4.7% |
| BM_MergeInfos_Scale/4096 | 2.8ms | 521.8us | 201.3us | -92.8% | -61.4% |
| BM_MergeInfos_Scale/512 | 68.9us | 34.9us | 19.9us | -71.2% | -43.1% |
| BM_MergeInfos_Scale/64 | 10.3us | 5.8us | 4.1us | -59.8% | -28.4% |
| BM_MergeInfos_Scale/8 | 2.8us | 2.1us | 1.9us | -33.3% | -12.6% |
| BM_SerializeFunctionInfo | 25.5us | 26.0us | 26.2us | +2.4% | +0.8% |
---
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 | 46 +-
clang-tools-extra/clang-doc/Representation.h | 110 ++--
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 +-
.../unittests/clang-doc/BitcodeTest.cpp | 113 ++--
.../unittests/clang-doc/ClangDocTest.cpp | 274 +++++---
.../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 | 335 ++++++----
.../unittests/clang-doc/SerializeTest.cpp | 435 +++++++------
.../unittests/clang-doc/YAMLGeneratorTest.cpp | 112 ++--
20 files changed, 1660 insertions(+), 954 deletions(-)
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index b7f4d6aa7ba23..c5e848ae4c28d 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -129,14 +129,15 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
"invalid value for FieldId");
}
-static llvm::Error decodeRecord(const Record &R,
- llvm::SmallVectorImpl<Location> &Field,
+static llvm::Error decodeRecord(const Record &R, OwningVec<Location> &Field,
llvm::StringRef Blob) {
if (R[0] > INT_MAX)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"integer too large to parse");
- Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
- static_cast<bool>(R[2]));
+
+ Field.push_back(*allocatePtr<Location>(static_cast<int>(R[0]),
+ static_cast<int>(R[1]), Blob,
+ static_cast<bool>(R[2])));
return llvm::Error::success();
}
@@ -425,6 +426,99 @@ ClangDocBitcodeReader::parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
}
}
+template <typename T, typename BlockBeginHandler, typename BlockEndHandler>
+llvm::Error ClangDocBitcodeReader::parseBlock(unsigned ID, T I,
+ BlockBeginHandler &&BBH,
+ BlockEndHandler &&BEH) {
+ return parseBlock(ID, I, std::forward<BlockBeginHandler>(BBH),
+ std::forward<BlockEndHandler>(BEH),
+ [&](unsigned Code) { return readRecord(Code, I); });
+}
+
+template <typename ChildType>
+llvm::Expected<bool> ClangDocBitcodeReader::readSubBlockIfMatch(
+ unsigned ID, unsigned TargetID, llvm::SmallVectorImpl<ChildType> &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 <typename T>
+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 <typename InfoT>
+llvm::Expected<bool> ClangDocBitcodeReader::routeReferenceBlock(
+ unsigned ID, llvm::SmallVectorImpl<Reference> &Namespaces, InfoT *I,
+ std::initializer_list<ReferenceMap> 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<CommentInfo> LocalChildren;
@@ -448,25 +542,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
if (!LocalChildren.empty())
I->Children =
allocateArray<CommentInfo>(LocalChildren, TransientArena);
- if (!AttrKeys.empty()) {
- StringRef *KeysMem =
- TransientArena.Allocate<StringRef>(AttrKeys.size());
- std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
- I->AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
- }
- if (!AttrValues.empty()) {
- StringRef *ValuesMem =
- TransientArena.Allocate<StringRef>(AttrValues.size());
- std::uninitialized_copy(AttrValues.begin(), AttrValues.end(),
- ValuesMem);
- I->AttrValues =
- llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
- }
- if (!Args.empty()) {
- StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
- std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
- I->Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
- }
+ if (!AttrKeys.empty())
+ I->AttrKeys = allocateArray(AttrKeys, TransientArena);
+ if (!AttrValues.empty())
+ I->AttrValues = allocateArray(AttrValues, TransientArena);
+ if (!Args.empty())
+ I->Args = allocateArray(Args, TransientArena);
+
return llvm::Error::success();
},
[&](unsigned BlockOrCode) -> llvm::Error {
@@ -481,6 +563,219 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
});
}
+template <>
+llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) {
+ llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
+ llvm::SmallVector<Reference> LocalNamespaces;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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<EnumValueInfo, 4> LocalMembers;
+ llvm::SmallVector<Reference> LocalNamespaces;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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<BaseRecordInfo, 4> LocalBases;
+ llvm::SmallVector<FriendInfo, 4> LocalFriends;
+ llvm::SmallVector<MemberTypeInfo> LocalMembers;
+ llvm::SmallVector<Reference> LocalParents;
+ llvm::SmallVector<Reference> LocalVirtualParents;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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<Reference> 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<BaseRecordInfo, 4> LocalBases;
+ llvm::SmallVector<FriendInfo, 4> LocalFriends;
+ llvm::SmallVector<MemberTypeInfo> LocalMembers;
+ llvm::SmallVector<Reference> LocalParents;
+ llvm::SmallVector<Reference> LocalVirtualParents;
+ llvm::SmallVector<Reference> LocalNamespaces;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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<TemplateParamInfo> LocalParams;
+ llvm::SmallVector<ConstraintInfo> LocalConstraints;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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<TemplateParamInfo> LocalParams;
+
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ 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) {
@@ -579,51 +874,25 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
"invalid field for Friend");
}
+template <typename, typename = void>
+struct has_description : std::false_type {};
+template <typename T>
+struct has_description<T, std::void_t<decltype(std::declval<T>().Description)>>
+ : std::true_type {};
+
template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
+ if constexpr (std::is_pointer_v<T>) {
+ using Pointee = std::remove_pointer_t<T>;
+ if constexpr (has_description<Pointee>::value) {
+ auto *NewComment = allocatePtr<CommentInfo>();
+ I->Description.push_back(*NewComment);
+ return NewComment;
+ }
+ }
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid type cannot contain CommentInfo");
}
-template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {
- return &I->Description.emplace_back();
-}
-
-template <> Expected<CommentInfo *> 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.
@@ -633,26 +902,11 @@ 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();
@@ -681,9 +935,6 @@ 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");
@@ -727,9 +978,6 @@ 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");
@@ -738,9 +986,6 @@ 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");
@@ -750,16 +995,13 @@ 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_namespace:
- I->Namespace.emplace_back(std::move(R));
- return llvm::Error::success();
- case FieldId::F_child_namespace: {
- Reference *NewR = allocatePtr<Reference>(TransientArena, std::move(R));
- I->Children.Namespaces.push_back(*NewR);
+ case FieldId::F_child_namespace:
+ I->Children.Namespaces.push_back(
+ *allocatePtr<Reference>(TransientArena, std::move(R)));
return llvm::Error::success();
- }
case FieldId::F_child_record:
- I->Children.Records.emplace_back(std::move(R));
+ I->Children.Records.push_back(
+ *allocatePtr<Reference>(TransientArena, std::move(R)));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -770,9 +1012,6 @@ 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();
@@ -784,17 +1023,9 @@ 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.emplace_back(std::move(R));
+ I->Children.Records.push_back(
+ *allocatePtr<Reference>(TransientArena, std::move(R)));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -823,54 +1054,42 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
"Friend cannot contain this Reference");
}
-template <typename T, typename ChildInfoType>
-static void addChild(T I, ChildInfoType &&R) {
+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 <typename T, typename = void> struct has_children : std::false_type {};
+template <typename T>
+struct has_children<T, std::void_t<decltype(std::declval<T>().Children)>>
+ : std::is_same<decltype(std::declval<T>().Children), ScopeChildren> {};
+
+template <typename TargetChild, typename = void>
+struct is_valid_child : std::false_type {};
+template <typename TargetChild>
+struct is_valid_child<
+ TargetChild, std::void_t<decltype(getList(std::declval<ScopeChildren &>(),
+ std::declval<TargetChild *>()))>>
+ : std::true_type {};
+
+template <typename Target, typename Child>
+static void addChild(Target I, Child &&R) {
+ if constexpr (std::is_pointer_v<Target>) {
+ using Pointee = std::remove_pointer_t<Target>;
+ if constexpr (has_children<Pointee>::value) {
+ using BareChild = std::remove_cv_t<std::remove_reference_t<Child>>;
+ if constexpr (is_valid_child<BareChild>::value) {
+ auto *Node = allocatePtr<BareChild>(std::move(R));
+ getList(I->Children, Node).push_back(*Node);
+ return;
+ }
+ }
+ }
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).
@@ -879,13 +1098,6 @@ template <typename T> 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 <typename T> static void addTemplate(T I, TemplateInfo &&P) {
@@ -925,9 +1137,6 @@ template <typename T> 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 <typename T>
@@ -952,6 +1161,37 @@ 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 <typename T>
+llvm::Error ClangDocBitcodeReader::readBlockWithNamespace(unsigned ID, T I) {
+ llvm::SmallVector<Reference> LocalNamespaces;
+ return parseBlock(
+ ID, I,
+ [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
+ return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
+ },
+ [&]() -> llvm::Error {
+ if (!LocalNamespaces.empty())
+ I->Namespace = allocateArray(LocalNamespaces, TransientArena);
+ return llvm::Error::success();
+ });
+}
+
template <typename T>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
return parseBlock(
@@ -969,13 +1209,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
return parseBlock(
ID, I,
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
- 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));
+ auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID,
+ LocalParams);
+ if (!B)
+ return B.takeError();
+ if (*B)
return true;
- }
+
return false;
},
[&]() -> llvm::Error {
@@ -988,27 +1228,19 @@ 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 <typename InfoType, typename T, typename Callback>
llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
Callback Function) {
InfoType Info;
if (auto Err = readBlock(ID, &Info))
return Err;
- Function(Parent, std::move(Info));
- return llvm::Error::success();
-}
-
-template <typename InfoType, typename T, typename Callback>
-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();
+ if constexpr (std::is_void_v<
+ std::invoke_result_t<Callback, T, InfoType &&>>) {
+ Function(Parent, std::move(Info));
+ return llvm::Error::success();
+ } else {
+ return Function(Parent, std::move(Info));
+ }
}
template <typename T>
@@ -1032,15 +1264,15 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
return llvm::Error::success();
}
case BI_TYPE_BLOCK_ID: {
- return handleTypeSubBlock<TypeInfo>(
- ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
+ return handleSubBlock<TypeInfo>(ID, I,
+ CreateAddFunc(addTypeInfo<T, TypeInfo>));
}
case BI_FIELD_TYPE_BLOCK_ID: {
- return handleTypeSubBlock<FieldTypeInfo>(
+ return handleSubBlock<FieldTypeInfo>(
ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
}
case BI_MEMBER_TYPE_BLOCK_ID: {
- return handleTypeSubBlock<MemberTypeInfo>(
+ return handleSubBlock<MemberTypeInfo>(
ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
}
case BI_REFERENCE_BLOCK_ID: {
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.h b/clang-tools-extra/clang-doc/BitcodeReader.h
index d3499fdee0f5d..4585cb454f408 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.h
+++ b/clang-tools-extra/clang-doc/BitcodeReader.h
@@ -44,12 +44,32 @@ class ClangDocBitcodeReader {
// Read a block of records into a single Info struct, calls readRecord on each
// record found.
template <typename T> llvm::Error readBlock(unsigned ID, T I);
+ template <typename T> llvm::Error readBlockWithNamespace(unsigned ID, T I);
template <typename T, typename BlockBeginHandler, typename BlockEndHandler,
typename RecordHandler>
llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
BlockEndHandler &&BEH, RecordHandler &&RH);
+ template <typename T, typename BlockBeginHandler, typename BlockEndHandler>
+ llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
+ BlockEndHandler &&BEH);
+
+ template <typename ChildType>
+ llvm::Expected<bool> readSubBlockIfMatch(unsigned ID, unsigned TargetID,
+ llvm::SmallVectorImpl<ChildType> &V);
+
+ struct ReferenceMap {
+ FieldId Field;
+ llvm::SmallVectorImpl<Reference> *Vec;
+ };
+
+ template <typename InfoT>
+ llvm::Expected<bool>
+ routeReferenceBlock(unsigned ID, llvm::SmallVectorImpl<Reference> &Namespaces,
+ InfoT *I,
+ std::initializer_list<ReferenceMap> Mappings = {});
+
// Step through a block of records to find the next data field.
template <typename T> 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 1615e553fe109..b8f78122350f1 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -27,6 +27,7 @@ class JSONGenerator : public Generator {
void serializeCommonChildren(
const ScopeChildren &Children, json::Object &Obj,
std::optional<ReferenceFunc> MDReferenceLambda = std::nullopt);
+ void serializeContexts(Info *I, llvm::StringMap<OwnedPtr<Info>> &Infos);
void serializeInfo(const ConstraintInfo &I, Object &Obj);
void serializeInfo(const TemplateInfo &Template, Object &Obj);
void serializeInfo(const ConceptInfo &I, Object &Obj);
@@ -61,11 +62,13 @@ class JSONGenerator : public Generator {
};
}
-public:
- static const char *Format;
+ llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
const ClangDocContext *CDCtx;
bool Markdown;
+public:
+ static const char *Format;
+
Error generateDocumentation(StringRef RootDir,
llvm::StringMap<OwnedPtr<doc::Info>> Infos,
const ClangDocContext &CDCtx,
@@ -320,13 +323,20 @@ 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) {
- json::Value ContextArray = json::Array();
- auto &ContextArrayRef = *ContextArray.getAsArray();
- ContextArrayRef.reserve(I.Contexts.size());
+ 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());
std::string CurrentRelativePath;
bool PreviousRecord = false;
- for (const auto &Current : I.Contexts) {
+ for (const auto &Current : Contexts) {
json::Value ContextVal = Object();
Object &Context = *ContextVal.getAsObject();
serializeReference(Current, Context);
@@ -372,11 +382,9 @@ void JSONGenerator::generateContext(const Info &I, Object &Obj) {
}
ContextArrayRef.back().getAsObject()->insert({"End", true});
- Obj["Contexts"] = ContextArray;
- Obj["HasContexts"] = true;
}
-static void serializeDescription(llvm::ArrayRef<CommentInfo> Description,
+static void serializeDescription(const OwningVec<CommentInfo> &Description,
json::Object &Obj, StringRef Key = "") {
if (Description.empty())
return;
@@ -429,7 +437,8 @@ void JSONGenerator::serializeCommonAttributes(const Info &I,
Obj["Location"] = serializeLocation(Symbol->DefLoc.value());
}
- if (!I.Contexts.empty())
+ auto It = ContextsMap.find(&I);
+ if (It != ContextsMap.end() && !It->second.empty())
generateContext(I, Obj);
}
@@ -834,9 +843,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 OwningVec<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
+static std::vector<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
CDCtxIndex.sort();
- OwningVec<Index> Processed;
+ std::vector<Index> Processed;
Processed.reserve(CDCtxIndex.Children.size());
for (const auto *Idx : CDCtxIndex.getSortedChildren()) {
Index NewIdx = *Idx;
@@ -856,7 +865,7 @@ Error JSONGenerator::serializeAllFiles(const ClangDocContext &CDCtx,
StringRef RootDir) {
json::Value ObjVal = Object();
Object &Obj = *ObjVal.getAsObject();
- OwningVec<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
+ std::vector<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
serializeArray(IndexCopy, Obj, "Index", serializeReferenceLambda());
SmallString<128> Path;
sys::path::append(Path, RootDir, "json", "all_files.json");
@@ -919,10 +928,12 @@ Error JSONGenerator::serializeIndex(StringRef RootDir) {
return Error::success();
}
-static void serializeContexts(Info *I, StringMap<OwnedPtr<Info>> &Infos) {
+void JSONGenerator::serializeContexts(Info *I,
+ StringMap<OwnedPtr<Info>> &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),
@@ -936,12 +947,12 @@ static void serializeContexts(Info *I, StringMap<OwnedPtr<Info>> &Infos) {
Context GlobalRef(ParentInfo->USR, "Global Namespace",
InfoType::IT_namespace, "GlobalNamespace", "",
SmallString<16>("index"));
- I->Contexts.push_back(GlobalRef);
- return;
+ LocalContexts.push_back(GlobalRef);
+ break;
}
Context ParentRef(*ParentInfo);
- I->Contexts.push_back(ParentRef);
+ LocalContexts.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 b0253c5d71bfc..9ccb7a8ccd633 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -31,8 +31,7 @@ static std::string genEmphasis(const Twine &Text) {
return "**" + Text.str() + "**";
}
-static std::string
-genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
+static std::string genReferenceList(llvm::ArrayRef<Reference> Refs) {
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
for (const auto &R : Refs) {
@@ -82,7 +81,7 @@ class TableCommentWriter {
public:
explicit TableCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
- void write(llvm::ArrayRef<CommentInfo> Comments) {
+ void write(const OwningVec<CommentInfo> &Comments) {
for (const auto &C : Comments)
writeTableSafeComment(C);
@@ -436,7 +435,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
OS << " for " << CDCtx.ProjectName;
OS << "\n\n";
- OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
+ std::vector<const Index *> Children = CDCtx.Idx.getSortedChildren();
for (const auto *C : Children)
serializeReference(OS, *C, 0);
@@ -455,7 +454,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
FileErr.message());
CDCtx.Idx.sort();
OS << "# " << CDCtx.ProjectName << " C/C++ Reference\n\n";
- OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
+ std::vector<const Index *> 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 583a0fe43b40c..499ab5638b34e 100644
--- a/clang-tools-extra/clang-doc/Mapper.cpp
+++ b/clang-tools-extra/clang-doc/Mapper.cpp
@@ -43,6 +43,9 @@ 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 42f85c39655dd..1f01169b4c638 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -105,17 +105,6 @@ static llvm::Expected<OwnedPtr<Info>> reduce(OwningPtrArray<Info> &Values) {
return std::move(Merged);
}
-// Return the index of the matching child in the vector, or -1 if merge is not
-// necessary.
-template <typename T>
-static int getChildIndexIfExists(OwningVec<T> &Children, T &ChildToMerge) {
- for (unsigned long I = 0; I < Children.size(); I++) {
- if (ChildToMerge.USR == Children[I].USR)
- return I;
- }
- return -1;
-}
-
template <typename T>
static void reduceChildren(llvm::simple_ilist<T> &Children,
llvm::simple_ilist<T> &&ChildrenToMerge) {
@@ -133,24 +122,13 @@ static void reduceChildren(llvm::simple_ilist<T> &Children,
}
}
-template <typename T>
-static void reduceChildren(OwningVec<T> &Children,
- OwningVec<T> &&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 <typename Container>
static void mergeUnkeyed(Container &Target, Container &&Source) {
- for (auto &Item : Source) {
+ while (!Source.empty()) {
+ auto &Item = Source.front();
+ Source.pop_front();
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; }))
- Target.push_back(std::move(Item));
+ Target.push_back(Item);
}
}
@@ -484,8 +462,8 @@ bool Index::operator<(const Index &Other) const {
return Name < Other.Name;
}
-OwningVec<const Index *> Index::getSortedChildren() const {
- OwningVec<const Index *> SortedChildren;
+std::vector<const Index *> Index::getSortedChildren() const {
+ std::vector<const Index *> SortedChildren;
SortedChildren.reserve(Children.size());
for (const auto &[_, C] : Children)
SortedChildren.push_back(&C);
@@ -529,12 +507,12 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
void ScopeChildren::sort() {
Namespaces.sort();
- llvm::sort(Records);
- llvm::sort(Functions);
- llvm::sort(Enums);
- llvm::sort(Typedefs);
- llvm::sort(Concepts);
- llvm::sort(Variables);
+ Records.sort();
+ Functions.sort();
+ Enums.sort();
+ Typedefs.sort();
+ Concepts.sort();
+ Variables.sort();
}
} // namespace doc
} // namespace clang
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index ffcb60f7ab67a..f73ab751b7ba3 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -72,8 +72,8 @@ inline StringRef internString(const Twine &T) {
}
template <typename T>
-inline llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
- llvm::BumpPtrAllocator &Alloc) {
+llvm::ArrayRef<T> allocateArray(llvm::SmallVectorImpl<T> &V,
+ llvm::BumpPtrAllocator &Alloc) {
if (V.empty())
return llvm::ArrayRef<T>();
T *Allocated = (T *)Alloc.Allocate<T>(V.size());
@@ -81,9 +81,19 @@ inline llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
return llvm::ArrayRef<T>(Allocated, V.size());
}
+template <typename T>
+llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
+ llvm::BumpPtrAllocator &Alloc) {
+ if (V.empty())
+ return llvm::ArrayRef<T>();
+ T *Allocated = (T *)Alloc.Allocate<T>(V.size());
+ std::uninitialized_copy(V.begin(), V.end(), Allocated);
+ return llvm::ArrayRef<T>(Allocated, V.size());
+}
+
// An abstraction for owned pointers. Initially mapped to OwnedPtr,
// to be eventually transitioned to bare pointers in an arena.
-template <typename T> using OwnedPtr = std::unique_ptr<T>;
+template <typename T> using OwnedPtr = T *;
// An abstraction for vectors that are populated and read sequentially.
// To be eventually transitioned to llvm::ArrayRef for arena storage.
@@ -91,7 +101,7 @@ template <typename T> using OwningArray = std::vector<T>;
// An abstraction for lists that are dynamically managed (inserted/removed).
// To be eventually transitioned to llvm::simple_ilist.
-template <typename T> using OwningVec = std::vector<T>;
+template <typename T> using OwningVec = llvm::simple_ilist<T>;
// An abstraction for dynamic lists of owned pointers.
// To be eventually transitioned to llvm::simple_ilist<T*> or similar.
@@ -105,9 +115,10 @@ template <typename T> using OwningPtrArray = std::vector<OwnedPtr<T>>;
// allocation mechanism.
template <typename T, typename... Args>
OwnedPtr<T> allocatePtr(Args &&...args) {
- return std::make_unique<T>(std::forward<Args>(args)...);
+ return new (TransientArena.Allocate<T>()) T(std::forward<Args>(args)...);
}
+// An overload to explicitly allocate on an arena, returning a bare pointer.
template <typename T, typename... Args>
T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
return new (Alloc.Allocate<T>()) T(std::forward<Args>(args)...);
@@ -115,7 +126,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 <typename T> T *getPtr(const OwnedPtr<T> &O) { return O.get(); }
+template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O; }
// SHA1'd hash of a USR.
using SymbolID = std::array<uint8_t, 20>;
@@ -292,7 +303,7 @@ struct ScopeChildren {
//
// Namespaces are not syntactically valid as children of records, but making
// this general for all possible container types reduces code complexity.
- llvm::simple_ilist<Reference> Namespaces;
+ OwningVec<Reference> Namespaces;
OwningVec<Reference> Records;
OwningVec<FunctionInfo> Functions;
OwningVec<EnumInfo> Enums;
@@ -342,7 +353,7 @@ struct TemplateSpecializationInfo {
SymbolID SpecializationOf;
// Template parameters applying to the specialized record/function.
- OwningVec<TemplateParamInfo> Params;
+ llvm::ArrayRef<TemplateParamInfo> Params;
};
struct ConstraintInfo {
@@ -358,11 +369,11 @@ struct ConstraintInfo {
// or an explicit template specialization.
struct TemplateInfo {
// May be empty for non-partial specializations.
- OwningVec<TemplateParamInfo> Params;
+ llvm::ArrayRef<TemplateParamInfo> Params;
// Set when this is a specialization of another record/function.
std::optional<TemplateSpecializationInfo> Specialization;
- OwningVec<ConstraintInfo> Constraints;
+ llvm::ArrayRef<ConstraintInfo> Constraints;
};
// Info for field types.
@@ -393,9 +404,11 @@ struct MemberTypeInfo : public FieldTypeInfo {
: FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {}
bool operator==(const MemberTypeInfo &Other) const {
- return std::tie(Type, Name, Access, IsStatic, Description) ==
- std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic,
- Other.Description);
+ 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());
}
OwningVec<CommentInfo> Description;
@@ -444,7 +457,6 @@ struct Info {
Info(const Info &Other) = delete;
Info(Info &&Other) = default;
- virtual ~Info() = default;
Info &operator=(Info &&Other) = default;
@@ -471,7 +483,7 @@ struct Info {
StringRef DocumentationFileName;
// List of parent namespaces for this decl.
- llvm::SmallVector<Reference, 4> Namespace;
+ llvm::ArrayRef<Reference> Namespace;
// Unique identifier for the decl described by this Info.
SymbolID USR = SymbolID();
@@ -484,8 +496,6 @@ struct Info {
// Comment description of this decl.
OwningVec<CommentInfo> Description;
-
- SmallVector<Context, 4> Contexts;
};
inline Context::Context(const Info &I)
@@ -514,8 +524,9 @@ 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[0] != Other.Loc[0])
- return Loc[0] < Other.Loc[0];
+ if (Loc.size() > 0 && Other.Loc.size() > 0 &&
+ Loc.front() != Other.Loc.front())
+ return Loc.front() < Other.Loc.front();
if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc)
return *DefLoc < *Other.DefLoc;
@@ -524,7 +535,7 @@ struct SymbolInfo : public Info {
}
std::optional<Location> DefLoc; // Location where this decl is defined.
- llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
+ OwningVec<Location> Loc; // Locations where this decl is declared.
StringRef MangledName;
bool IsStatic = false;
};
@@ -564,7 +575,7 @@ struct FunctionInfo : public SymbolInfo, public llvm::ilist_node<FunctionInfo> {
Reference Parent;
TypeInfo ReturnType;
- llvm::SmallVector<FieldTypeInfo, 4> Params;
+ llvm::ArrayRef<FieldTypeInfo> Params;
StringRef Prototype;
// When present, this function is a template or specialization.
@@ -600,18 +611,18 @@ struct RecordInfo : public SymbolInfo {
// When present, this record is a template or specialization.
std::optional<TemplateInfo> Template;
- llvm::SmallVector<MemberTypeInfo, 4>
- Members; // List of info about record members.
- llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
- // (does not include virtual
- // parents).
- llvm::SmallVector<Reference, 4>
+ llvm::ArrayRef<MemberTypeInfo> Members; // List of info about record members.
+ llvm::ArrayRef<Reference> Parents; // List of base/parent records
+ // (does not include virtual
+ // parents).
+ llvm::ArrayRef<Reference>
VirtualParents; // List of virtual base/parent records.
- OwningVec<BaseRecordInfo> Bases; // List of base/parent records; this includes
- // inherited methods and attributes
+ llvm::ArrayRef<BaseRecordInfo>
+ Bases; // List of base/parent records; this includes
+ // inherited methods and attributes
- OwningVec<FriendInfo> Friends;
+ llvm::ArrayRef<FriendInfo> Friends;
ScopeChildren Children;
};
@@ -638,7 +649,8 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node<TypedefInfo> {
bool IsUsing = false;
};
-struct BaseRecordInfo : public RecordInfo {
+struct BaseRecordInfo : public RecordInfo,
+ public llvm::ilist_node<BaseRecordInfo> {
BaseRecordInfo();
BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,
AccessSpecifier Access, bool IsParent);
@@ -695,7 +707,7 @@ struct EnumInfo : public SymbolInfo, public llvm::ilist_node<EnumInfo> {
// this will be "short".
std::optional<TypeInfo> BaseType;
- llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members.
+ llvm::ArrayRef<EnumValueInfo> Members; // List of enum members.
};
struct ConceptInfo : public SymbolInfo, public llvm::ilist_node<ConceptInfo> {
@@ -723,7 +735,7 @@ struct Index : public Reference {
std::optional<StringRef> JumpToSection;
llvm::StringMap<Index> Children;
- OwningVec<const Index *> getSortedChildren() const;
+ std::vector<const Index *> getSortedChildren() const;
void sort();
};
@@ -773,30 +785,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<CommentInfo>);
+static_assert(std::is_trivially_destructible_v<ConceptInfo>);
static_assert(std::is_trivially_destructible_v<ConstraintInfo>);
+static_assert(std::is_trivially_destructible_v<EnumInfo>);
static_assert(std::is_trivially_destructible_v<FieldTypeInfo>);
+static_assert(std::is_trivially_destructible_v<FriendInfo>);
+static_assert(std::is_trivially_destructible_v<FunctionInfo>);
+static_assert(std::is_trivially_destructible_v<Info>);
static_assert(std::is_trivially_destructible_v<Location>);
+static_assert(std::is_trivially_destructible_v<MemberTypeInfo>);
+static_assert(std::is_trivially_destructible_v<NamespaceInfo>);
+static_assert(std::is_trivially_destructible_v<RecordInfo>);
static_assert(std::is_trivially_destructible_v<Reference>);
+static_assert(std::is_trivially_destructible_v<ScopeChildren>);
+static_assert(std::is_trivially_destructible_v<SymbolInfo>);
+static_assert(std::is_trivially_destructible_v<TemplateInfo>);
static_assert(std::is_trivially_destructible_v<TemplateParamInfo>);
+static_assert(std::is_trivially_destructible_v<TemplateSpecializationInfo>);
static_assert(std::is_trivially_destructible_v<TypeInfo>);
-
-// FIXME: These types need to be trivially destructible for arena allocation.
-static_assert(!std::is_trivially_destructible_v<ConceptInfo>);
-static_assert(!std::is_trivially_destructible_v<EnumInfo>);
-static_assert(!std::is_trivially_destructible_v<FriendInfo>);
-static_assert(!std::is_trivially_destructible_v<FunctionInfo>);
-static_assert(!std::is_trivially_destructible_v<Info>);
-static_assert(!std::is_trivially_destructible_v<MemberTypeInfo>);
-static_assert(!std::is_trivially_destructible_v<NamespaceInfo>);
-static_assert(!std::is_trivially_destructible_v<RecordInfo>);
-static_assert(!std::is_trivially_destructible_v<ScopeChildren>);
-static_assert(!std::is_trivially_destructible_v<SymbolInfo>);
-static_assert(!std::is_trivially_destructible_v<TemplateInfo>);
-static_assert(!std::is_trivially_destructible_v<TemplateSpecializationInfo>);
-static_assert(!std::is_trivially_destructible_v<TypedefInfo>);
-static_assert(!std::is_trivially_destructible_v<VarInfo>);
+static_assert(std::is_trivially_destructible_v<TypedefInfo>);
+static_assert(std::is_trivially_destructible_v<VarInfo>);
} // namespace doc
} // namespace clang
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
\ No newline at end of file
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index ef7fed6cc8501..4b2f0b5eac3a4 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(
- const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+StringRef
+Serializer::getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces) {
llvm::SmallString<128> Path;
for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
llvm::sys::path::append(Path, R->Name);
@@ -258,9 +258,7 @@ void ClangDocCommentVisitor::visitInlineCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
- StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
- std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
- CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
+ CurrentCI.Args = allocateArray(Args, TransientArena);
}
}
@@ -276,16 +274,10 @@ void ClangDocCommentVisitor::visitHTMLStartTagComment(
AttrValues.push_back(internString(Attr.Value));
}
if (!AttrKeys.empty()) {
- StringRef *KeysMem = TransientArena.Allocate<StringRef>(AttrKeys.size());
- std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
- CurrentCI.AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
+ CurrentCI.AttrKeys = allocateArray(AttrKeys, TransientArena);
}
if (!AttrValues.empty()) {
- StringRef *ValuesMem =
- TransientArena.Allocate<StringRef>(AttrValues.size());
- std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), ValuesMem);
- CurrentCI.AttrValues =
- llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
+ CurrentCI.AttrValues = allocateArray(AttrValues, TransientArena);
}
}
@@ -302,9 +294,7 @@ void ClangDocCommentVisitor::visitBlockCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
- StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
- std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
- CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
+ CurrentCI.Args = allocateArray(Args, TransientArena);
}
}
@@ -475,29 +465,35 @@ void Serializer::InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
}
void Serializer::InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
- Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
- Info.Name, getInfoRelativePath(Info.Namespace),
- Info.MangledName);
+ Reference *R = allocatePtr<Reference>(
+ Info.USR, Info.Name, InfoType::IT_record, Info.Name,
+ getInfoRelativePath(Info.Namespace), Info.MangledName);
+ Scope.Records.push_back(*R);
}
void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
- Scope.Enums.push_back(std::move(Info));
+ EnumInfo *E = allocatePtr<EnumInfo>(std::move(Info));
+ Scope.Enums.push_back(*E);
}
void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
- Scope.Functions.push_back(std::move(Info));
+ FunctionInfo *F = allocatePtr<FunctionInfo>(std::move(Info));
+ Scope.Functions.push_back(*F);
}
void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
- Scope.Typedefs.push_back(std::move(Info));
+ TypedefInfo *T = allocatePtr<TypedefInfo>(std::move(Info));
+ Scope.Typedefs.push_back(*T);
}
void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
- Scope.Concepts.push_back(std::move(Info));
+ ConceptInfo *C = allocatePtr<ConceptInfo>(std::move(Info));
+ Scope.Concepts.push_back(*C);
}
void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
- Scope.Variables.push_back(std::move(Info));
+ VarInfo *V = allocatePtr<VarInfo>(std::move(Info));
+ Scope.Variables.push_back(*V);
}
// Creates a parent of the correct type for the given child and inserts it into
@@ -581,14 +577,18 @@ 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<MemberTypeInfo, 4> Members;
for (const FieldDecl *F : D->fields()) {
if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
continue;
- populateMemberTypeInfo(I, Access, F);
+ populateMemberTypeInfo(Members, Access, F);
}
const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
- if (!CxxRD)
+ if (!CxxRD) {
+ if (!Members.empty())
+ I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
return;
+ }
for (Decl *CxxDecl : CxxRD->decls()) {
auto *VD = dyn_cast<VarDecl>(CxxDecl);
if (!VD ||
@@ -596,40 +596,49 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
continue;
if (VD->isStaticDataMember())
- populateMemberTypeInfo(I, Access, VD, /*IsStatic=*/true);
+ populateMemberTypeInfo(Members, Access, VD, /*IsStatic=*/true);
}
+ if (!Members.empty())
+ I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
}
void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) {
+ llvm::SmallVector<EnumValueInfo, 4> 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);
- I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
+ EnumValueInfo &Member = LocalMembers.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)) {
- EnumValueInfo &Member = I.Members.back();
- Member.Description.emplace_back();
+ CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ Member.Description.push_back(*NewCI);
parseFullComment(Fc, Member.Description.back());
}
}
}
+ if (!LocalMembers.empty())
+ I.Members = allocateArray<EnumValueInfo>(LocalMembers, TransientArena);
}
void Serializer::parseParameters(FunctionInfo &I, const FunctionDecl *D) {
+ llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
auto &LO = D->getLangOpts();
for (const ParmVarDecl *P : D->parameters()) {
- FieldTypeInfo &FieldInfo = I.Params.emplace_back(
+ FieldTypeInfo &FieldInfo = LocalParams.emplace_back(
getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString());
if (std::optional<StringRef> DefaultValue =
getSourceCode(D, P->getDefaultArgRange()))
FieldInfo.DefaultValue = *DefaultValue;
}
+ if (!LocalParams.empty())
+ I.Params = allocateArray<FieldTypeInfo>(LocalParams, TransientArena);
}
// TODO: Remove the serialization of Parents and VirtualParents, this
@@ -639,28 +648,36 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D) {
if (!D->isThisDeclarationADefinition())
return;
+ llvm::SmallVector<Reference, 4> LocalParents;
for (const CXXBaseSpecifier &B : D->bases()) {
if (B.isVirtual())
continue;
if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
- I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
- InfoType::IT_record, B.getType().getAsString());
+ LocalParents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
+ InfoType::IT_record, B.getType().getAsString());
} else if (const RecordDecl *P = getRecordDeclForType(B.getType()))
- I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
- InfoType::IT_record, P->getQualifiedNameAsString(),
- internString(getInfoRelativePath(P)));
+ LocalParents.emplace_back(
+ getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
+ P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
else
- I.Parents.emplace_back(SymbolID(), B.getType().getAsString());
+ LocalParents.emplace_back(SymbolID(), B.getType().getAsString());
}
+ if (!LocalParents.empty())
+ I.Parents = allocateArray<Reference>(LocalParents, TransientArena);
+
+ llvm::SmallVector<Reference, 4> LocalVirtualParents;
for (const CXXBaseSpecifier &B : D->vbases()) {
if (const RecordDecl *P = getRecordDeclForType(B.getType()))
- I.VirtualParents.emplace_back(
+ LocalVirtualParents.emplace_back(
getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
else
- I.VirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
+ LocalVirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
}
+ if (!LocalVirtualParents.empty())
+ I.VirtualParents =
+ allocateArray<Reference>(LocalVirtualParents, TransientArena);
}
template <typename T>
@@ -708,10 +725,13 @@ void Serializer::populateTemplateParameters(
if (!TemplateInfo) {
TemplateInfo.emplace();
}
+ llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const NamedDecl *ND : *ParamList) {
- TemplateInfo->Params.emplace_back(
- getSourceCode(ND, ND->getSourceRange()));
+ LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange()));
}
+ if (!LocalParams.empty())
+ TemplateInfo->Params =
+ allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
@@ -774,9 +794,14 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C,
ConversionDecl->getConversionType().getAsString());
else
I.Name = internString(D->getNameAsString());
- populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
+ llvm::SmallVector<Reference, 4> LocalNamespaces;
+ populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
+ if (!LocalNamespaces.empty())
+ I.Namespace = allocateArray<Reference>(LocalNamespaces, TransientArena);
if (C) {
- I.Description.emplace_back();
+
+ CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ I.Description.push_back(*NewCI);
parseFullComment(C, I.Description.back());
}
}
@@ -788,8 +813,10 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
populateInfo(I, D, C, IsInAnonymousNamespace);
if (D->isThisDeclarationADefinition())
I.DefLoc = Loc;
- else
- I.Loc.emplace_back(Loc);
+ else {
+ Location *NewL = allocatePtr<Location>(Loc);
+ I.Loc.push_back(*NewL);
+ }
auto *Mangler = ItaniumMangleContext::create(
D->getASTContext(), D->getASTContext().getDiagnostics());
@@ -811,7 +838,8 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
}
void Serializer::handleCompoundConstraints(
- const Expr *Constraint, OwningVec<ConstraintInfo> &ConstraintInfos) {
+ const Expr *Constraint,
+ llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
ConstraintInfos);
@@ -835,6 +863,7 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
SmallVector<AssociatedConstraint> AssociatedConstraints;
D->getAssociatedConstraints(AssociatedConstraints);
+ SmallVector<ConstraintInfo, 4> LocalConstraints;
for (const auto &Constraint : AssociatedConstraints) {
if (!Constraint)
continue;
@@ -846,11 +875,14 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
ConstraintExpr->getNamedConcept()->getNameAsString());
CI.ConstraintExpr = internString(exprToString(ConstraintExpr));
- I.Constraints.push_back(std::move(CI));
+ LocalConstraints.push_back(std::move(CI));
} else {
- handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
+ handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
}
}
+ if (!LocalConstraints.empty())
+ I.Constraints =
+ allocateArray<ConstraintInfo>(LocalConstraints, TransientArena);
}
void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
@@ -879,9 +911,13 @@ void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
// Template parameters to the specialization.
if (FTSI->TemplateArguments) {
+ SmallVector<TemplateParamInfo, 4> LocalParams;
for (const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
- Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
+ LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
}
+ if (!LocalParams.empty())
+ Specialization.Params =
+ allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
}
@@ -901,26 +937,28 @@ void Serializer::populateMemberTypeInfo(T &I, const Decl *D) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
- I.Description.emplace_back();
+ CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ I.Description.push_back(*NewCI);
parseFullComment(Fc, I.Description.back());
}
}
-void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
- const DeclaratorDecl *D,
- bool IsStatic) {
+void Serializer::populateMemberTypeInfo(
+ SmallVectorImpl<MemberTypeInfo> &Members, 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 = I.Members.emplace_back(
+ MemberTypeInfo &NewMember = Members.emplace_back(
getTypeInfoForType(D->getTypeSourceInfo()->getType(), D->getLangOpts()),
D->getNameAsString(),
getFinalAccessSpecifier(Access, D->getAccessUnsafe()), IsStatic);
populateMemberTypeInfo(NewMember, D);
}
-void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D,
- bool IsFileInRootDir, bool PublicOnly,
- bool IsParent, AccessSpecifier ParentAccess) {
+void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
+ 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;
@@ -959,14 +997,15 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D,
IsInAnonymousNamespace);
FI.Access =
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
- BI.Children.Functions.emplace_back(std::move(FI));
+ FunctionInfo *FIPtr = allocatePtr<FunctionInfo>(std::move(FI));
+ BI.Children.Functions.push_back(*FIPtr);
}
- I.Bases.emplace_back(std::move(BI));
+ 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(I, Base, IsFileInRootDir, PublicOnly, false,
- I.Bases.back().Access);
+ parseBases(Bases, Base, IsFileInRootDir, PublicOnly, false,
+ Bases.back().Access);
}
}
}
@@ -995,6 +1034,8 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
if (!D->hasDefinition() || !D->hasFriends())
return;
+ llvm::SmallVector<FriendInfo, 4> LocalFriends;
+
for (const FriendDecl *FD : D->friends()) {
if (FD->isUnsupportedFriend())
continue;
@@ -1016,9 +1057,12 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
F.IsClass = true;
F.Template.emplace();
+ llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const auto *Param : ActualTD->getTemplateParameters()->asArray())
- F.Template->Params.emplace_back(
- getSourceCode(Param, Param->getSourceRange()));
+ LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
+ if (!LocalParams.empty())
+ F.Template->Params =
+ allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
ActualDecl = ActualTD->getTemplatedDecl();
}
@@ -1036,8 +1080,10 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
getInfoRelativePath(ActualDecl));
populateMemberTypeInfo(F, ActualDecl);
- RI.Friends.push_back(std::move(F));
+ LocalFriends.push_back(std::move(F));
}
+ if (!LocalFriends.empty())
+ RI.Friends = allocateArray<FriendInfo>(LocalFriends, TransientArena);
}
std::pair<OwnedPtr<Info>, OwnedPtr<Info>>
@@ -1061,7 +1107,11 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
}
// TODO: remove first call to parseBases, that function should be deleted
parseBases(*RI, C);
- parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true);
+ llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
+ parseBases(LocalBases, C, /*IsFileInRootDir=*/true, PublicOnly,
+ /*IsParent=*/true);
+ if (!LocalBases.empty())
+ RI->Bases = allocateArray<BaseRecordInfo>(LocalBases, TransientArena);
parseFriends(*RI, C);
}
RI->Path = internString(getInfoRelativePath(RI->Namespace));
@@ -1094,15 +1144,23 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
if (const ASTTemplateArgumentListInfo *AsWritten =
CTPSD->getTemplateArgsAsWritten()) {
+ llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
- Specialization.Params.emplace_back(
+ LocalParams.emplace_back(
getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
}
+ if (!LocalParams.empty())
+ Specialization.Params =
+ allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
} else {
+ llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
- Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
+ LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
}
+ if (!LocalParams.empty())
+ Specialization.Params =
+ allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
@@ -1164,8 +1222,9 @@ void Serializer::extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
- Info.Description.emplace_back();
- parseFullComment(Fc, Info.Description.back());
+ CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ Info.Description.push_back(*NewCI);
+ parseFullComment(Fc, *NewCI);
}
}
@@ -1258,10 +1317,13 @@ Serializer::emitInfo(const ConceptDecl *D, const FullComment *FC,
Concept.ConstraintExpression = exprToString(D->getConstraintExpr());
if (auto *ConceptParams = D->getTemplateParameters()) {
+ llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const auto *Param : ConceptParams->asArray()) {
- Concept.Template.Params.emplace_back(
- getSourceCode(Param, Param->getSourceRange()));
+ LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
}
+ if (!LocalParams.empty())
+ Concept.Template.Params =
+ allocateArray<TemplateParamInfo>(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 04891bea33220..3d53514d0756a 100644
--- a/clang-tools-extra/clang-doc/Serialize.h
+++ b/clang-tools-extra/clang-doc/Serialize.h
@@ -94,8 +94,7 @@ class Serializer {
StringRef getTypeAlias(const TypeAliasDecl *Alias);
- StringRef
- getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces);
+ StringRef getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces);
StringRef getInfoRelativePath(const Decl *D);
@@ -139,8 +138,9 @@ class Serializer {
void parseBases(RecordInfo &I, const CXXRecordDecl *D);
- void parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
- bool PublicOnly, bool IsParent,
+ void parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
+ const CXXRecordDecl *D, bool IsFileInRootDir, bool PublicOnly,
+ bool IsParent,
AccessSpecifier ParentAccess = AccessSpecifier::AS_public);
template <typename T>
@@ -165,8 +165,9 @@ class Serializer {
void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
Location Loc, bool &IsInAnonymousNamespace);
- void handleCompoundConstraints(const Expr *Constraint,
- OwningVec<ConstraintInfo> &ConstraintInfos);
+ void handleCompoundConstraints(
+ const Expr *Constraint,
+ llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos);
void populateConstraints(TemplateInfo &I, const TemplateDecl *D);
@@ -176,8 +177,9 @@ class Serializer {
template <typename T> void populateMemberTypeInfo(T &I, const Decl *D);
- void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
- const DeclaratorDecl *D, bool IsStatic = false);
+ void populateMemberTypeInfo(llvm::SmallVectorImpl<MemberTypeInfo> &Members,
+ 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 9e3bca84877e0..b5c43837f9505 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -31,9 +31,70 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(OwnedPtr<CommentInfo>)
namespace llvm {
+
+template <typename T>
+bool operator==(const llvm::simple_ilist<T> &LHS,
+ const llvm::simple_ilist<T> &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 <typename T>
+bool operator!=(const llvm::simple_ilist<T> &LHS,
+ const llvm::simple_ilist<T> &RHS) {
+ return !(LHS == RHS);
+}
+
namespace yaml {
-template <typename T> struct SequenceTraits<llvm::ArrayRef<T>> {
+// Provide SequenceTraits for ArrayRef<T*> since YAMLTraits only provides it for
+// MutableArrayRef
+template <typename T> struct SequenceTraits<ArrayRef<T *>> {
+ static size_t size(IO &io, ArrayRef<T *> &seq) { return seq.size(); }
+ static T *&element(IO &io, ArrayRef<T *> &seq, size_t index) {
+ // ArrayRef is not mutable, but YAML output only reads the value.
+ return const_cast<T *&>(seq[index]);
+ }
+};
+
+template <typename T> struct SequenceTraits<llvm::simple_ilist<T>> {
+ static size_t size(IO &io, llvm::simple_ilist<T> &seq) { return seq.size(); }
+ static T &element(IO &io, llvm::simple_ilist<T> &seq, size_t index) {
+ return *std::next(seq.begin(), index);
+ }
+};
+
+// Map pointers to the value mappings as clang-doc only does output
+// serialization.
+template <typename T> struct PointerMappingTraits {
+ static void mapping(IO &IO, T *&Val) {
+ if (Val)
+ MappingTraits<T>::mapping(IO, *Val);
+ }
+};
+
+template <>
+struct MappingTraits<clang::doc::Reference *>
+ : PointerMappingTraits<clang::doc::Reference> {};
+template <>
+struct MappingTraits<clang::doc::CommentInfo *>
+ : PointerMappingTraits<clang::doc::CommentInfo> {};
+template <>
+struct MappingTraits<clang::doc::FunctionInfo *>
+ : PointerMappingTraits<clang::doc::FunctionInfo> {};
+template <>
+struct MappingTraits<clang::doc::EnumInfo *>
+ : PointerMappingTraits<clang::doc::EnumInfo> {};
+template <>
+struct MappingTraits<clang::doc::TemplateParamInfo *>
+ : PointerMappingTraits<clang::doc::TemplateParamInfo> {};
+
+template <typename T> struct SequenceTraits<ArrayRef<T>> {
static size_t size(IO &io, llvm::ArrayRef<T> &seq) { return seq.size(); }
static T &element(IO &io, llvm::ArrayRef<T> &seq, size_t index) {
return const_cast<T &>(seq[index]);
@@ -191,7 +252,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<Location>());
- IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
+ IO.mapOptional("Location", I.Loc);
}
static void recordInfoMapping(IO &IO, RecordInfo &I) {
@@ -200,10 +261,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, llvm::SmallVector<Reference, 4>());
+ IO.mapOptional("Parents", I.Parents, SmallVector<Reference, 4>());
IO.mapOptional("VirtualParents", I.VirtualParents,
llvm::SmallVector<Reference, 4>());
- IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
+ IO.mapOptional("ChildRecords", I.Children.Records);
IO.mapOptional("ChildFunctions", I.Children.Functions);
IO.mapOptional("ChildEnums", I.Children.Enums);
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
@@ -339,7 +400,7 @@ template <> struct MappingTraits<NamespaceInfo> {
for (const auto &N : I.Children.Namespaces)
TempNamespaces.push_back(N);
IO.mapOptional("ChildNamespaces", TempNamespaces, std::vector<Reference>());
- IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
+ IO.mapOptional("ChildRecords", I.Children.Records);
IO.mapOptional("ChildFunctions", I.Children.Functions);
IO.mapOptional("ChildEnums", I.Children.Enums);
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
@@ -441,13 +502,6 @@ template <> struct MappingTraits<CommentInfo> {
static void mapping(IO &IO, CommentInfo &I) { commentInfoMapping(IO, I); }
};
-template <> struct MappingTraits<OwnedPtr<CommentInfo>> {
- static void mapping(IO &IO, OwnedPtr<CommentInfo> &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 f96cfc9426f1a..c610c57722649 100644
--- a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
+++ b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
@@ -184,9 +184,10 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
auto NI = allocatePtr<NamespaceInfo>();
NI->Name = "GlobalNamespace";
for (int i = 0; i < NumRecords; ++i) {
- NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)},
- "Record" + std::to_string(i),
- InfoType::IT_record);
+ Reference *R = new (TransientArena.Allocate<Reference>())
+ Reference(SymbolID{(uint8_t)(i & 0xFF)}, "Record" + std::to_string(i),
+ InfoType::IT_record);
+ NI->Children.Records.push_back(*R);
}
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
index 6bdf538012303..81de4ff2f6381 100644
--- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -56,7 +56,6 @@ static OwningPtrVec<Info> 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);
@@ -68,39 +67,43 @@ class BitcodeTest : public ClangDocContextTest {};
TEST_F(BitcodeTest, emitNamespaceInfoBitcode) {
NamespaceInfo I;
I.Name = "r";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
I.Children.Namespaces.push_back(NewNamespace);
- I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
- I.Children.Functions.emplace_back();
- I.Children.Enums.emplace_back();
+ 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);
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get()));
+ CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0]));
}
TEST_F(BitcodeTest, emitRecordInfoBitcode) {
RecordInfo I;
I.Name = "r";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
+ MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.TagType = TagTypeKind::Class;
I.IsTypeDef = true;
- 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);
+ 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);
// Documentation for the data member.
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
@@ -109,29 +112,47 @@ TEST_F(BitcodeTest, emitRecordInfoBitcode) {
CommentInfo TopCommentChildren[] = {
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
- I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment));
-
- I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
- I.Children.Functions.emplace_back();
- I.Children.Enums.emplace_back();
+ 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);
+
+ 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);
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get()));
+ CheckRecordInfo(&I, InfoAsRecord(ReadResults[0]));
}
TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
FunctionInfo I;
I.Name = "f";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
I.ReturnType = TypeInfo("void");
- I.Params.emplace_back(TypeInfo("int"), "P");
+ FieldTypeInfo P(TypeInfo("int"), "P");
+ FieldTypeInfo Params[] = {std::move(P)};
+ I.Params = llvm::ArrayRef(Params);
I.Access = AccessSpecifier::AS_none;
@@ -139,19 +160,23 @@ TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
+ CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
}
TEST_F(BitcodeTest, emitMethodInfoBitcode) {
FunctionInfo I;
I.Name = "f";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
I.ReturnType = TypeInfo("void");
- I.Params.emplace_back(TypeInfo("int"), "P");
+ FieldTypeInfo P(TypeInfo("int"), "P");
+ FieldTypeInfo Params[] = {std::move(P)};
+ I.Params = llvm::ArrayRef(Params);
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -161,31 +186,36 @@ TEST_F(BitcodeTest, emitMethodInfoBitcode) {
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
+ CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
}
TEST_F(BitcodeTest, emitEnumInfoBitcode) {
EnumInfo I;
I.Name = "e";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back("X");
+ EnumValueInfo EV("X");
+ EnumValueInfo Mems[] = {std::move(EV)};
+ I.Members = llvm::ArrayRef(Mems);
I.Scoped = true;
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get()));
+ CheckEnumInfo(&I, InfoAsEnum(ReadResults[0]));
}
TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
TypedefInfo I;
I.Name = "MyInt";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
I.Underlying = TypeInfo("unsigned");
@@ -196,13 +226,13 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
- I.Description.emplace_back(std::move(Top));
+ I.Description.push_back(Top);
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0].get()));
+ CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0]));
// Check one with no IsUsing set, no description, and no definition location.
TypedefInfo I2;
@@ -213,7 +243,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].get()));
+ CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0]));
}
TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
@@ -221,7 +251,8 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
F.Name = "F";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
- F.Params.emplace_back(TypeInfo("int"), "I");
+ FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I")};
+ F.Params = llvm::ArrayRef(PI);
// BlankLine
CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
@@ -293,13 +324,13 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
Verbatim, ParamOut, ParamIn, Return};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
- F.Description.emplace_back(std::move(Top));
+ F.Description.push_back(Top);
std::string WriteResult = writeInfo(&F, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
- CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get()));
+ CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0]));
}
} // namespace doc
diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
index 92127da53b7bb..2e5466c172a18 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<TypedefInfo *>(I);
}
-void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
- const std::vector<CommentInfo> &Actual);
-void CheckCommentInfo(const std::vector<OwnedPtr<CommentInfo>> &Expected,
- const std::vector<OwnedPtr<CommentInfo>> &Actual);
+void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
+ ArrayRef<CommentInfo> Actual);
+void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
+ const OwningVec<CommentInfo> &Actual);
void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
EXPECT_EQ(Expected.Kind, Actual.Kind);
@@ -84,52 +84,71 @@ void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
CheckCommentInfo(Expected.Children, Actual.Children);
}
-void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
- const std::vector<CommentInfo> &Actual) {
- ASSERT_EQ(Expected.size(), Actual.size());
- for (size_t Idx = 0; Idx < Actual.size(); ++Idx)
- CheckCommentInfo(Expected[Idx], Actual[Idx]);
+void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
+ ArrayRef<CommentInfo> 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<OwnedPtr<CommentInfo>> &Expected,
- const std::vector<OwnedPtr<CommentInfo>> &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<CommentInfo> &Expected,
+ const OwningVec<CommentInfo> &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 CheckReference(Reference &Expected, Reference &Actual) {
+void CheckReference(const Reference &Expected, const Reference &Actual) {
EXPECT_EQ(Expected.Name, Actual.Name);
EXPECT_EQ(Expected.RefType, Actual.RefType);
EXPECT_EQ(Expected.Path, Actual.Path);
}
-void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) {
+void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual) {
CheckReference(Expected->Type, Actual->Type);
}
-void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) {
+void CheckFieldTypeInfo(const FieldTypeInfo *Expected,
+ const FieldTypeInfo *Actual) {
CheckTypeInfo(Expected, Actual);
EXPECT_EQ(Expected->Name, Actual->Name);
}
-void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
+void CheckMemberTypeInfo(const MemberTypeInfo *Expected,
+ const MemberTypeInfo *Actual) {
CheckFieldTypeInfo(Expected, Actual);
EXPECT_EQ(Expected->Access, Actual->Access);
CheckCommentInfo(Expected->Description, Actual->Description);
}
-void CheckBaseInfo(Info *Expected, Info *Actual) {
+void CheckBaseInfo(const Info *Expected, const Info *Actual) {
EXPECT_EQ(size_t(20), Actual->USR.size());
EXPECT_EQ(Expected->Name, Actual->Name);
EXPECT_EQ(Expected->Path, Actual->Path);
- 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]);
+ 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());
CheckCommentInfo(Expected->Description, Actual->Description);
}
-void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
+void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) {
CheckBaseInfo(Expected, Actual);
EXPECT_EQ(Expected->DefLoc.has_value(), Actual->DefLoc.has_value());
if (Expected->DefLoc && Actual->DefLoc.has_value()) {
@@ -138,109 +157,186 @@ void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
EXPECT_EQ(Expected->DefLoc->EndLineNumber, Actual->DefLoc->EndLineNumber);
EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename);
}
- 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]);
+ 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());
}
-void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual) {
+void CheckFunctionInfo(const FunctionInfo *Expected,
+ const FunctionInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->IsMethod, Actual->IsMethod);
CheckReference(Expected->Parent, Actual->Parent);
CheckTypeInfo(&Expected->ReturnType, &Actual->ReturnType);
- ASSERT_EQ(Expected->Params.size(), Actual->Params.size());
- for (size_t Idx = 0; Idx < Actual->Params.size(); ++Idx)
+ for (size_t Idx = 0; Idx < Expected->Params.size(); ++Idx) {
EXPECT_EQ(Expected->Params[Idx], Actual->Params[Idx]);
+ }
EXPECT_EQ(Expected->Access, Actual->Access);
}
-void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual) {
+void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->Scoped, Actual->Scoped);
- 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 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());
}
-void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual) {
+void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->IsUsing, Actual->IsUsing);
CheckTypeInfo(&Expected->Underlying, &Actual->Underlying);
}
-void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual) {
+void CheckNamespaceInfo(const NamespaceInfo *Expected,
+ const NamespaceInfo *Actual) {
CheckBaseInfo(Expected, Actual);
ASSERT_EQ(Expected->Children.Namespaces.size(),
Actual->Children.Namespaces.size());
- auto ItExpected = Expected->Children.Namespaces.begin();
- auto ItActual = Actual->Children.Namespaces.begin();
- while (ItExpected != Expected->Children.Namespaces.end()) {
- CheckReference(*ItExpected, *ItActual);
- ++ItExpected;
- ++ItActual;
+ 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;
}
-
- 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]);
-
- 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]);
-
- 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]);
+ 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());
+
+ 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());
+
+ 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());
}
-void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual) {
+void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->TagType, Actual->TagType);
EXPECT_EQ(Expected->IsTypeDef, Actual->IsTypeDef);
- 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]);
-
- 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]);
-
- 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]);
-
- 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]);
-
- 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]);
-
- 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]);
-
- 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]);
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
+
+ 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());
}
-void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual) {
+void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
+ const BaseRecordInfo *Actual) {
CheckRecordInfo(Expected, Actual);
EXPECT_EQ(Expected->IsVirtual, Actual->IsVirtual);
@@ -248,7 +344,7 @@ void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual) {
EXPECT_EQ(Expected->IsParent, Actual->IsParent);
}
-void CheckIndex(Index &Expected, Index &Actual) {
+void CheckIndex(const Index &Expected, const 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 9b1a26af0cdf6..1525b1ed382ce 100644
--- a/clang-tools-extra/unittests/clang-doc/ClangDocTest.h
+++ b/clang-tools-extra/unittests/clang-doc/ClangDocTest.h
@@ -31,25 +31,32 @@ FunctionInfo *InfoAsFunction(Info *I);
EnumInfo *InfoAsEnum(Info *I);
TypedefInfo *InfoAsTypedef(Info *I);
-// 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);
+void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
+ ArrayRef<CommentInfo> Actual);
+void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
+ const OwningVec<CommentInfo> &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);
// This function explicitly does not check USRs, as that may change and it would
// be better to not rely on its implementation.
-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 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 CheckIndex(Index &Expected, Index &Actual);
+void CheckIndex(const Index &Expected, const 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 38f37bd535239..e352abbe0801f 100644
--- a/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/GeneratorTest.cpp
@@ -28,7 +28,8 @@ TEST_F(GeneratorTest, emitIndex) {
InfoC->USR = serialize::hashUSR("3");
Reference RefB = Reference(SymbolID(), "B");
RefB.USR = serialize::hashUSR("2");
- InfoC->Namespace = {std::move(RefB)};
+ Reference NsC[] = {std::move(RefB)};
+ InfoC->Namespace = llvm::ArrayRef(NsC);
Generator::addInfoToIndex(Idx, InfoC.get());
auto InfoD = std::make_unique<Info>();
InfoD->Name = "D";
@@ -40,7 +41,8 @@ TEST_F(GeneratorTest, emitIndex) {
RefD.USR = serialize::hashUSR("4");
Reference RefE = Reference(SymbolID(), "E");
RefE.USR = serialize::hashUSR("5");
- InfoF->Namespace = {std::move(RefE), std::move(RefD)};
+ Reference NsF[] = {std::move(RefE), std::move(RefD)};
+ InfoF->Namespace = llvm::ArrayRef(NsF);
Generator::addInfoToIndex(Idx, InfoF.get());
auto InfoG = std::make_unique<Info>(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 6edd303dbc326..509699f20aa09 100644
--- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
@@ -19,39 +19,54 @@ TEST_F(JSONGeneratorTest, emitRecordJSON) {
RecordInfo I;
I.Name = "Foo";
I.IsTypeDef = false;
- I.Namespace.emplace_back(EmptySID, "GlobalNamespace", InfoType::IT_namespace);
+ Reference Ns[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.Path = "GlobalNamespace";
I.DefLoc = Location(1, 1, "main.cpp");
I.TagType = TagTypeKind::Class;
I.Template = TemplateInfo();
- I.Template->Params.emplace_back("class T");
+ TemplateParamInfo TParams[] = {TemplateParamInfo("class T")};
+ I.Template->Params = llvm::ArrayRef(TParams);
- 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";
+ 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.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_protected);
+ MemberTypeInfo M[] = {
+ MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_protected)};
+ I.Members = llvm::ArrayRef(M);
- 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);
+ 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);
// F is in the global namespace
- 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 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);
+
+ Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
+ "path::to::A::r::ChildStruct", "path/to/A/r");
+ I.Children.Records.push_back(ChildStruct);
- 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";
+ FunctionInfo F2;
+ F2.Name = "OneFunction";
+ I.Children.Functions.push_back(F2);
auto G = getJSONGenerator();
assert(G);
@@ -197,20 +212,26 @@ TEST_F(JSONGeneratorTest, emitNamespaceJSON) {
NamespaceInfo I;
I.Name = "Namespace";
I.Path = "path/to/A";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
"path::to::A::Namespace::ChildNamespace",
"path/to/A/Namespace");
I.Children.Namespaces.push_back(NewNamespace);
- 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";
+
+ 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);
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 6661360049881..2dc472a352fd8 100644
--- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
@@ -26,16 +26,22 @@ class MDGeneratorTest : public ClangDocContextTest {};
TEST_F(MDGeneratorTest, emitNamespaceMD) {
NamespaceInfo I;
I.Name = "Namespace";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
I.Children.Namespaces.push_back(NewNamespace);
- 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";
+ 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);
auto G = getMDGenerator();
assert(G);
@@ -79,21 +85,31 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) {
TEST_F(MDGeneratorTest, emitRecordMD) {
RecordInfo I;
I.Name = "r";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
+ MemberTypeInfo M[] = {
+ MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
+ I.Members = llvm::ArrayRef(M);
I.TagType = TagTypeKind::Class;
- I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
- I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
+ 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 F;
+ F.Name = "OneFunction";
+ I.Children.Functions.push_back(F);
- 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";
+ EnumInfo E;
+ E.Name = "OneEnum";
+ I.Children.Enums.push_back(E);
auto G = getMDGenerator();
assert(G);
@@ -143,15 +159,18 @@ ChildStruct
TEST_F(MDGeneratorTest, emitFunctionMD) {
FunctionInfo I;
I.Name = "f";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
I.Access = AccessSpecifier::AS_none;
I.ReturnType = TypeInfo("void");
- I.Params.emplace_back(TypeInfo("int"), "P");
+ FieldTypeInfo P[] = {FieldTypeInfo(TypeInfo("int"), "P")};
+ I.Params = llvm::ArrayRef(P);
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -175,12 +194,15 @@ TEST_F(MDGeneratorTest, emitFunctionMD) {
TEST_F(MDGeneratorTest, emitEnumMD) {
EnumInfo I;
I.Name = "e";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back("X");
+ EnumValueInfo EV[] = {EnumValueInfo("X")};
+ I.Members = llvm::ArrayRef(EV);
I.Scoped = true;
auto G = getMDGenerator();
@@ -208,8 +230,9 @@ TEST_F(MDGeneratorTest, emitCommentMD) {
I.DefLoc = Location(10, 10, "test.cpp");
I.ReturnType = TypeInfo("void");
- I.Params.emplace_back(TypeInfo("int"), "I");
- I.Params.emplace_back(TypeInfo("int"), "J");
+ FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I"),
+ FieldTypeInfo(TypeInfo("int"), "J")};
+ I.Params = llvm::ArrayRef(PI);
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 15b791a044d2d..50374743681e3 100644
--- a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp
@@ -18,150 +18,200 @@ class MergeTest : public ClangDocContextTest {};
TEST_F(MergeTest, mergeNamespaceInfos) {
NamespaceInfo One;
One.Name = "Namespace";
- One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ One.Namespace = llvm::ArrayRef(Ns1);
Reference RA(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
One.Children.Namespaces.push_back(RA);
- 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;
+ 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);
NamespaceInfo Two;
Two.Name = "Namespace";
- Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Two.Namespace = llvm::ArrayRef(Ns2);
Reference RB(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
Two.Children.Namespaces.push_back(RB);
- 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";
+ 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);
OwningPtrVec<Info> Infos;
- Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(One)));
- Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(Two)));
+ Infos.push_back(&One);
+ Infos.push_back(&Two);
- auto Expected = allocatePtr<NamespaceInfo>();
- Expected->Name = "Namespace";
- Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ NamespaceInfo Expected;
+ Expected.Name = "Namespace";
+ Reference NsExpected[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Expected.Namespace = llvm::ArrayRef(NsExpected);
Reference RC(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
- Expected->Children.Namespaces.push_back(RC);
- Expected->Children.Records.emplace_back(NonEmptySID, "ChildStruct",
- InfoType::IT_record);
+ Expected.Children.Namespaces.push_back(RC);
+ Reference RCE1(NonEmptySID, "ChildStruct", InfoType::IT_record);
+ Expected.Children.Records.push_back(RCE1);
Reference RD(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
- 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";
+ 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);
auto Actual = mergeInfos(Infos);
assert(Actual);
- CheckNamespaceInfo(InfoAsNamespace(Expected.get()),
- InfoAsNamespace(Actual.get().get()));
+ CheckNamespaceInfo(InfoAsNamespace(&Expected), InfoAsNamespace(Actual.get()));
}
TEST_F(MergeTest, mergeRecordInfos) {
RecordInfo One;
One.Name = "r";
One.IsTypeDef = true;
- One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ One.Namespace = llvm::ArrayRef(Ns1);
One.DefLoc = Location(10, 10, "test.cpp");
- One.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
+ MemberTypeInfo M1[] = {
+ MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
+ One.Members = llvm::ArrayRef(M1);
One.TagType = TagTypeKind::Class;
- One.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
- One.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
-
- 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;
+ 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);
+
+ 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);
RecordInfo Two;
Two.Name = "r";
- Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Two.Namespace = llvm::ArrayRef(Ns2);
- Two.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc2(12, 12, "test.cpp");
+ Two.Loc.push_back(Loc2);
Two.TagType = TagTypeKind::Class;
- 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";
+ 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);
OwningPtrVec<Info> Infos;
- Infos.emplace_back(allocatePtr<RecordInfo>(std::move(One)));
- Infos.emplace_back(allocatePtr<RecordInfo>(std::move(Two)));
-
- auto Expected = allocatePtr<RecordInfo>();
- Expected->Name = "r";
- Expected->IsTypeDef = true;
- Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
-
- Expected->DefLoc = Location(10, 10, "test.cpp");
- Expected->Loc.emplace_back(12, 12, "test.cpp");
-
- 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);
-
- 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";
+ Infos.push_back(&One);
+ Infos.push_back(&Two);
+
+ RecordInfo Expected;
+ Expected.Name = "r";
+ Expected.IsTypeDef = true;
+ Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Expected.Namespace = llvm::ArrayRef(NsE);
+
+ Expected.DefLoc = Location(10, 10, "test.cpp");
+ Location LocE(12, 12, "test.cpp");
+ Expected.Loc.push_back(LocE);
+
+ 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);
+
+ 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);
auto Actual = mergeInfos(Infos);
assert(Actual);
- CheckRecordInfo(InfoAsRecord(Expected.get()),
- InfoAsRecord(Actual.get().get()));
+ CheckRecordInfo(InfoAsRecord(&Expected), InfoAsRecord(Actual.get()));
}
TEST_F(MergeTest, mergeFunctionInfos) {
FunctionInfo One;
One.Name = "f";
- One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ One.Namespace = llvm::ArrayRef(Ns1);
One.DefLoc = Location(10, 10, "test.cpp");
- One.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ One.Loc.push_back(Loc1);
One.IsMethod = true;
One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
@@ -170,89 +220,106 @@ TEST_F(MergeTest, mergeFunctionInfos) {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo OnePara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, OneText)};
- One.Description.emplace_back(CommentKind::CK_FullComment, OnePara);
+ CommentInfo TopOne(CommentKind::CK_FullComment, OnePara);
+ One.Description.push_back(TopOne);
FunctionInfo Two;
Two.Name = "f";
- Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Two.Namespace = llvm::ArrayRef(Ns2);
- Two.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc2(12, 12, "test.cpp");
+ Two.Loc.push_back(Loc2);
Two.ReturnType = TypeInfo("void");
- Two.Params.emplace_back(TypeInfo("int"), "P");
+ FieldTypeInfo P2(TypeInfo("int"), "P");
+ FieldTypeInfo Params2[] = {std::move(P2)};
+ Two.Params = llvm::ArrayRef(Params2);
CommentInfo TwoText[] = {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo TwoPara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, TwoText)};
- Two.Description.emplace_back(CommentKind::CK_FullComment, TwoPara);
+ CommentInfo TopTwo(CommentKind::CK_FullComment, TwoPara);
+ Two.Description.push_back(TopTwo);
OwningPtrVec<Info> Infos;
- Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(One)));
- Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(Two)));
+ Infos.push_back(&One);
+ Infos.push_back(&Two);
- auto Expected = allocatePtr<FunctionInfo>();
- Expected->Name = "f";
- Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ FunctionInfo Expected;
+ Expected.Name = "f";
+ Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Expected.Namespace = llvm::ArrayRef(NsE);
- Expected->DefLoc = Location(10, 10, "test.cpp");
- Expected->Loc.emplace_back(12, 12, "test.cpp");
+ Expected.DefLoc = Location(10, 10, "test.cpp");
+ Location LocE(12, 12, "test.cpp");
+ Expected.Loc.push_back(LocE);
- Expected->ReturnType = TypeInfo("void");
- Expected->Params.emplace_back(TypeInfo("int"), "P");
- Expected->IsMethod = true;
- Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
+ 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);
CommentInfo ExpectedText[] = {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo ExpectedPara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, ExpectedText)};
- Expected->Description.emplace_back(CommentKind::CK_FullComment, ExpectedPara);
+ CommentInfo TopE(CommentKind::CK_FullComment, ExpectedPara);
+ Expected.Description.push_back(TopE);
auto Actual = mergeInfos(Infos);
assert(Actual);
- CheckFunctionInfo(InfoAsFunction(Expected.get()),
- InfoAsFunction(Actual.get().get()));
+ CheckFunctionInfo(InfoAsFunction(&Expected), InfoAsFunction(Actual.get()));
}
TEST_F(MergeTest, mergeEnumInfos) {
EnumInfo One;
One.Name = "e";
- One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ One.Namespace = llvm::ArrayRef(Ns1);
One.DefLoc = Location(10, 10, "test.cpp");
- One.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ One.Loc.push_back(Loc1);
One.Scoped = true;
EnumInfo Two;
Two.Name = "e";
- Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Two.Namespace = llvm::ArrayRef(Ns2);
- Two.Loc.emplace_back(20, 20, "test.cpp");
+ Location Loc2(20, 20, "test.cpp");
+ Two.Loc.push_back(Loc2);
- Two.Members.emplace_back("X");
- Two.Members.emplace_back("Y");
+ EnumValueInfo EV2[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
+ Two.Members = llvm::ArrayRef(EV2);
OwningPtrVec<Info> Infos;
- Infos.emplace_back(allocatePtr<EnumInfo>(std::move(One)));
- Infos.emplace_back(allocatePtr<EnumInfo>(std::move(Two)));
+ Infos.push_back(&One);
+ Infos.push_back(&Two);
- auto Expected = allocatePtr<EnumInfo>();
- Expected->Name = "e";
- Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ EnumInfo Expected;
+ Expected.Name = "e";
+ Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ Expected.Namespace = llvm::ArrayRef(NsE);
- Expected->DefLoc = Location(10, 10, "test.cpp");
- Expected->Loc.emplace_back(12, 12, "test.cpp");
- Expected->Loc.emplace_back(20, 20, "test.cpp");
+ 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->Members.emplace_back("X");
- Expected->Members.emplace_back("Y");
- Expected->Scoped = true;
+ EnumValueInfo EV_E[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
+ Expected.Members = llvm::ArrayRef(EV_E);
+ Expected.Scoped = true;
auto Actual = mergeInfos(Infos);
assert(Actual);
- CheckEnumInfo(InfoAsEnum(Expected.get()), InfoAsEnum(Actual.get().get()));
+ CheckEnumInfo(InfoAsEnum(&Expected), InfoAsEnum(Actual.get()));
}
} // namespace doc
diff --git a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
index 4e963fd64f11b..371efab1b3081 100644
--- a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -117,25 +117,27 @@ TEST_F(SerializeTest, emitNamespaceInfo) {
extractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
/*Public=*/false, Infos, this->Diags);
- NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *A = InfoAsNamespace(Infos[0]);
NamespaceInfo ExpectedA(EmptySID, "A");
CheckNamespaceInfo(&ExpectedA, A);
- NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
+ NamespaceInfo *B = InfoAsNamespace(Infos[2]);
NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
- ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference NsB[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ ExpectedB.Namespace = llvm::ArrayRef(NsB);
CheckNamespaceInfo(&ExpectedB, B);
- NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
+ NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4]);
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "f";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
- F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
- F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference NsF[] = {Reference(EmptySID, "B", InfoType::IT_namespace),
+ Reference(EmptySID, "A", InfoType::IT_namespace)};
+ F.Namespace = llvm::ArrayRef(NsF);
F.Access = AccessSpecifier::AS_none;
- ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
+ ExpectedBWithFunction.Children.Functions.push_back(F);
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -144,7 +146,7 @@ TEST_F(SerializeTest, emitAnonymousNamespaceInfo) {
extractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos,
this->Diags);
- NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *A = InfoAsNamespace(Infos[0]);
NamespaceInfo ExpectedA(EmptySID);
ExpectedA.Name = "@nonymous_namespace";
CheckNamespaceInfo(&ExpectedA, A);
@@ -170,95 +172,103 @@ void F<int>::TemplateMethod();
typedef struct {} G;)raw",
10, /*Public=*/false, Infos, this->Diags);
- RecordInfo *E = InfoAsRecord(Infos[0].get());
+ RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
- ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsE[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.TagType = TagTypeKind::Class;
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
- ExpectedE.Members.emplace_back(TypeInfo("int"), "value",
- AccessSpecifier::AS_public);
+ MemberTypeInfo MemE[] = {
+ MemberTypeInfo(TypeInfo("int"), "value", AccessSpecifier::AS_public)};
+ ExpectedE.Members = llvm::ArrayRef(MemE);
// 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].get());
+ RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2]);
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");
- EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
- EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsEC[] = {
+ Reference(EmptySID, "E", InfoType::IT_record),
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ EConstructor.Namespace = llvm::ArrayRef(NsEC);
EConstructor.Access = AccessSpecifier::AS_public;
EConstructor.IsMethod = true;
- ExpectedRecordWithEConstructor.Children.Functions.emplace_back(
- std::move(EConstructor));
+ ExpectedRecordWithEConstructor.Children.Functions.push_back(EConstructor);
CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
- RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
+ RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3]);
RecordInfo ExpectedRecordWithMethod(EmptySID);
FunctionInfo Method;
Method.Name = "ProtectedMethod";
Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
Method.ReturnType = TypeInfo("void");
- 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);
+ 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.Access = AccessSpecifier::AS_protected;
Method.IsMethod = true;
- ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method));
+ ExpectedRecordWithMethod.Children.Functions.push_back(Method);
CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
- RecordInfo *F = InfoAsRecord(Infos[4].get());
+ RecordInfo *F = InfoAsRecord(Infos[4]);
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
- ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsF3[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedF.Namespace = llvm::ArrayRef(NsF3);
ExpectedF.TagType = TagTypeKind::Struct;
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedF, F);
- RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
+ RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6]);
RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
FunctionInfo TemplateMethod;
TemplateMethod.Name = "TemplateMethod";
TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
TemplateMethod.ReturnType = TypeInfo("void");
- 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);
+ 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.Access = AccessSpecifier::AS_public;
TemplateMethod.IsMethod = true;
- ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back(
- std::move(TemplateMethod));
+ ExpectedRecordWithTemplateMethod.Children.Functions.push_back(TemplateMethod);
CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
- RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
+ RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7]);
RecordInfo ExpectedTemplatedRecord(EmptySID);
FunctionInfo SpecializedTemplateMethod;
SpecializedTemplateMethod.Name = "TemplateMethod";
SpecializedTemplateMethod.Parent =
Reference(EmptySID, "F", InfoType::IT_record);
SpecializedTemplateMethod.ReturnType = TypeInfo("void");
- 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);
+ 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.Access = AccessSpecifier::AS_public;
SpecializedTemplateMethod.IsMethod = true;
- ExpectedTemplatedRecord.Children.Functions.emplace_back(
- std::move(SpecializedTemplateMethod));
+ ExpectedTemplatedRecord.Children.Functions.push_back(
+ SpecializedTemplateMethod);
CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
- RecordInfo *G = InfoAsRecord(Infos[8].get());
+ RecordInfo *G = InfoAsRecord(Infos[8]);
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
- ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsG[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedG.Namespace = llvm::ArrayRef(NsG);
ExpectedG.TagType = TagTypeKind::Struct;
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
ExpectedG.IsTypeDef = true;
@@ -271,25 +281,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].get());
+ NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0]);
NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
EnumInfo E;
E.Name = "E";
E.DefLoc = Location(0, 0, "test.cpp");
- E.Members.emplace_back("X", "0");
- E.Members.emplace_back("Y", "1");
- ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E));
+ EnumValueInfo EMem[] = {EnumValueInfo("X", "0"), EnumValueInfo("Y", "1")};
+ E.Members = llvm::ArrayRef(EMem);
+ ExpectedNamespaceWithEnum.Children.Enums.push_back(E);
CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
- NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
+ NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1]);
NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
EnumInfo G;
G.Name = "G";
G.Scoped = true;
G.DefLoc = Location(0, 0, "test.cpp");
- G.Members.emplace_back("A", "0");
- G.Members.emplace_back("B", "1");
- ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G));
+ EnumValueInfo GMem[] = {EnumValueInfo("A", "0"), EnumValueInfo("B", "1")};
+ G.Members = llvm::ArrayRef(GMem);
+ ExpectedNamespaceWithScopedEnum.Children.Enums.push_back(G);
CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
}
@@ -297,12 +307,14 @@ TEST_F(SerializeTest, emitUndefinedRecordInfo) {
EmittedInfoList Infos;
extractInfosFromCode("class E;", 2, /*Public=*/false, Infos, this->Diags);
- RecordInfo *E = InfoAsRecord(Infos[0].get());
+ RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
- ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsE[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.TagType = TagTypeKind::Class;
- ExpectedE.Loc.emplace_back(0, 0, "test.cpp");
+ Location LE(0, 0, "test.cpp");
+ ExpectedE.Loc.push_back(LE);
CheckRecordInfo(&ExpectedE, E);
}
@@ -311,14 +323,16 @@ TEST_F(SerializeTest, emitRecordMemberInfo) {
extractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos,
this->Diags);
- RecordInfo *E = InfoAsRecord(Infos[0].get());
+ RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
- ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsE[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.TagType = TagTypeKind::Struct;
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
- ExpectedE.Members.emplace_back(TypeInfo("int"), "I",
- AccessSpecifier::AS_public);
+ MemberTypeInfo MemE[] = {
+ MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_public)};
+ ExpectedE.Members = llvm::ArrayRef(MemE);
CheckRecordInfo(&ExpectedE, E);
}
@@ -327,23 +341,25 @@ TEST_F(SerializeTest, emitInternalRecordInfo) {
extractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos,
this->Diags);
- RecordInfo *E = InfoAsRecord(Infos[0].get());
+ RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
- ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsE[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
ExpectedE.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedE, E);
- RecordInfo *G = InfoAsRecord(Infos[2].get());
+ RecordInfo *G = InfoAsRecord(Infos[2]);
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;
- ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
- ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsG[] = {
+ Reference(EmptySID, "E", InfoType::IT_record),
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedG.Namespace = llvm::ArrayRef(NsG);
CheckRecordInfo(&ExpectedG, G);
}
@@ -358,14 +374,14 @@ TEST_F(SerializeTest, emitPublicFunctionInternalInfo) {
extractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
Infos, this->Diags);
- NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
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.emplace_back(std::move(F));
+ ExpectedBWithFunction.Children.Functions.push_back(F);
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -374,15 +390,16 @@ TEST_F(SerializeTest, emitInlinedFunctionInfo) {
extractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos,
this->Diags);
- NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "F";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
- F.Params.emplace_back(TypeInfo("int"), "I");
+ FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I")};
+ F.Params = llvm::ArrayRef(Params);
F.Access = AccessSpecifier::AS_none;
- ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
+ ExpectedBWithFunction.Children.Functions.push_back(F);
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -397,132 +414,169 @@ class I {} ;
class J : public I<int> {} ;)raw",
14, /*Public=*/false, Infos, this->Diags);
- RecordInfo *F = InfoAsRecord(Infos[0].get());
+ RecordInfo *F = InfoAsRecord(Infos[0]);
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
- ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace, "");
+ Reference NsF[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedF.Namespace = llvm::ArrayRef(NsF);
ExpectedF.TagType = TagTypeKind::Class;
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedF, F);
- RecordInfo *G = InfoAsRecord(Infos[3].get());
+ RecordInfo *G = InfoAsRecord(Infos[3]);
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
- ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsG[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedG.Namespace = llvm::ArrayRef(NsG);
ExpectedG.TagType = TagTypeKind::Class;
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
- ExpectedG.Members.emplace_back(TypeInfo("int"), "I",
- AccessSpecifier::AS_protected);
+ MemberTypeInfo MemG[] = {
+ MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_protected)};
+ ExpectedG.Members = llvm::ArrayRef(MemG);
CheckRecordInfo(&ExpectedG, G);
- RecordInfo *E = InfoAsRecord(Infos[6].get());
+ RecordInfo *E = InfoAsRecord(Infos[6]);
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
- 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);
+ 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);
FunctionInfo FunctionSet;
FunctionSet.Name = "set";
FunctionSet.ReturnType = TypeInfo("void");
- 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);
+ 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.Access = AccessSpecifier::AS_protected;
FunctionSet.IsMethod = 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);
+ BaseF.Children.Functions.push_back(FunctionSet);
+
+ BaseRecordInfo BaseG(EmptySID, /*Name=*/"G",
+ /*Path=*/"GlobalNamespace", true,
+ AccessSpecifier::AS_private, true);
FunctionInfo FunctionGet;
FunctionGet.Name = "get";
FunctionGet.ReturnType = TypeInfo("int");
- FunctionGet.DefLoc = Location();
- FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
- FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ 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.Access = AccessSpecifier::AS_private;
FunctionGet.IsMethod = true;
- ExpectedE.Bases.back().Children.Functions.emplace_back(
- std::move(FunctionGet));
- ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
- AccessSpecifier::AS_private);
+ 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.DefLoc = Location(0, 0, "test.cpp");
ExpectedE.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedE, E);
- RecordInfo *H = InfoAsRecord(Infos[8].get());
+ RecordInfo *H = InfoAsRecord(Infos[8]);
RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
- ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsH[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedH.Namespace = llvm::ArrayRef(NsH);
ExpectedH.TagType = TagTypeKind::Class;
ExpectedH.DefLoc = Location(0, 0, "test.cpp");
- 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);
+ 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);
FunctionInfo FunctionSetNew;
FunctionSetNew.Name = "set";
FunctionSetNew.ReturnType = TypeInfo("void");
- 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);
+ 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.Access = AccessSpecifier::AS_private;
FunctionSetNew.IsMethod = true;
- ExpectedH.Bases.back().Children.Functions.emplace_back(
- std::move(FunctionSetNew));
- ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
- /*Path=*/"GlobalNamespace", true,
- AccessSpecifier::AS_private, false);
+ BaseHF.Children.Functions.push_back(FunctionSetNew);
+ BaseRecordInfo BaseHG(EmptySID, /*Name=*/"G",
+ /*Path=*/"GlobalNamespace", true,
+ AccessSpecifier::AS_private, false);
FunctionInfo FunctionGetNew;
FunctionGetNew.Name = "get";
FunctionGetNew.ReturnType = TypeInfo("int");
- FunctionGetNew.DefLoc = Location();
- FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
- FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ 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.Access = AccessSpecifier::AS_private;
FunctionGetNew.IsMethod = true;
- ExpectedH.Bases.back().Children.Functions.emplace_back(
- std::move(FunctionGetNew));
- ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
- AccessSpecifier::AS_private);
+ 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);
+
CheckRecordInfo(&ExpectedH, H);
- RecordInfo *I = InfoAsRecord(Infos[10].get());
+ RecordInfo *I = InfoAsRecord(Infos[10]);
RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
- ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
+ Reference NsI[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedI.Namespace = llvm::ArrayRef(NsI);
ExpectedI.TagType = TagTypeKind::Class;
ExpectedI.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedI, I);
- RecordInfo *J = InfoAsRecord(Infos[12].get());
+ RecordInfo *J = InfoAsRecord(Infos[12]);
RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
- ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
- InfoType::IT_namespace);
- ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
- InfoType::IT_record);
- ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
- /*Path=*/"GlobalNamespace", false,
- AccessSpecifier::AS_public, true);
+ Reference NsJ[] = {
+ Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
+ ExpectedJ.Namespace = llvm::ArrayRef(NsJ);
+ Reference ParJ[] = {
+ Reference(EmptySID, /*Name=*/"I<int>", InfoType::IT_record)};
+ ExpectedJ.Parents = llvm::ArrayRef(ParJ);
+ BaseRecordInfo BasesJ[] = {BaseRecordInfo(EmptySID, /*Name=*/"I<int>",
+ /*Path=*/"GlobalNamespace", false,
+ AccessSpecifier::AS_public, true)};
+ ExpectedJ.Bases = llvm::ArrayRef(BasesJ);
ExpectedJ.DefLoc = Location(0, 0, "test.cpp");
ExpectedJ.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedJ, J);
@@ -538,30 +592,33 @@ static int staticModuleFunction(int x);
export double exportedModuleFunction(double y);)raw",
2, /*Public=*/true, Infos, Args, this->Diags);
- NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "moduleFunction";
F.ReturnType = TypeInfo("int");
- 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";
+ 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.Access = AccessSpecifier::AS_none;
- ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
+ ExpectedBWithFunction.Children.Functions.push_back(F);
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
- NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
+ NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1]);
NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
FunctionInfo ExportedF;
ExportedF.Name = "exportedModuleFunction";
ExportedF.ReturnType =
TypeInfo(Reference(EmptySID, "double", InfoType::IT_default));
- ExportedF.Loc.emplace_back(0, 0, "test.cpp");
- ExportedF.Params.emplace_back(TypeInfo("double"), "y");
+ Location LF2(0, 0, "test.cpp");
+ ExportedF.Loc.push_back(LF2);
+ FieldTypeInfo ParamsExportedF[] = {FieldTypeInfo(TypeInfo("double"), "y")};
+ ExportedF.Params = llvm::ArrayRef(ParamsExportedF);
ExportedF.Access = AccessSpecifier::AS_none;
- ExpectedBWithExportedFunction.Children.Functions.emplace_back(
- std::move(ExportedF));
+ ExpectedBWithExportedFunction.Children.Functions.push_back(ExportedF);
CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
}
@@ -571,24 +628,24 @@ TEST_F(SerializeTest, emitChildRecords) {
extractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
/*Public=*/false, Infos, this->Diags);
- NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
+ NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
NamespaceInfo ExpectedParentA(EmptySID);
- ExpectedParentA.Children.Records.emplace_back(
- EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
+ Reference RA(EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
+ ExpectedParentA.Children.Records.push_back(RA);
CheckNamespaceInfo(&ExpectedParentA, ParentA);
- RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
+ RecordInfo *ParentB = InfoAsRecord(Infos[3]);
RecordInfo ExpectedParentB(EmptySID);
llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
llvm::sys::path::native(ExpectedParentBPath);
- ExpectedParentB.Children.Records.emplace_back(
- EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
+ Reference RB(EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
+ ExpectedParentB.Children.Records.push_back(RB);
CheckRecordInfo(&ExpectedParentB, ParentB);
- NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
+ NamespaceInfo *ParentC = InfoAsNamespace(Infos[7]);
NamespaceInfo ExpectedParentC(EmptySID);
- ExpectedParentC.Children.Records.emplace_back(
- EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
+ Reference RC(EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
+ ExpectedParentC.Children.Records.push_back(RC);
CheckNamespaceInfo(&ExpectedParentC, ParentC);
}
@@ -598,13 +655,13 @@ TEST_F(SerializeTest, emitChildNamespaces) {
extractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
Infos, this->Diags);
- NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
+ NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
NamespaceInfo ExpectedParentA(EmptySID);
Reference RA(EmptySID, "A", InfoType::IT_namespace);
ExpectedParentA.Children.Namespaces.push_back(RA);
CheckNamespaceInfo(&ExpectedParentA, ParentA);
- NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
+ NamespaceInfo *ParentB = InfoAsNamespace(Infos[3]);
NamespaceInfo ExpectedParentB(EmptySID);
Reference RB(EmptySID, "B", InfoType::IT_namespace, "A::B", "A");
ExpectedParentB.Children.Namespaces.push_back(RB);
@@ -617,10 +674,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].get());
+ NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size());
- const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0];
+ const TypedefInfo &FirstTD = *GlobalNS1->Children.Typedefs.begin();
EXPECT_EQ("MyInt", FirstTD.Name);
EXPECT_FALSE(FirstTD.IsUsing);
EXPECT_EQ("int", FirstTD.Underlying.Type.Name);
@@ -628,11 +685,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].get());
+ NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size());
// Second is the "using" typedef.
- const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0];
+ const TypedefInfo &SecondTD = *GlobalNS2->Children.Typedefs.begin();
EXPECT_EQ("MyDouble", SecondTD.Name);
EXPECT_TRUE(SecondTD.IsUsing);
EXPECT_EQ("double", SecondTD.Underlying.Type.Name);
@@ -647,10 +704,10 @@ TEST_F(SerializeTest, emitFunctionTemplate) {
/*Public=*/false, Infos, this->Diags);
// First info will be the global namespace.
- NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
+ NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
ASSERT_EQ(1u, GlobalNS1->Children.Functions.size());
- const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0];
+ const FunctionInfo &Func1 = *GlobalNS1->Children.Functions.begin();
EXPECT_EQ("GetFoo", Func1.Name);
ASSERT_TRUE(Func1.Template);
EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization.
@@ -662,11 +719,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].get());
+ NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
ASSERT_EQ(1u, GlobalNS2->Children.Functions.size());
// This one is a template specialization.
- const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0];
+ const FunctionInfo &Func2 = *GlobalNS2->Children.Functions.begin();
EXPECT_EQ("GetFoo", Func2.Name);
ASSERT_TRUE(Func2.Template);
EXPECT_TRUE(Func2.Template->Params.empty()); // No template params.
@@ -694,7 +751,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
/*Public=*/false, Infos, this->Diags);
// First record.
- const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get());
+ const RecordInfo *Rec1 = InfoAsRecord(Infos[0]);
EXPECT_EQ("MyTemplate", Rec1->Name);
ASSERT_TRUE(Rec1->Template);
EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization.
@@ -704,7 +761,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ("int I", Rec1->Template->Params[0].Contents);
// Second record.
- const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get());
+ const RecordInfo *Rec2 = InfoAsRecord(Infos[2]);
EXPECT_EQ("MyTemplate", Rec2->Name);
ASSERT_TRUE(Rec2->Template);
EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params.
@@ -716,7 +773,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf);
// Third record.
- const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get());
+ const RecordInfo *Rec3 = InfoAsRecord(Infos[4]);
EXPECT_EQ("OtherTemplate", Rec3->Name);
ASSERT_TRUE(Rec3->Template);
@@ -726,7 +783,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents);
// Fourth record.
- const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get());
+ const RecordInfo *Rec4 = InfoAsRecord(Infos[6]);
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 a7f8629b926c1..6f4b724bd9427 100644
--- a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
@@ -28,20 +28,25 @@ TEST_F(YAMLGeneratorTest, emitNamespaceYAML) {
NamespaceInfo I;
I.Name = "Namespace";
I.Path = "path/to/A";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
"path::to::A::Namespace::ChildNamespace",
"path/to/A/Namespace");
I.Children.Namespaces.push_back(NewNamespace);
- 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";
+ 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);
auto G = getYAMLGenerator();
assert(G);
@@ -85,12 +90,14 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
I.Name = "r";
I.Path = "path/to/A";
I.IsTypeDef = true;
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
+ MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
// Member documentation.
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
@@ -99,26 +106,39 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
CommentInfo TopCommentChildren[] = {
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
- I.Members.back().Description.push_back(std::move(TopComment));
+ M.Description.push_back(TopComment);
+ MemberTypeInfo MemArr[] = {std::move(M)};
+ I.Members = llvm::ArrayRef(MemArr);
I.TagType = TagTypeKind::Class;
- 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
- 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");
+ 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.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";
+ // 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);
+
+ 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);
auto G = getYAMLGenerator();
assert(G);
@@ -205,17 +225,22 @@ IsTypeDef: true
TEST_F(YAMLGeneratorTest, emitFunctionYAML) {
FunctionInfo I;
I.Name = "f";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
I.Access = AccessSpecifier::AS_none;
I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default));
- I.Params.emplace_back(TypeInfo("int"), "P");
- I.Params.emplace_back(TypeInfo("double"), "D");
- I.Params.back().DefaultValue = "2.0 * M_PI";
+
+ 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.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -270,12 +295,15 @@ IsMethod: true
TEST_F(YAMLGeneratorTest, emitSimpleEnumYAML) {
EnumInfo I;
I.Name = "e";
- I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+ Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
+ I.Namespace = llvm::ArrayRef(Ns);
I.DefLoc = Location(10, 10, "test.cpp");
- I.Loc.emplace_back(12, 12, "test.cpp");
+ Location Loc1(12, 12, "test.cpp");
+ I.Loc.push_back(Loc1);
- I.Members.emplace_back("X");
+ EnumValueInfo EV[] = {EnumValueInfo("X")};
+ I.Members = llvm::ArrayRef(EV);
I.Scoped = false;
auto G = getYAMLGenerator();
@@ -312,7 +340,8 @@ TEST_F(YAMLGeneratorTest, enumTypedScopedEnumYAML) {
EnumInfo I;
I.Name = "e";
- I.Members.emplace_back("X", "-9876", "FOO_BAR + 2");
+ EnumValueInfo EV[] = {EnumValueInfo("X", "-9876", "FOO_BAR + 2")};
+ I.Members = llvm::ArrayRef(EV);
I.Scoped = true;
I.BaseType = TypeInfo("short");
@@ -370,8 +399,9 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
I.Name = "f";
I.DefLoc = Location(10, 10, "test.cpp");
I.ReturnType = TypeInfo("void");
- I.Params.emplace_back(TypeInfo("int"), "I");
- I.Params.emplace_back(TypeInfo("int"), "J");
+ FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I"),
+ FieldTypeInfo(TypeInfo("int"), "J")};
+ I.Params = llvm::ArrayRef(Params);
I.Access = AccessSpecifier::AS_none;
// BlankLine
@@ -444,7 +474,7 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
Verbatim, ParamOut, ParamIn, Return};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
- I.Description.emplace_back(std::move(Top));
+ I.Description.push_back(Top);
auto G = getYAMLGenerator();
assert(G);
More information about the llvm-branch-commits
mailing list