Revert clang-doc arena merging patches (#191668)

This is a set of squashed reverts of recent clang doc patches, since its
breaking something on Darwin builders:
https://lab.llvm.org/buildbot/#/builders/23/builds/19172

Revert "[clang-doc][nfc] Default initialize all StringRef members
(#191641)"

This reverts commit 155b9b354c.

Revert "[clang-doc] Initialize StringRef members in Info types
(#191637)"

This reverts commit 489dab3827.

Revert "[clang-doc] Initialize member variable (#191570)"

This reverts commit 5d64a44a84.

Revert "[clang-doc] Merge data into persistent memory (#190056)"

This reverts commit 21e0034c69.

Revert "[clang-doc] Support deep copy between arenas for merging
(#190055)"

This reverts commit c70dae8b0c.
This commit is contained in:
Paul Kirth
2026-04-13 08:40:40 -07:00
committed by GitHub
parent 212d612bae
commit 22e6a261fa
21 changed files with 1009 additions and 1995 deletions

View File

@@ -129,15 +129,14 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
"invalid value for FieldId");
}
static llvm::Error decodeRecord(const Record &R, OwningVec<Location> &Field,
static llvm::Error decodeRecord(const Record &R,
llvm::SmallVectorImpl<Location> &Field,
llvm::StringRef Blob) {
if (R[0] > INT_MAX)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"integer too large to parse");
Field.push_back(*allocatePtr<Location>(static_cast<int>(R[0]),
static_cast<int>(R[1]), Blob,
static_cast<bool>(R[2])));
Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
static_cast<bool>(R[2]));
return llvm::Error::success();
}
@@ -426,99 +425,6 @@ 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;
@@ -542,13 +448,25 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
if (!LocalChildren.empty())
I->Children =
allocateArray<CommentInfo>(LocalChildren, TransientArena);
if (!AttrKeys.empty())
I->AttrKeys = allocateArray(AttrKeys, TransientArena);
if (!AttrValues.empty())
I->AttrValues = allocateArray(AttrValues, TransientArena);
if (!Args.empty())
I->Args = allocateArray(Args, TransientArena);
if (!AttrKeys.empty()) {
StringRef *KeysMem =
TransientArena.Allocate<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());
}
return llvm::Error::success();
},
[&](unsigned BlockOrCode) -> llvm::Error {
@@ -563,219 +481,6 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
});
}
template <>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) {
llvm::SmallVector<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) {
@@ -874,25 +579,51 @@ 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.
@@ -902,11 +633,26 @@ static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
"invalid type cannot contain TypeInfo");
}
template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
I->Members.emplace_back(std::move(T));
return llvm::Error::success();
}
template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
I->Members.emplace_back(std::move(T));
return llvm::Error::success();
}
template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
I->ReturnType = std::move(T);
return llvm::Error::success();
}
template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
I->Params.emplace_back(std::move(T));
return llvm::Error::success();
}
template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
I->ReturnType.emplace(std::move(T));
return llvm::Error::success();
@@ -935,6 +681,9 @@ static llvm::Error addReference(T I, Reference &&R, FieldId F) {
template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"VarInfo cannot contain this Reference");
@@ -978,6 +727,9 @@ llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid type cannot contain Reference");
@@ -986,6 +738,9 @@ template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid type cannot contain Reference");
@@ -995,13 +750,16 @@ template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
template <>
llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_child_namespace:
I->Children.Namespaces.push_back(
*allocatePtr<Reference>(TransientArena, std::move(R)));
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
case FieldId::F_child_namespace: {
Reference *NewR = allocatePtr<Reference>(TransientArena, std::move(R));
I->Children.Namespaces.push_back(*NewR);
return llvm::Error::success();
}
case FieldId::F_child_record:
I->Children.Records.push_back(
*allocatePtr<Reference>(TransientArena, std::move(R)));
I->Children.Records.emplace_back(std::move(R));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -1012,6 +770,9 @@ llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
template <>
llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
case FieldId::F_parent:
I->Parent = std::move(R);
return llvm::Error::success();
@@ -1023,9 +784,17 @@ llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
switch (F) {
case FieldId::F_namespace:
I->Namespace.emplace_back(std::move(R));
return llvm::Error::success();
case FieldId::F_parent:
I->Parents.emplace_back(std::move(R));
return llvm::Error::success();
case FieldId::F_vparent:
I->VirtualParents.emplace_back(std::move(R));
return llvm::Error::success();
case FieldId::F_child_record:
I->Children.Records.push_back(
*allocatePtr<Reference>(TransientArena, std::move(R)));
I->Children.Records.emplace_back(std::move(R));
return llvm::Error::success();
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -1054,42 +823,54 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
"Friend cannot contain this Reference");
}
static auto &getList(ScopeChildren &C, FunctionInfo *) { return C.Functions; }
static auto &getList(ScopeChildren &C, EnumInfo *) { return C.Enums; }
static auto &getList(ScopeChildren &C, TypedefInfo *) { return C.Typedefs; }
static auto &getList(ScopeChildren &C, ConceptInfo *) { return C.Concepts; }
static auto &getList(ScopeChildren &C, VarInfo *) { return C.Variables; }
template <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;
}
}
}
template <typename T, typename ChildInfoType>
static void addChild(T I, ChildInfoType &&R) {
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid child type for info"));
}
// Namespace children:
template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
I->Children.Functions.emplace_back(std::move(R));
}
template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
I->Children.Enums.emplace_back(std::move(R));
}
template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
I->Children.Typedefs.emplace_back(std::move(R));
}
template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
I->Children.Concepts.emplace_back(std::move(R));
}
template <> void addChild(NamespaceInfo *I, VarInfo &&R) {
I->Children.Variables.emplace_back(std::move(R));
}
// Record children:
template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
I->Children.Functions.emplace_back(std::move(R));
}
template <> void addChild(RecordInfo *I, EnumInfo &&R) {
I->Children.Enums.emplace_back(std::move(R));
}
template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
I->Children.Typedefs.emplace_back(std::move(R));
}
template <> void addChild(RecordInfo *I, FriendInfo &&R) {
I->Friends.emplace_back(std::move(R));
}
// Other types of children:
template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
I->Members.emplace_back(std::move(R));
}
template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
I->Bases.emplace_back(std::move(R));
}
template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
I->Children.Functions.emplace_back(std::move(R));
}
// TemplateParam children. These go into either a TemplateInfo (for template
// parameters) or TemplateSpecializationInfo (for the specialization's
// parameters).
@@ -1098,6 +879,13 @@ template <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) {
@@ -1137,6 +925,9 @@ 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>
@@ -1161,37 +952,6 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
}
// Read a block of records into a single info.
template <>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I) {
return readBlockWithNamespace(ID, I);
}
template <>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I) {
return readBlockWithNamespace(ID, I);
}
template <>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I) {
return readBlockWithNamespace(ID, I);
}
template <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(
@@ -1209,13 +969,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
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)
if (BlockOrCode == BI_FIELD_TYPE_BLOCK_ID) {
FieldTypeInfo FI;
if (auto Err = readBlock(BlockOrCode, &FI))
return std::move(Err);
LocalParams.push_back(std::move(FI));
return true;
}
return false;
},
[&]() -> llvm::Error {
@@ -1228,19 +988,27 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
});
}
// TODO: fix inconsistentent returning of errors in add callbacks.
// Once that's fixed, we only need one handleSubBlock.
template <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;
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));
}
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();
}
template <typename T>
@@ -1264,15 +1032,15 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
return llvm::Error::success();
}
case BI_TYPE_BLOCK_ID: {
return handleSubBlock<TypeInfo>(ID, I,
CreateAddFunc(addTypeInfo<T, TypeInfo>));
return handleTypeSubBlock<TypeInfo>(
ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
}
case BI_FIELD_TYPE_BLOCK_ID: {
return handleSubBlock<FieldTypeInfo>(
return handleTypeSubBlock<FieldTypeInfo>(
ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
}
case BI_MEMBER_TYPE_BLOCK_ID: {
return handleSubBlock<MemberTypeInfo>(
return handleTypeSubBlock<MemberTypeInfo>(
ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
}
case BI_REFERENCE_BLOCK_ID: {

View File

@@ -44,32 +44,12 @@ private:
// 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);

View File

@@ -27,7 +27,6 @@ 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);
@@ -62,12 +61,10 @@ class JSONGenerator : public Generator {
};
}
llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
const ClangDocContext *CDCtx;
bool Markdown;
public:
static const char *Format;
const ClangDocContext *CDCtx;
bool Markdown;
Error generateDocumentation(StringRef RootDir,
llvm::StringMap<OwnedPtr<doc::Info>> Infos,
@@ -323,20 +320,13 @@ static Object serializeComment(const CommentInfo &I, Object &Description) {
/// Creates Contexts for namespaces and records to allow for navigation.
void JSONGenerator::generateContext(const Info &I, Object &Obj) {
Obj["Contexts"] = json::Array();
Obj["HasContexts"] = true;
auto It = ContextsMap.find(&I);
if (It == ContextsMap.end() || It->second.empty())
return;
auto &ContextArrayRef = *Obj["Contexts"].getAsArray();
const auto &Contexts = It->second;
ContextArrayRef.reserve(Contexts.size());
json::Value ContextArray = json::Array();
auto &ContextArrayRef = *ContextArray.getAsArray();
ContextArrayRef.reserve(I.Contexts.size());
std::string CurrentRelativePath;
bool PreviousRecord = false;
for (const auto &Current : Contexts) {
for (const auto &Current : I.Contexts) {
json::Value ContextVal = Object();
Object &Context = *ContextVal.getAsObject();
serializeReference(Current, Context);
@@ -382,9 +372,11 @@ void JSONGenerator::generateContext(const Info &I, Object &Obj) {
}
ContextArrayRef.back().getAsObject()->insert({"End", true});
Obj["Contexts"] = ContextArray;
Obj["HasContexts"] = true;
}
static void serializeDescription(const OwningVec<CommentInfo> &Description,
static void serializeDescription(llvm::ArrayRef<CommentInfo> Description,
json::Object &Obj, StringRef Key = "") {
if (Description.empty())
return;
@@ -437,8 +429,7 @@ void JSONGenerator::serializeCommonAttributes(const Info &I,
Obj["Location"] = serializeLocation(Symbol->DefLoc.value());
}
auto It = ContextsMap.find(&I);
if (It != ContextsMap.end() && !It->second.empty())
if (!I.Contexts.empty())
generateContext(I, Obj);
}
@@ -835,9 +826,9 @@ SmallString<16> JSONGenerator::determineFileName(Info *I,
/// \param CDCtxIndex Passed by copy since clang-doc's context is passed to the
/// generator as `const`
static std::vector<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
static OwningVec<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
CDCtxIndex.sort();
std::vector<Index> Processed;
OwningVec<Index> Processed;
Processed.reserve(CDCtxIndex.Children.size());
for (const auto *Idx : CDCtxIndex.getSortedChildren()) {
Index NewIdx = *Idx;
@@ -857,7 +848,7 @@ Error JSONGenerator::serializeAllFiles(const ClangDocContext &CDCtx,
StringRef RootDir) {
json::Value ObjVal = Object();
Object &Obj = *ObjVal.getAsObject();
std::vector<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
OwningVec<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
serializeArray(IndexCopy, Obj, "Index", serializeReferenceLambda());
SmallString<128> Path;
sys::path::append(Path, RootDir, "json", "all_files.json");
@@ -920,12 +911,10 @@ Error JSONGenerator::serializeIndex(StringRef RootDir) {
return Error::success();
}
void JSONGenerator::serializeContexts(Info *I,
StringMap<OwnedPtr<Info>> &Infos) {
static void 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),
@@ -939,12 +928,12 @@ void JSONGenerator::serializeContexts(Info *I,
Context GlobalRef(ParentInfo->USR, "Global Namespace",
InfoType::IT_namespace, "GlobalNamespace", "",
SmallString<16>("index"));
LocalContexts.push_back(GlobalRef);
break;
I->Contexts.push_back(GlobalRef);
return;
}
Context ParentRef(*ParentInfo);
LocalContexts.push_back(ParentRef);
I->Contexts.push_back(ParentRef);
ParentUSR = ParentInfo->ParentUSR;
}
}

View File

@@ -31,7 +31,8 @@ static std::string genEmphasis(const Twine &Text) {
return "**" + Text.str() + "**";
}
static std::string genReferenceList(llvm::ArrayRef<Reference> Refs) {
static std::string
genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
for (const auto &R : Refs) {
@@ -81,7 +82,7 @@ class TableCommentWriter {
public:
explicit TableCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
void write(const OwningVec<CommentInfo> &Comments) {
void write(llvm::ArrayRef<CommentInfo> Comments) {
for (const auto &C : Comments)
writeTableSafeComment(C);
@@ -435,7 +436,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
OS << " for " << CDCtx.ProjectName;
OS << "\n\n";
std::vector<const Index *> Children = CDCtx.Idx.getSortedChildren();
OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
for (const auto *C : Children)
serializeReference(OS, *C, 0);
@@ -454,7 +455,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
FileErr.message());
CDCtx.Idx.sort();
OS << "# " << CDCtx.ProjectName << " C/C++ Reference\n\n";
std::vector<const Index *> Children = CDCtx.Idx.getSortedChildren();
OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
for (const auto *C : Children) {
if (!C->Children.empty()) {
const char *Type;

View File

@@ -43,9 +43,6 @@ void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
if (CDCtx.FTimeTrace)
llvm::timeTraceProfilerInitialize(200, "clang-doc");
TraverseDecl(Context.getTranslationUnitDecl());
TransientArena.Reset();
if (CDCtx.FTimeTrace)
llvm::timeTraceProfilerFinishThread();
}

View File

@@ -105,6 +105,17 @@ 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) {
@@ -115,145 +126,34 @@ static void reduceChildren(llvm::simple_ilist<T> &Children,
auto It = llvm::find_if(
Children, [&](const T &C) { return C.USR == ChildToMerge->USR; });
if (It == Children.end()) {
T *NewChild = allocatePtr<T>(PersistentArena, ChildToMerge->USR);
NewChild->merge(std::move(*ChildToMerge));
Children.push_back(*NewChild);
Children.push_back(*ChildToMerge);
} else {
It->merge(std::move(*ChildToMerge));
}
}
}
template <>
void reduceChildren<Reference>(
llvm::simple_ilist<Reference> &Children,
llvm::simple_ilist<Reference> &&ChildrenToMerge) {
while (!ChildrenToMerge.empty()) {
Reference *ChildToMerge = &ChildrenToMerge.front();
ChildrenToMerge.pop_front();
auto It = llvm::find_if(Children, [&](const Reference &C) {
return C.USR == ChildToMerge->USR;
});
if (It == Children.end()) {
Reference *NewChild = allocatePtr<Reference>(PersistentArena);
NewChild->USR = ChildToMerge->USR;
NewChild->RefType = ChildToMerge->RefType;
NewChild->merge(std::move(*ChildToMerge));
Children.push_back(*NewChild);
} else {
It->merge(std::move(*ChildToMerge));
template <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) {
using T = typename Container::value_type;
while (!Source.empty()) {
auto &Item = Source.front();
Source.pop_front();
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
T *NewItem = allocatePtr<T>(PersistentArena, Item);
Target.push_back(*NewItem);
}
for (auto &Item : Source) {
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; }))
Target.push_back(std::move(Item));
}
}
template <>
void mergeUnkeyed<OwningVec<CommentInfo>>(OwningVec<CommentInfo> &Target,
OwningVec<CommentInfo> &&Source) {
while (!Source.empty()) {
auto &Item = Source.front();
Source.pop_front();
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
CommentInfo *NewItem =
allocatePtr<CommentInfo>(PersistentArena, Item, PersistentArena);
Target.push_back(*NewItem);
}
}
}
llvm::Error mergeSingleInfo(doc::OwnedPtr<doc::Info> &Reduced,
doc::OwnedPtr<doc::Info> &&NewInfo,
llvm::BumpPtrAllocator &Arena) {
if (!Reduced) {
switch (NewInfo->IT) {
case InfoType::IT_namespace:
Reduced = allocatePtr<NamespaceInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_record:
Reduced = allocatePtr<RecordInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_enum:
Reduced = allocatePtr<EnumInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_function:
Reduced = allocatePtr<FunctionInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_typedef:
Reduced = allocatePtr<TypedefInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_concept:
Reduced = allocatePtr<ConceptInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_variable:
Reduced = allocatePtr<VarInfo>(Arena, NewInfo->USR);
break;
case InfoType::IT_friend:
Reduced = allocatePtr<FriendInfo>(Arena, NewInfo->USR);
break;
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"unknown info type");
}
}
if (Reduced->IT != NewInfo->IT)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"info types mismatch");
switch (Reduced->IT) {
case InfoType::IT_namespace:
static_cast<NamespaceInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<NamespaceInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_record:
static_cast<RecordInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<RecordInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_enum:
static_cast<EnumInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<EnumInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_function:
static_cast<FunctionInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<FunctionInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_typedef:
static_cast<TypedefInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<TypedefInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_concept:
static_cast<ConceptInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<ConceptInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_variable:
static_cast<VarInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<VarInfo *>(getPtr(NewInfo))));
break;
case InfoType::IT_friend:
static_cast<FriendInfo *>(getPtr(Reduced))
->merge(std::move(*static_cast<FriendInfo *>(getPtr(NewInfo))));
break;
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"unknown info type");
}
return llvm::Error::success();
}
// Dispatch function.
llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
if (Values.empty() || !Values[0])
@@ -284,20 +184,6 @@ llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
llvm_unreachable("unhandled enumerator");
}
TemplateSpecializationInfo::TemplateSpecializationInfo(
const TemplateSpecializationInfo &Other, llvm::BumpPtrAllocator &Arena)
: SpecializationOf(Other.SpecializationOf) {
Params = allocateArray(Other.Params, Arena);
}
TemplateInfo::TemplateInfo(const TemplateInfo &Other,
llvm::BumpPtrAllocator &Arena) {
Params = allocateArray(Other.Params, Arena);
if (Other.Specialization)
Specialization = TemplateSpecializationInfo(*Other.Specialization, Arena);
Constraints = allocateArray(Other.Constraints, Arena);
}
bool CommentInfo::operator==(const CommentInfo &Other) const {
auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
SelfClosing, Explicit, AttrKeys, AttrValues, Args);
@@ -333,28 +219,6 @@ bool CommentInfo::operator<(const CommentInfo &Other) const {
return false;
}
CommentInfo::CommentInfo(const CommentInfo &Other,
llvm::BumpPtrAllocator &Arena) {
Kind = Other.Kind;
Direction = Other.Direction;
Name = Other.Name;
ParamName = Other.ParamName;
CloseName = Other.CloseName;
SelfClosing = Other.SelfClosing;
Explicit = Other.Explicit;
Text = Other.Text;
AttrKeys = allocateArray(Other.AttrKeys, Arena);
AttrValues = allocateArray(Other.AttrValues, Arena);
Args = allocateArray(Other.Args, Arena);
if (!Other.Children.empty()) {
CommentInfo *NewArray = Arena.Allocate<CommentInfo>(Other.Children.size());
for (size_t Idx = 0; Idx < Other.Children.size(); ++Idx) {
new (NewArray + Idx) CommentInfo(Other.Children[Idx], Arena);
}
Children = llvm::ArrayRef<CommentInfo>(NewArray, Other.Children.size());
}
}
static llvm::SmallString<64>
calculateRelativeFilePath(const InfoType &Type, const StringRef &Path,
const StringRef &Name, const StringRef &CurrentPath) {
@@ -411,8 +275,6 @@ void Reference::merge(Reference &&Other) {
Name = Other.Name;
if (Path.empty())
Path = Other.Path;
if (QualName.empty())
QualName = Other.QualName;
if (DocumentationFileName.empty())
DocumentationFileName = Other.DocumentationFileName;
}
@@ -427,31 +289,6 @@ void FriendInfo::merge(FriendInfo &&Other) {
SymbolInfo::merge(std::move(Other));
}
FriendInfo::FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena)
: SymbolInfo(Other, Arena) {
Ref = Other.Ref;
if (Other.Template)
Template.emplace(*Other.Template, Arena);
if (Other.ReturnType)
ReturnType = Other.ReturnType;
if (!Other.Params.empty())
Params = allocateArray(Other.Params, Arena);
IsClass = Other.IsClass;
}
Info::Info(const Info &Other, llvm::BumpPtrAllocator &Arena)
: Path(Other.Path), Name(Other.Name),
DocumentationFileName(Other.DocumentationFileName), USR(Other.USR),
ParentUSR(Other.ParentUSR), IT(Other.IT) {
Namespace = allocateArray(Other.Namespace, Arena);
if (!Other.Description.empty()) {
for (const auto &Desc : Other.Description) {
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
Description.push_back(*NewDesc);
}
}
}
void Info::mergeBase(Info &&Other) {
assert(mergeable(Other));
if (USR == EmptySID)
@@ -460,8 +297,8 @@ void Info::mergeBase(Info &&Other) {
Name = Other.Name;
if (Path == "")
Path = Other.Path;
if (Namespace.empty() && !Other.Namespace.empty())
Namespace = allocateArray(Other.Namespace, PersistentArena);
if (Namespace.empty())
Namespace = std::move(Other.Namespace);
// Unconditionally extend the description, since each decl may have a comment.
mergeUnkeyed(Description, std::move(Other.Description));
if (ParentUSR == EmptySID)
@@ -474,17 +311,6 @@ bool Info::mergeable(const Info &Other) {
return IT == Other.IT && USR == Other.USR;
}
SymbolInfo::SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena)
: Info(Other, Arena), DefLoc(Other.DefLoc), MangledName(Other.MangledName),
IsStatic(Other.IsStatic) {
if (!Other.Loc.empty()) {
for (const auto &L : Other.Loc) {
Location *NewL = allocatePtr<Location>(Arena, L);
Loc.push_back(*NewL);
}
}
}
void SymbolInfo::merge(SymbolInfo &&Other) {
assert(mergeable(Other));
if (!DefLoc)
@@ -494,8 +320,6 @@ void SymbolInfo::merge(SymbolInfo &&Other) {
mergeBase(std::move(Other));
if (MangledName.empty())
MangledName = std::move(Other.MangledName);
if (!IsStatic)
IsStatic = Other.IsStatic;
}
NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path)
@@ -517,76 +341,37 @@ void NamespaceInfo::merge(NamespaceInfo &&Other) {
RecordInfo::RecordInfo(SymbolID USR, StringRef Name, StringRef Path)
: SymbolInfo(InfoType::IT_record, USR, Name, Path) {}
// FIXME: This constructor is currently unsafe for cross-arena copies of
// populated records. Because a default copy of ScopeChildren will shallow-copy
// the intrusive pointers, leading to a use-after-free when the TransientArena
// is reset. Subsequent patches will address this by deep-copying children
// individually via reduceChildren.
RecordInfo::RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena)
: SymbolInfo(Other, Arena), TagType(Other.TagType),
IsTypeDef(Other.IsTypeDef) {
Members = deepCopyArray(Other.Members, Arena);
Parents = allocateArray(Other.Parents, Arena);
VirtualParents = allocateArray(Other.VirtualParents, Arena);
Bases = deepCopyArray(Other.Bases, Arena);
Friends = deepCopyArray(Other.Friends, Arena);
}
MemberTypeInfo::MemberTypeInfo(const MemberTypeInfo &Other,
llvm::BumpPtrAllocator &Arena)
: FieldTypeInfo(Other), Access(Other.Access), IsStatic(Other.IsStatic) {
if (!Other.Description.empty()) {
for (const auto &Desc : Other.Description) {
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
Description.push_back(*NewDesc);
}
}
}
void RecordInfo::merge(RecordInfo &&Other) {
assert(mergeable(Other));
if (!llvm::to_underlying(TagType))
TagType = Other.TagType;
IsTypeDef = IsTypeDef || Other.IsTypeDef;
if (Members.empty() && !Other.Members.empty())
Members = deepCopyArray(Other.Members, PersistentArena);
if (Bases.empty() && !Other.Bases.empty())
Bases = deepCopyArray(Other.Bases, PersistentArena);
if (Parents.empty() && !Other.Parents.empty())
Parents = allocateArray(Other.Parents, PersistentArena);
if (VirtualParents.empty() && !Other.VirtualParents.empty())
VirtualParents = allocateArray(Other.VirtualParents, PersistentArena);
if (Friends.empty() && !Other.Friends.empty())
Friends = deepCopyArray(Other.Friends, PersistentArena);
if (Members.empty())
Members = std::move(Other.Members);
if (Bases.empty())
Bases = std::move(Other.Bases);
if (Parents.empty())
Parents = std::move(Other.Parents);
if (VirtualParents.empty())
VirtualParents = std::move(Other.VirtualParents);
if (Friends.empty())
Friends = std::move(Other.Friends);
// Reduce children if necessary.
reduceChildren(Children.Records, std::move(Other.Children.Records));
reduceChildren(Children.Functions, std::move(Other.Children.Functions));
reduceChildren(Children.Enums, std::move(Other.Children.Enums));
reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs));
SymbolInfo::merge(std::move(Other));
if (!Template && Other.Template)
Template = TemplateInfo(*Other.Template, PersistentArena);
}
EnumValueInfo::EnumValueInfo(const EnumValueInfo &Other,
llvm::BumpPtrAllocator &Arena)
: Name(Other.Name), Value(Other.Value), ValueExpr(Other.ValueExpr) {
if (!Other.Description.empty()) {
for (const auto &Desc : Other.Description) {
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
Description.push_back(*NewDesc);
}
}
if (!Template)
Template = Other.Template;
}
void EnumInfo::merge(EnumInfo &&Other) {
assert(mergeable(Other));
if (!Scoped)
Scoped = Other.Scoped;
if (!BaseType && Other.BaseType)
BaseType = std::move(Other.BaseType);
if (Members.empty() && !Other.Members.empty())
Members = deepCopyArray(Other.Members, PersistentArena);
if (Members.empty())
Members = std::move(Other.Members);
SymbolInfo::merge(std::move(Other));
}
@@ -600,11 +385,11 @@ void FunctionInfo::merge(FunctionInfo &&Other) {
ReturnType = std::move(Other.ReturnType);
if (Parent.USR == EmptySID && Parent.Name == "")
Parent = std::move(Other.Parent);
if (Params.empty() && !Other.Params.empty())
Params = allocateArray(Other.Params, PersistentArena);
if (Params.empty())
Params = std::move(Other.Params);
SymbolInfo::merge(std::move(Other));
if (!Template && Other.Template)
Template = TemplateInfo(*Other.Template, PersistentArena);
if (!Template)
Template = Other.Template;
}
void TypedefInfo::merge(TypedefInfo &&Other) {
@@ -613,8 +398,8 @@ void TypedefInfo::merge(TypedefInfo &&Other) {
IsUsing = Other.IsUsing;
if (Underlying.Type.Name == "")
Underlying = Other.Underlying;
if (!Template && Other.Template)
Template = TemplateInfo(*Other.Template, PersistentArena);
if (!Template)
Template = Other.Template;
SymbolInfo::merge(std::move(Other));
}
@@ -624,11 +409,10 @@ void ConceptInfo::merge(ConceptInfo &&Other) {
IsType = Other.IsType;
if (ConstraintExpression.empty())
ConstraintExpression = std::move(Other.ConstraintExpression);
if (Template.Constraints.empty() && !Other.Template.Constraints.empty())
Template.Constraints =
allocateArray(Other.Template.Constraints, PersistentArena);
if (Template.Params.empty() && !Other.Template.Params.empty())
Template.Params = allocateArray(Other.Template.Params, PersistentArena);
if (Template.Constraints.empty())
Template.Constraints = std::move(Other.Template.Constraints);
if (Template.Params.empty())
Template.Params = std::move(Other.Template.Params);
SymbolInfo::merge(std::move(Other));
}
@@ -643,11 +427,6 @@ void VarInfo::merge(VarInfo &&Other) {
BaseRecordInfo::BaseRecordInfo() : RecordInfo() {}
BaseRecordInfo::BaseRecordInfo(const BaseRecordInfo &Other,
llvm::BumpPtrAllocator &Arena)
: RecordInfo(Other, Arena), Access(Other.Access),
IsVirtual(Other.IsVirtual), IsParent(Other.IsParent) {}
BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path,
bool IsVirtual, AccessSpecifier Access,
bool IsParent)
@@ -705,8 +484,8 @@ bool Index::operator<(const Index &Other) const {
return Name < Other.Name;
}
std::vector<const Index *> Index::getSortedChildren() const {
std::vector<const Index *> SortedChildren;
OwningVec<const Index *> Index::getSortedChildren() const {
OwningVec<const Index *> SortedChildren;
SortedChildren.reserve(Children.size());
for (const auto &[_, C] : Children)
SortedChildren.push_back(&C);
@@ -750,12 +529,12 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
void ScopeChildren::sort() {
Namespaces.sort();
Records.sort();
Functions.sort();
Enums.sort();
Typedefs.sort();
Concepts.sort();
Variables.sort();
llvm::sort(Records);
llvm::sort(Functions);
llvm::sort(Enums);
llvm::sort(Typedefs);
llvm::sort(Concepts);
llvm::sort(Variables);
}
} // namespace doc
} // namespace clang

View File

@@ -52,7 +52,6 @@ private:
ConcurrentStringPool &getGlobalStringPool();
extern thread_local llvm::BumpPtrAllocator TransientArena;
extern thread_local llvm::BumpPtrAllocator PersistentArena;
inline StringRef internString(const Twine &T) {
if (T.isTriviallyEmpty())
@@ -73,8 +72,8 @@ inline StringRef internString(const Twine &T) {
}
template <typename T>
llvm::ArrayRef<T> allocateArray(llvm::SmallVectorImpl<T> &V,
llvm::BumpPtrAllocator &Alloc) {
inline 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());
@@ -82,31 +81,9 @@ llvm::ArrayRef<T> allocateArray(llvm::SmallVectorImpl<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());
}
template <typename T>
llvm::ArrayRef<T> deepCopyArray(llvm::ArrayRef<T> V,
llvm::BumpPtrAllocator &Alloc) {
if (V.empty())
return llvm::ArrayRef<T>();
T *Allocated = (T *)Alloc.Allocate<T>(V.size());
for (size_t Idx = 0; Idx < V.size(); ++Idx) {
new (Allocated + Idx) T(V[Idx], Alloc);
}
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 = T *;
template <typename T> using OwnedPtr = std::unique_ptr<T>;
// An abstraction for vectors that are populated and read sequentially.
// To be eventually transitioned to llvm::ArrayRef for arena storage.
@@ -114,7 +91,7 @@ template <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 = llvm::simple_ilist<T>;
template <typename T> using OwningVec = std::vector<T>;
// An abstraction for dynamic lists of owned pointers.
// To be eventually transitioned to llvm::simple_ilist<T*> or similar.
@@ -128,10 +105,9 @@ template <typename T> using OwningPtrArray = std::vector<OwnedPtr<T>>;
// allocation mechanism.
template <typename T, typename... Args>
OwnedPtr<T> allocatePtr(Args &&...args) {
return new (TransientArena.Allocate<T>()) T(std::forward<Args>(args)...);
return std::make_unique<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)...);
@@ -139,7 +115,7 @@ T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
// A helper function to access the underlying pointer from an owned pointer,
// abstracting away the pointer dereferencing mechanism.
template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O; }
template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O.get(); }
// SHA1'd hash of a USR.
using SymbolID = std::array<uint8_t, 20>;
@@ -193,7 +169,6 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
CommentInfo() = default;
CommentInfo(const CommentInfo &Other) = default;
CommentInfo &operator=(const CommentInfo &Other) = default;
CommentInfo(const CommentInfo &Other, llvm::BumpPtrAllocator &Arena);
CommentInfo(CommentInfo &&Other) = default;
CommentInfo &operator=(CommentInfo &&Other) = default;
@@ -219,11 +194,11 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
llvm::ArrayRef<CommentInfo>
Children; // List of child comments for this CommentInfo.
StringRef Direction = {}; // Parameter direction (for (T)ParamCommand).
StringRef Name = {}; // Name of the comment (for Verbatim and HTML).
StringRef ParamName = {}; // Parameter name (for (T)ParamCommand).
StringRef CloseName = {}; // Closing tag name (for VerbatimBlock).
StringRef Text = {}; // Text of the comment.
StringRef Direction; // Parameter direction (for (T)ParamCommand).
StringRef Name; // Name of the comment (for Verbatim and HTML).
StringRef ParamName; // Parameter name (for (T)ParamCommand).
StringRef CloseName; // Closing tag name (for VerbatimBlock).
StringRef Text; // Text of the comment.
llvm::ArrayRef<StringRef> AttrKeys; // List of attribute keys (for HTML).
llvm::ArrayRef<StringRef>
AttrValues; // List of attribute values for each key (for HTML).
@@ -285,17 +260,17 @@ struct Reference : public llvm::ilist_node<Reference> {
// Name of type (possibly unresolved). Not including namespaces or template
// parameters (so for a std::vector<int> this would be "vector"). See also
// QualName.
StringRef Name = {};
StringRef Name;
// Full qualified name of this type, including namespaces and template
// parameter (for example this could be "std::vector<int>"). Contrast to
// Name.
StringRef QualName = {};
StringRef QualName;
// Path of directory where the clang-doc generated file will be saved
// (possibly unresolved)
StringRef Path = {};
StringRef DocumentationFileName = {};
StringRef Path;
StringRef DocumentationFileName;
};
// A Context is a reference that holds a relative path from a certain Info's
@@ -305,7 +280,7 @@ struct Context : public Reference {
StringRef Path, StringRef DocumentationFileName)
: Reference(USR, Name, IT, QualName, Path, DocumentationFileName) {}
explicit Context(const Info &I);
StringRef RelativePath = {};
StringRef RelativePath;
};
// Holds the children of a record or namespace.
@@ -317,7 +292,7 @@ struct ScopeChildren {
//
// Namespaces are not syntactically valid as children of records, but making
// this general for all possible container types reduces code complexity.
OwningVec<Reference> Namespaces;
llvm::simple_ilist<Reference> Namespaces;
OwningVec<Reference> Records;
OwningVec<FunctionInfo> Functions;
OwningVec<EnumInfo> Enums;
@@ -359,19 +334,15 @@ struct TemplateParamInfo {
// The literal contents of the code for that specifies this template parameter
// for this declaration. Typical values will be "class T" and
// "typename T = int".
StringRef Contents = {};
StringRef Contents;
};
struct TemplateSpecializationInfo {
TemplateSpecializationInfo() = default;
TemplateSpecializationInfo(const TemplateSpecializationInfo &Other,
llvm::BumpPtrAllocator &Arena);
// Indicates the declaration that this specializes.
SymbolID SpecializationOf;
// Template parameters applying to the specialized record/function.
llvm::ArrayRef<TemplateParamInfo> Params;
OwningVec<TemplateParamInfo> Params;
};
struct ConstraintInfo {
@@ -380,21 +351,18 @@ struct ConstraintInfo {
: ConceptRef(USR, Name, InfoType::IT_concept) {}
Reference ConceptRef;
StringRef ConstraintExpr = {};
StringRef ConstraintExpr;
};
// Records the template information for a struct or function that is a template
// or an explicit template specialization.
struct TemplateInfo {
TemplateInfo() = default;
TemplateInfo(const TemplateInfo &Other, llvm::BumpPtrAllocator &Arena);
// May be empty for non-partial specializations.
llvm::ArrayRef<TemplateParamInfo> Params;
OwningVec<TemplateParamInfo> Params;
// Set when this is a specialization of another record/function.
std::optional<TemplateSpecializationInfo> Specialization;
llvm::ArrayRef<ConstraintInfo> Constraints;
OwningVec<ConstraintInfo> Constraints;
};
// Info for field types.
@@ -410,27 +378,24 @@ struct FieldTypeInfo : public TypeInfo {
std::tie(Other.Type, Other.Name, Other.DefaultValue);
}
StringRef Name = {}; // Name associated with this info.
StringRef Name; // Name associated with this info.
// When used for function parameters, contains the string representing the
// expression of the default value, if any.
StringRef DefaultValue = {};
StringRef DefaultValue;
};
// Info for member types.
struct MemberTypeInfo : public FieldTypeInfo {
MemberTypeInfo() = default;
MemberTypeInfo(const MemberTypeInfo &Other, llvm::BumpPtrAllocator &Arena);
MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access,
bool IsStatic = false)
: FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {}
bool operator==(const MemberTypeInfo &Other) const {
if (std::tie(Type, Name, Access, IsStatic) !=
std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic))
return false;
return std::equal(Description.begin(), Description.end(),
Other.Description.begin(), Other.Description.end());
return std::tie(Type, Name, Access, IsStatic, Description) ==
std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic,
Other.Description);
}
OwningVec<CommentInfo> Description;
@@ -465,7 +430,7 @@ struct Location : public llvm::ilist_node<Location> {
std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename);
}
StringRef Filename = {};
StringRef Filename;
int StartLineNumber = 0;
int EndLineNumber = 0;
bool IsFileInRootDir = false;
@@ -477,9 +442,9 @@ struct Info {
StringRef Name = StringRef(), StringRef Path = StringRef())
: Path(internString(Path)), Name(internString(Name)), USR(USR), IT(IT) {}
Info(const Info &Other, llvm::BumpPtrAllocator &Arena);
Info(const Info &Other) = delete;
Info(Info &&Other) = default;
virtual ~Info() = default;
Info &operator=(Info &&Other) = default;
@@ -495,18 +460,18 @@ struct Info {
StringRef getFileBaseName() const;
// Path of directory where the clang-doc generated file will be saved.
StringRef Path = {};
StringRef Path;
// Unqualified name of the decl.
StringRef Name = {};
StringRef Name;
// The name used for the file that this info is documented in.
// In the JSON generator, infos are documented in files with mangled names.
// Thus, we keep track of the physical filename for linking purposes.
StringRef DocumentationFileName = {};
StringRef DocumentationFileName;
// List of parent namespaces for this decl.
llvm::ArrayRef<Reference> Namespace;
llvm::SmallVector<Reference, 4> Namespace;
// Unique identifier for the decl described by this Info.
SymbolID USR = SymbolID();
@@ -519,6 +484,8 @@ struct Info {
// Comment description of this decl.
OwningVec<CommentInfo> Description;
SmallVector<Context, 4> Contexts;
};
inline Context::Context(const Info &I)
@@ -540,8 +507,6 @@ struct SymbolInfo : public Info {
StringRef Name = StringRef(), StringRef Path = StringRef())
: Info(IT, USR, Name, Path) {}
SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena);
void merge(SymbolInfo &&I);
bool operator<(const SymbolInfo &Other) const {
@@ -549,9 +514,8 @@ struct SymbolInfo : public Info {
// generated in the order of the source code.
// If the declaration location is the same, or not present
// we sort by defined location otherwise fallback to the extracted name
if (Loc.size() > 0 && Other.Loc.size() > 0 &&
Loc.front() != Other.Loc.front())
return Loc.front() < Other.Loc.front();
if (Loc.size() > 0 && Other.Loc.size() > 0 && Loc[0] != Other.Loc[0])
return Loc[0] < Other.Loc[0];
if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc)
return *DefLoc < *Other.DefLoc;
@@ -560,8 +524,8 @@ struct SymbolInfo : public Info {
}
std::optional<Location> DefLoc; // Location where this decl is defined.
OwningVec<Location> Loc; // Locations where this decl is declared.
StringRef MangledName = {};
llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
StringRef MangledName;
bool IsStatic = false;
};
@@ -571,7 +535,6 @@ struct FriendInfo : public SymbolInfo, public llvm::ilist_node<FriendInfo> {
FriendInfo(const InfoType IT, const SymbolID &USR,
const StringRef Name = StringRef())
: SymbolInfo(IT, USR, Name) {}
FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena);
bool mergeable(const FriendInfo &Other);
void merge(FriendInfo &&Other);
@@ -601,8 +564,8 @@ struct FunctionInfo : public SymbolInfo, public llvm::ilist_node<FunctionInfo> {
Reference Parent;
TypeInfo ReturnType;
llvm::ArrayRef<FieldTypeInfo> Params;
StringRef Prototype = {};
llvm::SmallVector<FieldTypeInfo, 4> Params;
StringRef Prototype;
// When present, this function is a template or specialization.
std::optional<TemplateInfo> Template;
@@ -623,8 +586,6 @@ struct RecordInfo : public SymbolInfo {
RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),
StringRef Path = StringRef());
RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena);
void merge(RecordInfo &&I);
// Type of this record (struct, class, union, interface).
@@ -639,18 +600,18 @@ struct RecordInfo : public SymbolInfo {
// When present, this record is a template or specialization.
std::optional<TemplateInfo> Template;
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>
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>
VirtualParents; // List of virtual base/parent records.
llvm::ArrayRef<BaseRecordInfo>
Bases; // List of base/parent records; this includes
// inherited methods and attributes
OwningVec<BaseRecordInfo> Bases; // List of base/parent records; this includes
// inherited methods and attributes
llvm::ArrayRef<FriendInfo> Friends;
OwningVec<FriendInfo> Friends;
ScopeChildren Children;
};
@@ -668,7 +629,7 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node<TypedefInfo> {
std::optional<TemplateInfo> Template;
// Underlying type declaration
StringRef TypeDeclaration = {};
StringRef TypeDeclaration;
// Indicates if this is a new C++ "using"-style typedef:
// using MyVector = std::vector<int>
@@ -677,10 +638,8 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node<TypedefInfo> {
bool IsUsing = false;
};
struct BaseRecordInfo : public RecordInfo,
public llvm::ilist_node<BaseRecordInfo> {
struct BaseRecordInfo : public RecordInfo {
BaseRecordInfo();
BaseRecordInfo(const BaseRecordInfo &Other, llvm::BumpPtrAllocator &Arena);
BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,
AccessSpecifier Access, bool IsParent);
@@ -700,8 +659,6 @@ struct EnumValueInfo {
: Name(internString(Name)), Value(internString(Value)),
ValueExpr(internString(ValueExpr)) {}
EnumValueInfo(const EnumValueInfo &Other, llvm::BumpPtrAllocator &Arena);
bool operator==(const EnumValueInfo &Other) const {
return std::tie(Name, Value, ValueExpr) ==
std::tie(Other.Name, Other.Value, Other.ValueExpr);
@@ -738,7 +695,7 @@ struct EnumInfo : public SymbolInfo, public llvm::ilist_node<EnumInfo> {
// this will be "short".
std::optional<TypeInfo> BaseType;
llvm::ArrayRef<EnumValueInfo> Members; // List of enum members.
llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members.
};
struct ConceptInfo : public SymbolInfo, public llvm::ilist_node<ConceptInfo> {
@@ -747,9 +704,9 @@ struct ConceptInfo : public SymbolInfo, public llvm::ilist_node<ConceptInfo> {
void merge(ConceptInfo &&I);
bool IsType = false;
bool IsType;
TemplateInfo Template;
StringRef ConstraintExpression = {};
StringRef ConstraintExpression;
};
struct Index : public Reference {
@@ -766,7 +723,7 @@ struct Index : public Reference {
std::optional<StringRef> JumpToSection;
llvm::StringMap<Index> Children;
std::vector<const Index *> getSortedChildren() const;
OwningVec<const Index *> getSortedChildren() const;
void sort();
};
@@ -777,12 +734,6 @@ struct Index : public Reference {
// if they are different.
llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values);
// Merges a single new Info into an existing Reduced Info (allocating it if
// needed).
llvm::Error mergeSingleInfo(doc::OwnedPtr<doc::Info> &Reduced,
doc::OwnedPtr<doc::Info> &&NewInfo,
llvm::BumpPtrAllocator &Arena);
struct ClangDocContext {
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
@@ -822,26 +773,28 @@ struct ClangDocContext {
// Ensure arena allocated types remain safe to allocate in the arena.
// Only trivially destructible types are safe, so enforce that at compile-time.
static_assert(std::is_trivially_destructible_v<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>);
static_assert(std::is_trivially_destructible_v<TypedefInfo>);
static_assert(std::is_trivially_destructible_v<VarInfo>);
// 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>);
} // namespace doc
} // namespace clang

View File

@@ -182,8 +182,8 @@ StringRef Serializer::getTypeAlias(const TypeAliasDecl *Alias) {
//
// }
// }
StringRef
Serializer::getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces) {
StringRef Serializer::getInfoRelativePath(
const llvm::SmallVectorImpl<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,7 +258,9 @@ void ClangDocCommentVisitor::visitInlineCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
CurrentCI.Args = allocateArray(Args, TransientArena);
StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
}
}
@@ -274,10 +276,16 @@ void ClangDocCommentVisitor::visitHTMLStartTagComment(
AttrValues.push_back(internString(Attr.Value));
}
if (!AttrKeys.empty()) {
CurrentCI.AttrKeys = allocateArray(AttrKeys, TransientArena);
StringRef *KeysMem = TransientArena.Allocate<StringRef>(AttrKeys.size());
std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
CurrentCI.AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
}
if (!AttrValues.empty()) {
CurrentCI.AttrValues = allocateArray(AttrValues, TransientArena);
StringRef *ValuesMem =
TransientArena.Allocate<StringRef>(AttrValues.size());
std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), ValuesMem);
CurrentCI.AttrValues =
llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
}
}
@@ -294,7 +302,9 @@ void ClangDocCommentVisitor::visitBlockCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
CurrentCI.Args = allocateArray(Args, TransientArena);
StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
}
}
@@ -465,35 +475,29 @@ void Serializer::InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
}
void Serializer::InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
Reference *R = allocatePtr<Reference>(
Info.USR, Info.Name, InfoType::IT_record, Info.Name,
getInfoRelativePath(Info.Namespace), Info.MangledName);
Scope.Records.push_back(*R);
Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
Info.Name, getInfoRelativePath(Info.Namespace),
Info.MangledName);
}
void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
EnumInfo *E = allocatePtr<EnumInfo>(std::move(Info));
Scope.Enums.push_back(*E);
Scope.Enums.push_back(std::move(Info));
}
void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
FunctionInfo *F = allocatePtr<FunctionInfo>(std::move(Info));
Scope.Functions.push_back(*F);
Scope.Functions.push_back(std::move(Info));
}
void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
TypedefInfo *T = allocatePtr<TypedefInfo>(std::move(Info));
Scope.Typedefs.push_back(*T);
Scope.Typedefs.push_back(std::move(Info));
}
void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
ConceptInfo *C = allocatePtr<ConceptInfo>(std::move(Info));
Scope.Concepts.push_back(*C);
Scope.Concepts.push_back(std::move(Info));
}
void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
VarInfo *V = allocatePtr<VarInfo>(std::move(Info));
Scope.Variables.push_back(*V);
Scope.Variables.push_back(std::move(Info));
}
// Creates a parent of the correct type for the given child and inserts it into
@@ -577,18 +581,14 @@ AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
// record, the access specification of the field depends on the inheritance mode
void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
bool PublicOnly, AccessSpecifier Access) {
SmallVector<MemberTypeInfo, 4> Members;
for (const FieldDecl *F : D->fields()) {
if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
continue;
populateMemberTypeInfo(Members, Access, F);
populateMemberTypeInfo(I, Access, F);
}
const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
if (!CxxRD) {
if (!Members.empty())
I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
if (!CxxRD)
return;
}
for (Decl *CxxDecl : CxxRD->decls()) {
auto *VD = dyn_cast<VarDecl>(CxxDecl);
if (!VD ||
@@ -596,49 +596,40 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
continue;
if (VD->isStaticDataMember())
populateMemberTypeInfo(Members, Access, VD, /*IsStatic=*/true);
populateMemberTypeInfo(I, Access, VD, /*IsStatic=*/true);
}
if (!Members.empty())
I.Members = allocateArray<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);
EnumValueInfo &Member = LocalMembers.emplace_back(
E->getNameAsString(), ValueStr.str(), ValueExpr);
I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
ASTContext &Context = E->getASTContext();
if (RawComment *Comment =
E->getASTContext().getRawCommentForDeclNoCache(E)) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
CommentInfo *NewCI = allocatePtr<CommentInfo>();
Member.Description.push_back(*NewCI);
EnumValueInfo &Member = I.Members.back();
Member.Description.emplace_back();
parseFullComment(Fc, Member.Description.back());
}
}
}
if (!LocalMembers.empty())
I.Members = allocateArray<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 = LocalParams.emplace_back(
FieldTypeInfo &FieldInfo = I.Params.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
@@ -648,36 +639,28 @@ 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();
LocalParents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
InfoType::IT_record, B.getType().getAsString());
I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
InfoType::IT_record, B.getType().getAsString());
} else if (const RecordDecl *P = getRecordDeclForType(B.getType()))
LocalParents.emplace_back(
getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
InfoType::IT_record, P->getQualifiedNameAsString(),
internString(getInfoRelativePath(P)));
else
LocalParents.emplace_back(SymbolID(), B.getType().getAsString());
I.Parents.emplace_back(SymbolID(), B.getType().getAsString());
}
if (!LocalParents.empty())
I.Parents = allocateArray<Reference>(LocalParents, TransientArena);
llvm::SmallVector<Reference, 4> LocalVirtualParents;
for (const CXXBaseSpecifier &B : D->vbases()) {
if (const RecordDecl *P = getRecordDeclForType(B.getType()))
LocalVirtualParents.emplace_back(
I.VirtualParents.emplace_back(
getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
else
LocalVirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
I.VirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
}
if (!LocalVirtualParents.empty())
I.VirtualParents =
allocateArray<Reference>(LocalVirtualParents, TransientArena);
}
template <typename T>
@@ -725,13 +708,10 @@ void Serializer::populateTemplateParameters(
if (!TemplateInfo) {
TemplateInfo.emplace();
}
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const NamedDecl *ND : *ParamList) {
LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange()));
TemplateInfo->Params.emplace_back(
getSourceCode(ND, ND->getSourceRange()));
}
if (!LocalParams.empty())
TemplateInfo->Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
@@ -794,14 +774,9 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C,
ConversionDecl->getConversionType().getAsString());
else
I.Name = internString(D->getNameAsString());
llvm::SmallVector<Reference, 4> LocalNamespaces;
populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
if (!LocalNamespaces.empty())
I.Namespace = allocateArray<Reference>(LocalNamespaces, TransientArena);
populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
if (C) {
CommentInfo *NewCI = allocatePtr<CommentInfo>();
I.Description.push_back(*NewCI);
I.Description.emplace_back();
parseFullComment(C, I.Description.back());
}
}
@@ -813,10 +788,8 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
populateInfo(I, D, C, IsInAnonymousNamespace);
if (D->isThisDeclarationADefinition())
I.DefLoc = Loc;
else {
Location *NewL = allocatePtr<Location>(Loc);
I.Loc.push_back(*NewL);
}
else
I.Loc.emplace_back(Loc);
auto *Mangler = ItaniumMangleContext::create(
D->getASTContext(), D->getASTContext().getDiagnostics());
@@ -838,8 +811,7 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
}
void Serializer::handleCompoundConstraints(
const Expr *Constraint,
llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
const Expr *Constraint, OwningVec<ConstraintInfo> &ConstraintInfos) {
if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
ConstraintInfos);
@@ -863,7 +835,6 @@ 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;
@@ -875,14 +846,11 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
ConstraintExpr->getNamedConcept()->getNameAsString());
CI.ConstraintExpr = internString(exprToString(ConstraintExpr));
LocalConstraints.push_back(std::move(CI));
I.Constraints.push_back(std::move(CI));
} else {
handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
}
}
if (!LocalConstraints.empty())
I.Constraints =
allocateArray<ConstraintInfo>(LocalConstraints, TransientArena);
}
void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
@@ -911,13 +879,9 @@ void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
// Template parameters to the specialization.
if (FTSI->TemplateArguments) {
SmallVector<TemplateParamInfo, 4> LocalParams;
for (const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
}
if (!LocalParams.empty())
Specialization.Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
}
@@ -937,28 +901,26 @@ void Serializer::populateMemberTypeInfo(T &I, const Decl *D) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
CommentInfo *NewCI = allocatePtr<CommentInfo>();
I.Description.push_back(*NewCI);
I.Description.emplace_back();
parseFullComment(Fc, I.Description.back());
}
}
void Serializer::populateMemberTypeInfo(
SmallVectorImpl<MemberTypeInfo> &Members, AccessSpecifier &Access,
const DeclaratorDecl *D, bool IsStatic) {
void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
const DeclaratorDecl *D,
bool IsStatic) {
// Use getAccessUnsafe so that we just get the default AS_none if it's not
// valid, as opposed to an assert.
MemberTypeInfo &NewMember = Members.emplace_back(
MemberTypeInfo &NewMember = I.Members.emplace_back(
getTypeInfoForType(D->getTypeSourceInfo()->getType(), D->getLangOpts()),
D->getNameAsString(),
getFinalAccessSpecifier(Access, D->getAccessUnsafe()), IsStatic);
populateMemberTypeInfo(NewMember, D);
}
void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
const CXXRecordDecl *D, bool IsFileInRootDir,
bool PublicOnly, bool IsParent,
AccessSpecifier ParentAccess) {
void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D,
bool IsFileInRootDir, bool PublicOnly,
bool IsParent, AccessSpecifier ParentAccess) {
// Don't parse bases if this isn't a definition.
if (!D->isThisDeclarationADefinition())
return;
@@ -997,15 +959,14 @@ void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
IsInAnonymousNamespace);
FI.Access =
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
FunctionInfo *FIPtr = allocatePtr<FunctionInfo>(std::move(FI));
BI.Children.Functions.push_back(*FIPtr);
BI.Children.Functions.emplace_back(std::move(FI));
}
Bases.emplace_back(std::move(BI));
I.Bases.emplace_back(std::move(BI));
// Call this function recursively to get the inherited classes of
// this base; these new bases will also get stored in the original
// RecordInfo: I.
parseBases(Bases, Base, IsFileInRootDir, PublicOnly, false,
Bases.back().Access);
parseBases(I, Base, IsFileInRootDir, PublicOnly, false,
I.Bases.back().Access);
}
}
}
@@ -1034,8 +995,6 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
if (!D->hasDefinition() || !D->hasFriends())
return;
llvm::SmallVector<FriendInfo, 4> LocalFriends;
for (const FriendDecl *FD : D->friends()) {
if (FD->isUnsupportedFriend())
continue;
@@ -1057,12 +1016,9 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
F.IsClass = true;
F.Template.emplace();
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const auto *Param : ActualTD->getTemplateParameters()->asArray())
LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
if (!LocalParams.empty())
F.Template->Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
F.Template->Params.emplace_back(
getSourceCode(Param, Param->getSourceRange()));
ActualDecl = ActualTD->getTemplatedDecl();
}
@@ -1080,10 +1036,8 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
getInfoRelativePath(ActualDecl));
populateMemberTypeInfo(F, ActualDecl);
LocalFriends.push_back(std::move(F));
RI.Friends.push_back(std::move(F));
}
if (!LocalFriends.empty())
RI.Friends = allocateArray<FriendInfo>(LocalFriends, TransientArena);
}
std::pair<OwnedPtr<Info>, OwnedPtr<Info>>
@@ -1107,11 +1061,7 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
}
// TODO: remove first call to parseBases, that function should be deleted
parseBases(*RI, C);
llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
parseBases(LocalBases, C, /*IsFileInRootDir=*/true, PublicOnly,
/*IsParent=*/true);
if (!LocalBases.empty())
RI->Bases = allocateArray<BaseRecordInfo>(LocalBases, TransientArena);
parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true);
parseFriends(*RI, C);
}
RI->Path = internString(getInfoRelativePath(RI->Namespace));
@@ -1144,23 +1094,15 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
if (const ASTTemplateArgumentListInfo *AsWritten =
CTPSD->getTemplateArgsAsWritten()) {
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
LocalParams.emplace_back(
Specialization.Params.emplace_back(
getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
}
if (!LocalParams.empty())
Specialization.Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
} else {
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
}
if (!LocalParams.empty())
Specialization.Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
}
@@ -1222,9 +1164,8 @@ void Serializer::extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
CommentInfo *NewCI = allocatePtr<CommentInfo>();
Info.Description.push_back(*NewCI);
parseFullComment(Fc, *NewCI);
Info.Description.emplace_back();
parseFullComment(Fc, Info.Description.back());
}
}
@@ -1317,13 +1258,10 @@ Serializer::emitInfo(const ConceptDecl *D, const FullComment *FC,
Concept.ConstraintExpression = exprToString(D->getConstraintExpr());
if (auto *ConceptParams = D->getTemplateParameters()) {
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
for (const auto *Param : ConceptParams->asArray()) {
LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
Concept.Template.Params.emplace_back(
getSourceCode(Param, Param->getSourceRange()));
}
if (!LocalParams.empty())
Concept.Template.Params =
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
}
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))

View File

@@ -94,7 +94,8 @@ private:
StringRef getTypeAlias(const TypeAliasDecl *Alias);
StringRef getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces);
StringRef
getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces);
StringRef getInfoRelativePath(const Decl *D);
@@ -138,9 +139,8 @@ private:
void parseBases(RecordInfo &I, const CXXRecordDecl *D);
void parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
const CXXRecordDecl *D, bool IsFileInRootDir, bool PublicOnly,
bool IsParent,
void parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
bool PublicOnly, bool IsParent,
AccessSpecifier ParentAccess = AccessSpecifier::AS_public);
template <typename T>
@@ -165,9 +165,8 @@ private:
void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
Location Loc, bool &IsInAnonymousNamespace);
void handleCompoundConstraints(
const Expr *Constraint,
llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos);
void handleCompoundConstraints(const Expr *Constraint,
OwningVec<ConstraintInfo> &ConstraintInfos);
void populateConstraints(TemplateInfo &I, const TemplateDecl *D);
@@ -177,9 +176,8 @@ private:
template <typename T> void populateMemberTypeInfo(T &I, const Decl *D);
void populateMemberTypeInfo(llvm::SmallVectorImpl<MemberTypeInfo> &Members,
AccessSpecifier &Access, const DeclaratorDecl *D,
bool IsStatic = false);
void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
const DeclaratorDecl *D, bool IsStatic = false);
void parseFriends(RecordInfo &RI, const CXXRecordDecl *D);

View File

@@ -31,70 +31,9 @@ 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 {
// 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>> {
template <typename T> struct SequenceTraits<llvm::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]);
@@ -252,7 +191,7 @@ static void infoMapping(IO &IO, Info &I) {
static void symbolInfoMapping(IO &IO, SymbolInfo &I) {
infoMapping(IO, I);
IO.mapOptional("DefLocation", I.DefLoc, std::optional<Location>());
IO.mapOptional("Location", I.Loc);
IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
}
static void recordInfoMapping(IO &IO, RecordInfo &I) {
@@ -261,10 +200,10 @@ static void recordInfoMapping(IO &IO, RecordInfo &I) {
IO.mapOptional("IsTypeDef", I.IsTypeDef, false);
IO.mapOptional("Members", I.Members);
IO.mapOptional("Bases", I.Bases);
IO.mapOptional("Parents", I.Parents, SmallVector<Reference, 4>());
IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
IO.mapOptional("VirtualParents", I.VirtualParents,
llvm::SmallVector<Reference, 4>());
IO.mapOptional("ChildRecords", I.Children.Records);
IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
IO.mapOptional("ChildFunctions", I.Children.Functions);
IO.mapOptional("ChildEnums", I.Children.Enums);
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
@@ -400,7 +339,7 @@ template <> struct MappingTraits<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);
IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
IO.mapOptional("ChildFunctions", I.Children.Functions);
IO.mapOptional("ChildEnums", I.Children.Enums);
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
@@ -502,6 +441,13 @@ template <> struct MappingTraits<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

View File

@@ -184,10 +184,9 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
auto NI = allocatePtr<NamespaceInfo>();
NI->Name = "GlobalNamespace";
for (int i = 0; i < NumRecords; ++i) {
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);
NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)},
"Record" + std::to_string(i),
InfoType::IT_record);
}
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());

View File

@@ -29,7 +29,6 @@
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Execution.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -359,22 +358,15 @@ Example usage for a project using a compile commands database:
llvm::hardware_concurrency(ExecutorConcurrency));
{
llvm::TimeTraceScope TS("Reduce");
for (const auto &Group : USRToBitcode) {
StringRef Key = Group.getKey();
std::vector<StringRef> Bitcodes = Group.getValue();
Pool.async([Key, Bitcodes, &CDCtx, &Diags, &USRToInfo, &USRToInfoMutex,
&IndexMutex, &DiagMutex, &Error, DiagIDBitcodeReading,
DiagIDBitcodeMerging]() {
if (CDCtx.FTimeTrace)
for (auto &Group : USRToBitcode) {
Pool.async([&, &Diags = Diags]() { // time trace decoding bitcode
if (FTimeTrace)
llvm::timeTraceProfilerInitialize(200, "clang-doc");
doc::OwnedPtr<doc::Info> Reduced = nullptr;
doc::OwningPtrVec<doc::Info> Infos;
{
llvm::TimeTraceScope Red("decoding and merging bitcode");
for (const auto &Bitcode : Bitcodes) {
llvm::scope_exit ArenaGuard(
[] { clang::doc::TransientArena.Reset(); });
llvm::TimeTraceScope Red("decoding bitcode");
for (auto &Bitcode : Group.getValue()) {
llvm::BitstreamCursor Stream(Bitcode);
doc::ClangDocBitcodeReader Reader(Stream, Diags);
auto ReadInfos = Reader.readBitcode();
@@ -386,17 +378,25 @@ Example usage for a project using a compile commands database:
Error = true;
return;
}
for (auto &I : *ReadInfos) {
if (auto Err = doc::mergeSingleInfo(
Reduced, std::move(I), clang::doc::PersistentArena)) {
std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex);
Diags.Report(DiagIDBitcodeMerging)
<< toString(std::move(Err));
return;
}
}
std::move(ReadInfos->begin(), ReadInfos->end(),
std::back_inserter(Infos));
}
} // time trace decoding and merging bitcode
} // time trace decoding bitcode
doc::OwnedPtr<doc::Info> Reduced;
{
llvm::TimeTraceScope Merge("merging bitcode");
auto ExpReduced = doc::mergeInfos(Infos);
if (!ExpReduced) {
std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex);
Diags.Report(DiagIDBitcodeMerging)
<< toString(ExpReduced.takeError());
return;
}
Reduced = std::move(*ExpReduced);
} // time trace merging bitcode
// Add a reference to this Info in the Index
{
@@ -408,7 +408,7 @@ Example usage for a project using a compile commands database:
{
llvm::TimeTraceScope Merge("USRToInfo");
std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
USRToInfo[Key] = std::move(Reduced);
USRToInfo[Group.getKey()] = std::move(Reduced);
}
if (CDCtx.FTimeTrace)

View File

@@ -56,6 +56,7 @@ 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);
@@ -67,43 +68,39 @@ class BitcodeTest : public ClangDocContextTest {};
TEST_F(BitcodeTest, emitNamespaceInfoBitcode) {
NamespaceInfo I;
I.Name = "r";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
I.Children.Namespaces.push_back(NewNamespace);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Records.push_back(ChildStruct);
FunctionInfo FI;
I.Children.Functions.push_back(FI);
EnumInfo EI;
I.Children.Enums.push_back(EI);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Functions.emplace_back();
I.Children.Enums.emplace_back();
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0]));
CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitRecordInfoBitcode) {
RecordInfo I;
I.Name = "r";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.TagType = TagTypeKind::Class;
I.IsTypeDef = true;
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
true);
FunctionInfo FI;
B.Children.Functions.push_back(FI);
MemberTypeInfo BM(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_public, true);
I.Bases.back().Children.Functions.emplace_back();
I.Bases.back().Members.emplace_back(TypeInfo("int"), "X",
AccessSpecifier::AS_private);
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
// Documentation for the data member.
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
@@ -112,47 +109,29 @@ TEST_F(BitcodeTest, emitRecordInfoBitcode) {
CommentInfo TopCommentChildren[] = {
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
BM.Description.push_back(TopComment);
MemberTypeInfo BMem[] = {std::move(BM)};
B.Members = llvm::ArrayRef(BMem);
BaseRecordInfo Bases[] = {std::move(B)};
I.Bases = llvm::ArrayRef(Bases);
I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment));
MemberTypeInfo Mem[] = {std::move(M)};
I.Members = llvm::ArrayRef(Mem);
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)};
I.Parents = llvm::ArrayRef(Parents);
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)};
I.VirtualParents = llvm::ArrayRef(VParents);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Records.push_back(ChildStruct);
FunctionInfo FI2;
I.Children.Functions.push_back(FI2);
EnumInfo EI;
I.Children.Enums.push_back(EI);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Functions.emplace_back();
I.Children.Enums.emplace_back();
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckRecordInfo(&I, InfoAsRecord(ReadResults[0]));
CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
FunctionInfo I;
I.Name = "f";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
I.ReturnType = TypeInfo("void");
FieldTypeInfo P(TypeInfo("int"), "P");
FieldTypeInfo Params[] = {std::move(P)};
I.Params = llvm::ArrayRef(Params);
I.Params.emplace_back(TypeInfo("int"), "P");
I.Access = AccessSpecifier::AS_none;
@@ -160,23 +139,19 @@ TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitMethodInfoBitcode) {
FunctionInfo I;
I.Name = "f";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
I.ReturnType = TypeInfo("void");
FieldTypeInfo P(TypeInfo("int"), "P");
FieldTypeInfo Params[] = {std::move(P)};
I.Params = llvm::ArrayRef(Params);
I.Params.emplace_back(TypeInfo("int"), "P");
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -186,36 +161,31 @@ TEST_F(BitcodeTest, emitMethodInfoBitcode) {
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitEnumInfoBitcode) {
EnumInfo I;
I.Name = "e";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
EnumValueInfo EV("X");
EnumValueInfo Mems[] = {std::move(EV)};
I.Members = llvm::ArrayRef(Mems);
I.Members.emplace_back("X");
I.Scoped = true;
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckEnumInfo(&I, InfoAsEnum(ReadResults[0]));
CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
TypedefInfo I;
I.Name = "MyInt";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
I.Underlying = TypeInfo("unsigned");
@@ -226,13 +196,13 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
I.Description.push_back(Top);
I.Description.emplace_back(std::move(Top));
std::string WriteResult = writeInfo(&I, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0]));
CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0].get()));
// Check one with no IsUsing set, no description, and no definition location.
TypedefInfo I2;
@@ -243,7 +213,7 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
WriteResult = writeInfo(&I2, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0]));
CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0].get()));
}
TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
@@ -251,8 +221,7 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
F.Name = "F";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I")};
F.Params = llvm::ArrayRef(PI);
F.Params.emplace_back(TypeInfo("int"), "I");
// BlankLine
CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
@@ -324,13 +293,13 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
Verbatim, ParamOut, ParamIn, Return};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
F.Description.push_back(Top);
F.Description.emplace_back(std::move(Top));
std::string WriteResult = writeInfo(&F, this->Diags);
EXPECT_TRUE(WriteResult.size() > 0);
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0]));
CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get()));
}
} // namespace doc

View File

@@ -54,10 +54,10 @@ TypedefInfo *InfoAsTypedef(Info *I) {
return static_cast<TypedefInfo *>(I);
}
void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
ArrayRef<CommentInfo> Actual);
void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
const OwningVec<CommentInfo> &Actual);
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(const CommentInfo &Expected, const CommentInfo &Actual) {
EXPECT_EQ(Expected.Kind, Actual.Kind);
@@ -84,71 +84,52 @@ void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
CheckCommentInfo(Expected.Children, Actual.Children);
}
void CheckCommentInfo(ArrayRef<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<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(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 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 CheckReference(const Reference &Expected, const Reference &Actual) {
void CheckReference(Reference &Expected, Reference &Actual) {
EXPECT_EQ(Expected.Name, Actual.Name);
EXPECT_EQ(Expected.RefType, Actual.RefType);
EXPECT_EQ(Expected.Path, Actual.Path);
}
void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual) {
void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) {
CheckReference(Expected->Type, Actual->Type);
}
void CheckFieldTypeInfo(const FieldTypeInfo *Expected,
const FieldTypeInfo *Actual) {
void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) {
CheckTypeInfo(Expected, Actual);
EXPECT_EQ(Expected->Name, Actual->Name);
}
void CheckMemberTypeInfo(const MemberTypeInfo *Expected,
const MemberTypeInfo *Actual) {
void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
CheckFieldTypeInfo(Expected, Actual);
EXPECT_EQ(Expected->Access, Actual->Access);
CheckCommentInfo(Expected->Description, Actual->Description);
}
void CheckBaseInfo(const Info *Expected, const Info *Actual) {
void CheckBaseInfo(Info *Expected, Info *Actual) {
EXPECT_EQ(size_t(20), Actual->USR.size());
EXPECT_EQ(Expected->Name, Actual->Name);
EXPECT_EQ(Expected->Path, Actual->Path);
auto ItN_E = Expected->Namespace.begin();
auto ItN_A = Actual->Namespace.begin();
while (ItN_E != Expected->Namespace.end() &&
ItN_A != Actual->Namespace.end()) {
CheckReference(*ItN_E, *ItN_A);
++ItN_E;
++ItN_A;
}
EXPECT_TRUE(ItN_E == Expected->Namespace.end() &&
ItN_A == Actual->Namespace.end());
ASSERT_EQ(Expected->Namespace.size(), Actual->Namespace.size());
for (size_t Idx = 0; Idx < Actual->Namespace.size(); ++Idx)
CheckReference(Expected->Namespace[Idx], Actual->Namespace[Idx]);
CheckCommentInfo(Expected->Description, Actual->Description);
}
void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) {
void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
CheckBaseInfo(Expected, Actual);
EXPECT_EQ(Expected->DefLoc.has_value(), Actual->DefLoc.has_value());
if (Expected->DefLoc && Actual->DefLoc.has_value()) {
@@ -157,186 +138,109 @@ void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) {
EXPECT_EQ(Expected->DefLoc->EndLineNumber, Actual->DefLoc->EndLineNumber);
EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename);
}
auto ItE = Expected->Loc.begin();
auto ItA = Actual->Loc.begin();
while (ItE != Expected->Loc.end() && ItA != Actual->Loc.end()) {
EXPECT_EQ(*ItE, *ItA);
++ItE;
++ItA;
}
EXPECT_TRUE(ItE == Expected->Loc.end() && ItA == Actual->Loc.end());
ASSERT_EQ(Expected->Loc.size(), Actual->Loc.size());
for (size_t Idx = 0; Idx < Actual->Loc.size(); ++Idx)
EXPECT_EQ(Expected->Loc[Idx], Actual->Loc[Idx]);
}
void CheckFunctionInfo(const FunctionInfo *Expected,
const FunctionInfo *Actual) {
void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->IsMethod, Actual->IsMethod);
CheckReference(Expected->Parent, Actual->Parent);
CheckTypeInfo(&Expected->ReturnType, &Actual->ReturnType);
for (size_t Idx = 0; Idx < Expected->Params.size(); ++Idx) {
ASSERT_EQ(Expected->Params.size(), Actual->Params.size());
for (size_t Idx = 0; Idx < Actual->Params.size(); ++Idx)
EXPECT_EQ(Expected->Params[Idx], Actual->Params[Idx]);
}
EXPECT_EQ(Expected->Access, Actual->Access);
}
void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual) {
void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->Scoped, Actual->Scoped);
auto ItM_E = Expected->Members.begin();
auto ItM_A = Actual->Members.begin();
while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) {
EXPECT_EQ(*ItM_E, *ItM_A);
++ItM_E;
++ItM_A;
}
EXPECT_TRUE(ItM_E == Expected->Members.end() &&
ItM_A == Actual->Members.end());
ASSERT_EQ(Expected->Members.size(), Actual->Members.size());
for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx)
EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]);
}
void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual) {
void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->IsUsing, Actual->IsUsing);
CheckTypeInfo(&Expected->Underlying, &Actual->Underlying);
}
void CheckNamespaceInfo(const NamespaceInfo *Expected,
const NamespaceInfo *Actual) {
void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual) {
CheckBaseInfo(Expected, Actual);
ASSERT_EQ(Expected->Children.Namespaces.size(),
Actual->Children.Namespaces.size());
auto ItN_E = Expected->Children.Namespaces.begin();
auto ItN_A = Actual->Children.Namespaces.begin();
while (ItN_E != Expected->Children.Namespaces.end() &&
ItN_A != Actual->Children.Namespaces.end()) {
CheckReference(*ItN_E, *ItN_A);
++ItN_E;
++ItN_A;
auto ItExpected = Expected->Children.Namespaces.begin();
auto ItActual = Actual->Children.Namespaces.begin();
while (ItExpected != Expected->Children.Namespaces.end()) {
CheckReference(*ItExpected, *ItActual);
++ItExpected;
++ItActual;
}
EXPECT_TRUE(ItN_E == Expected->Children.Namespaces.end() &&
ItN_A == Actual->Children.Namespaces.end());
auto ItR_E = Expected->Children.Records.begin();
auto ItR_A = Actual->Children.Records.begin();
while (ItR_E != Expected->Children.Records.end() &&
ItR_A != Actual->Children.Records.end()) {
CheckReference(*ItR_E, *ItR_A);
++ItR_E;
++ItR_A;
}
EXPECT_TRUE(ItR_E == Expected->Children.Records.end() &&
ItR_A == Actual->Children.Records.end());
ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size());
for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx)
CheckReference(Expected->Children.Records[Idx],
Actual->Children.Records[Idx]);
auto ItF_E = Expected->Children.Functions.begin();
auto ItF_A = Actual->Children.Functions.begin();
while (ItF_E != Expected->Children.Functions.end() &&
ItF_A != Actual->Children.Functions.end()) {
CheckFunctionInfo(&(*ItF_E), &(*ItF_A));
++ItF_E;
++ItF_A;
}
EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() &&
ItF_A == Actual->Children.Functions.end());
ASSERT_EQ(Expected->Children.Functions.size(),
Actual->Children.Functions.size());
for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx)
CheckFunctionInfo(&Expected->Children.Functions[Idx],
&Actual->Children.Functions[Idx]);
auto ItEnum_E = Expected->Children.Enums.begin();
auto ItEnum_A = Actual->Children.Enums.begin();
while (ItEnum_E != Expected->Children.Enums.end() &&
ItEnum_A != Actual->Children.Enums.end()) {
CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A));
++ItEnum_E;
++ItEnum_A;
}
EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() &&
ItEnum_A == Actual->Children.Enums.end());
ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size());
for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx)
CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]);
}
void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual) {
void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual) {
CheckSymbolInfo(Expected, Actual);
EXPECT_EQ(Expected->TagType, Actual->TagType);
EXPECT_EQ(Expected->IsTypeDef, Actual->IsTypeDef);
auto ItM_E = Expected->Members.begin();
auto ItM_A = Actual->Members.begin();
while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) {
EXPECT_EQ(*ItM_E, *ItM_A);
++ItM_E;
++ItM_A;
}
EXPECT_TRUE(ItM_E == Expected->Members.end() &&
ItM_A == Actual->Members.end());
ASSERT_EQ(Expected->Members.size(), Actual->Members.size());
for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx)
EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]);
auto ItP_E = Expected->Parents.begin();
auto ItP_A = Actual->Parents.begin();
while (ItP_E != Expected->Parents.end() && ItP_A != Actual->Parents.end()) {
CheckReference(*ItP_E, *ItP_A);
++ItP_E;
++ItP_A;
}
EXPECT_TRUE(ItP_E == Expected->Parents.end() &&
ItP_A == Actual->Parents.end());
ASSERT_EQ(Expected->Parents.size(), Actual->Parents.size());
for (size_t Idx = 0; Idx < Actual->Parents.size(); ++Idx)
CheckReference(Expected->Parents[Idx], Actual->Parents[Idx]);
auto ItVP_E = Expected->VirtualParents.begin();
auto ItVP_A = Actual->VirtualParents.begin();
while (ItVP_E != Expected->VirtualParents.end() &&
ItVP_A != Actual->VirtualParents.end()) {
CheckReference(*ItVP_E, *ItVP_A);
++ItVP_E;
++ItVP_A;
}
EXPECT_TRUE(ItVP_E == Expected->VirtualParents.end() &&
ItVP_A == Actual->VirtualParents.end());
ASSERT_EQ(Expected->VirtualParents.size(), Actual->VirtualParents.size());
for (size_t Idx = 0; Idx < Actual->VirtualParents.size(); ++Idx)
CheckReference(Expected->VirtualParents[Idx], Actual->VirtualParents[Idx]);
auto ItB_E = Expected->Bases.begin();
auto ItB_A = Actual->Bases.begin();
while (ItB_E != Expected->Bases.end() && ItB_A != Actual->Bases.end()) {
CheckBaseRecordInfo(&(*ItB_E), &(*ItB_A));
++ItB_E;
++ItB_A;
}
EXPECT_TRUE(ItB_E == Expected->Bases.end() && ItB_A == Actual->Bases.end());
ASSERT_EQ(Expected->Bases.size(), Actual->Bases.size());
for (size_t Idx = 0; Idx < Actual->Bases.size(); ++Idx)
CheckBaseRecordInfo(&Expected->Bases[Idx], &Actual->Bases[Idx]);
auto ItR_E = Expected->Children.Records.begin();
auto ItR_A = Actual->Children.Records.begin();
while (ItR_E != Expected->Children.Records.end() &&
ItR_A != Actual->Children.Records.end()) {
CheckReference(*ItR_E, *ItR_A);
++ItR_E;
++ItR_A;
}
EXPECT_TRUE(ItR_E == Expected->Children.Records.end() &&
ItR_A == Actual->Children.Records.end());
ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size());
for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx)
CheckReference(Expected->Children.Records[Idx],
Actual->Children.Records[Idx]);
auto ItF_E = Expected->Children.Functions.begin();
auto ItF_A = Actual->Children.Functions.begin();
while (ItF_E != Expected->Children.Functions.end() &&
ItF_A != Actual->Children.Functions.end()) {
CheckFunctionInfo(&(*ItF_E), &(*ItF_A));
++ItF_E;
++ItF_A;
}
EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() &&
ItF_A == Actual->Children.Functions.end());
ASSERT_EQ(Expected->Children.Functions.size(),
Actual->Children.Functions.size());
for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx)
CheckFunctionInfo(&Expected->Children.Functions[Idx],
&Actual->Children.Functions[Idx]);
auto ItEnum_E = Expected->Children.Enums.begin();
auto ItEnum_A = Actual->Children.Enums.begin();
while (ItEnum_E != Expected->Children.Enums.end() &&
ItEnum_A != Actual->Children.Enums.end()) {
CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A));
++ItEnum_E;
++ItEnum_A;
}
EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() &&
ItEnum_A == Actual->Children.Enums.end());
ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size());
for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx)
CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]);
}
void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
const BaseRecordInfo *Actual) {
void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual) {
CheckRecordInfo(Expected, Actual);
EXPECT_EQ(Expected->IsVirtual, Actual->IsVirtual);
@@ -344,7 +248,7 @@ void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
EXPECT_EQ(Expected->IsParent, Actual->IsParent);
}
void CheckIndex(const Index &Expected, const Index &Actual) {
void CheckIndex(Index &Expected, Index &Actual) {
CheckReference(Expected, Actual);
ASSERT_EQ(Expected.Children.size(), Actual.Children.size());
for (auto &[_, C] : Expected.Children)

View File

@@ -31,32 +31,25 @@ FunctionInfo *InfoAsFunction(Info *I);
EnumInfo *InfoAsEnum(Info *I);
TypedefInfo *InfoAsTypedef(Info *I);
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);
// Unlike the operator==, these functions explicitly does not check USRs, as
// that may change and it would be better to not rely on its implementation.
void CheckReference(Reference &Expected, Reference &Actual);
void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual);
void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual);
void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual);
// This function explicitly does not check USRs, as that may change and it would
// be better to not rely on its implementation.
void CheckBaseInfo(const Info *Expected, const Info *Actual);
void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual);
void CheckFunctionInfo(const FunctionInfo *Expected,
const FunctionInfo *Actual);
void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual);
void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual);
void CheckNamespaceInfo(const NamespaceInfo *Expected,
const NamespaceInfo *Actual);
void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual);
void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
const BaseRecordInfo *Actual);
void CheckBaseInfo(Info *Expected, Info *Actual);
void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual);
void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual);
void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual);
void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual);
void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual);
void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual);
void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual);
void CheckIndex(const Index &Expected, const Index &Actual);
void CheckIndex(Index &Expected, Index &Actual);
class ClangDocContextTest : public ::testing::Test {
protected:

View File

@@ -28,8 +28,7 @@ TEST_F(GeneratorTest, emitIndex) {
InfoC->USR = serialize::hashUSR("3");
Reference RefB = Reference(SymbolID(), "B");
RefB.USR = serialize::hashUSR("2");
Reference NsC[] = {std::move(RefB)};
InfoC->Namespace = llvm::ArrayRef(NsC);
InfoC->Namespace = {std::move(RefB)};
Generator::addInfoToIndex(Idx, InfoC.get());
auto InfoD = std::make_unique<Info>();
InfoD->Name = "D";
@@ -41,8 +40,7 @@ TEST_F(GeneratorTest, emitIndex) {
RefD.USR = serialize::hashUSR("4");
Reference RefE = Reference(SymbolID(), "E");
RefE.USR = serialize::hashUSR("5");
Reference NsF[] = {std::move(RefE), std::move(RefD)};
InfoF->Namespace = llvm::ArrayRef(NsF);
InfoF->Namespace = {std::move(RefE), std::move(RefD)};
Generator::addInfoToIndex(Idx, InfoF.get());
auto InfoG = std::make_unique<Info>(InfoType::IT_namespace);
Generator::addInfoToIndex(Idx, InfoG.get());

View File

@@ -19,54 +19,39 @@ TEST_F(JSONGeneratorTest, emitRecordJSON) {
RecordInfo I;
I.Name = "Foo";
I.IsTypeDef = false;
Reference Ns[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "GlobalNamespace", InfoType::IT_namespace);
I.Path = "GlobalNamespace";
I.DefLoc = Location(1, 1, "main.cpp");
I.TagType = TagTypeKind::Class;
I.Template = TemplateInfo();
TemplateParamInfo TParams[] = {TemplateParamInfo("class T")};
I.Template->Params = llvm::ArrayRef(TParams);
I.Template->Params.emplace_back("class T");
EnumInfo E;
E.Name = "Color";
E.Scoped = false;
EnumValueInfo EV[] = {EnumValueInfo("RED", "0")};
E.Members = llvm::ArrayRef(EV);
I.Children.Enums.push_back(E);
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "Color";
I.Children.Enums.back().Scoped = false;
I.Children.Enums.back().Members.emplace_back();
I.Children.Enums.back().Members.back().Name = "RED";
I.Children.Enums.back().Members.back().Value = "0";
MemberTypeInfo M[] = {
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_protected)};
I.Members = llvm::ArrayRef(M);
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_protected);
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
true);
FunctionInfo F;
F.Name = "InheritedFunctionOne";
B.Children.Functions.push_back(F);
MemberTypeInfo BM[] = {
MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_public)};
B.Members = llvm::ArrayRef(BM);
BaseRecordInfo Bases[] = {std::move(B)};
I.Bases = llvm::ArrayRef(Bases);
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_public, true);
I.Bases.back().Children.Functions.emplace_back();
I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";
I.Bases.back().Members.emplace_back(TypeInfo("int"), "N",
AccessSpecifier::AS_public);
// F is in the global namespace
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")};
I.Parents = llvm::ArrayRef(Parents);
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record,
"path::to::G::G", "path/to/G")};
I.VirtualParents = llvm::ArrayRef(VParents);
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
"path::to::G::G", "path/to/G");
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::r::ChildStruct", "path/to/A/r");
I.Children.Records.push_back(ChildStruct);
FunctionInfo F2;
F2.Name = "OneFunction";
I.Children.Functions.push_back(F2);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::r::ChildStruct", "path/to/A/r");
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
auto G = getJSONGenerator();
assert(G);
@@ -212,26 +197,20 @@ TEST_F(JSONGeneratorTest, emitNamespaceJSON) {
NamespaceInfo I;
I.Name = "Namespace";
I.Path = "path/to/A";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
"path::to::A::Namespace::ChildNamespace",
"path/to/A/Namespace");
I.Children.Namespaces.push_back(NewNamespace);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::Namespace::ChildStruct",
"path/to/A/Namespace");
I.Children.Records.push_back(ChildStruct);
FunctionInfo F;
F.Name = "OneFunction";
F.Access = AccessSpecifier::AS_none;
I.Children.Functions.push_back(F);
EnumInfo E;
E.Name = "OneEnum";
I.Children.Enums.push_back(E);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::Namespace::ChildStruct",
"path/to/A/Namespace");
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "OneEnum";
auto G = getJSONGenerator();
assert(G);

View File

@@ -26,22 +26,16 @@ class MDGeneratorTest : public ClangDocContextTest {};
TEST_F(MDGeneratorTest, emitNamespaceMD) {
NamespaceInfo I;
I.Name = "Namespace";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
I.Children.Namespaces.push_back(NewNamespace);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Records.push_back(ChildStruct);
FunctionInfo F;
F.Name = "OneFunction";
F.Access = AccessSpecifier::AS_none;
I.Children.Functions.push_back(F);
EnumInfo E;
E.Name = "OneEnum";
I.Children.Enums.push_back(E);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "OneEnum";
auto G = getMDGenerator();
assert(G);
@@ -85,31 +79,21 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) {
TEST_F(MDGeneratorTest, emitRecordMD) {
RecordInfo I;
I.Name = "r";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
MemberTypeInfo M[] = {
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
I.Members = llvm::ArrayRef(M);
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.TagType = TagTypeKind::Class;
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)};
I.Parents = llvm::ArrayRef(Parents);
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)};
I.VirtualParents = llvm::ArrayRef(VParents);
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Records.push_back(ChildStruct);
FunctionInfo F;
F.Name = "OneFunction";
I.Children.Functions.push_back(F);
EnumInfo E;
E.Name = "OneEnum";
I.Children.Enums.push_back(E);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "OneEnum";
auto G = getMDGenerator();
assert(G);
@@ -159,18 +143,15 @@ ChildStruct
TEST_F(MDGeneratorTest, emitFunctionMD) {
FunctionInfo I;
I.Name = "f";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
I.Access = AccessSpecifier::AS_none;
I.ReturnType = TypeInfo("void");
FieldTypeInfo P[] = {FieldTypeInfo(TypeInfo("int"), "P")};
I.Params = llvm::ArrayRef(P);
I.Params.emplace_back(TypeInfo("int"), "P");
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -194,15 +175,12 @@ TEST_F(MDGeneratorTest, emitFunctionMD) {
TEST_F(MDGeneratorTest, emitEnumMD) {
EnumInfo I;
I.Name = "e";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
EnumValueInfo EV[] = {EnumValueInfo("X")};
I.Members = llvm::ArrayRef(EV);
I.Members.emplace_back("X");
I.Scoped = true;
auto G = getMDGenerator();
@@ -230,9 +208,8 @@ TEST_F(MDGeneratorTest, emitCommentMD) {
I.DefLoc = Location(10, 10, "test.cpp");
I.ReturnType = TypeInfo("void");
FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I"),
FieldTypeInfo(TypeInfo("int"), "J")};
I.Params = llvm::ArrayRef(PI);
I.Params.emplace_back(TypeInfo("int"), "I");
I.Params.emplace_back(TypeInfo("int"), "J");
I.Access = AccessSpecifier::AS_none;
CommentInfo Top;

View File

@@ -18,200 +18,150 @@ class MergeTest : public ClangDocContextTest {};
TEST_F(MergeTest, mergeNamespaceInfos) {
NamespaceInfo One;
One.Name = "Namespace";
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
One.Namespace = llvm::ArrayRef(Ns1);
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference RA(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
One.Children.Namespaces.push_back(RA);
Reference RC1(NonEmptySID, "ChildStruct", InfoType::IT_record);
One.Children.Records.push_back(RC1);
FunctionInfo F1;
F1.Name = "OneFunction";
F1.USR = NonEmptySID;
One.Children.Functions.push_back(F1);
EnumInfo E1;
E1.Name = "OneEnum";
E1.USR = NonEmptySID;
One.Children.Enums.push_back(E1);
One.Children.Records.emplace_back(NonEmptySID, "ChildStruct",
InfoType::IT_record);
One.Children.Functions.emplace_back();
One.Children.Functions.back().Name = "OneFunction";
One.Children.Functions.back().USR = NonEmptySID;
One.Children.Enums.emplace_back();
One.Children.Enums.back().Name = "OneEnum";
One.Children.Enums.back().USR = NonEmptySID;
NamespaceInfo Two;
Two.Name = "Namespace";
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Two.Namespace = llvm::ArrayRef(Ns2);
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference RB(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
Two.Children.Namespaces.push_back(RB);
Reference RC2(EmptySID, "OtherChildStruct", InfoType::IT_record);
Two.Children.Records.push_back(RC2);
FunctionInfo F2;
F2.Name = "TwoFunction";
Two.Children.Functions.push_back(F2);
EnumInfo E2;
E2.Name = "TwoEnum";
Two.Children.Enums.push_back(E2);
Two.Children.Records.emplace_back(EmptySID, "OtherChildStruct",
InfoType::IT_record);
Two.Children.Functions.emplace_back();
Two.Children.Functions.back().Name = "TwoFunction";
Two.Children.Enums.emplace_back();
Two.Children.Enums.back().Name = "TwoEnum";
OwningPtrVec<Info> Infos;
Infos.push_back(&One);
Infos.push_back(&Two);
Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(One)));
Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(Two)));
NamespaceInfo Expected;
Expected.Name = "Namespace";
Reference NsExpected[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Expected.Namespace = llvm::ArrayRef(NsExpected);
auto Expected = allocatePtr<NamespaceInfo>();
Expected->Name = "Namespace";
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference RC(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
Expected.Children.Namespaces.push_back(RC);
Reference RCE1(NonEmptySID, "ChildStruct", InfoType::IT_record);
Expected.Children.Records.push_back(RCE1);
Expected->Children.Namespaces.push_back(RC);
Expected->Children.Records.emplace_back(NonEmptySID, "ChildStruct",
InfoType::IT_record);
Reference RD(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
Expected.Children.Namespaces.push_back(RD);
Reference RCE2(EmptySID, "OtherChildStruct", InfoType::IT_record);
Expected.Children.Records.push_back(RCE2);
FunctionInfo FE1;
FE1.Name = "OneFunction";
FE1.USR = NonEmptySID;
Expected.Children.Functions.push_back(FE1);
FunctionInfo FE2;
FE2.Name = "TwoFunction";
Expected.Children.Functions.push_back(FE2);
EnumInfo EE1;
EE1.Name = "OneEnum";
EE1.USR = NonEmptySID;
Expected.Children.Enums.push_back(EE1);
EnumInfo EE2;
EE2.Name = "TwoEnum";
Expected.Children.Enums.push_back(EE2);
Expected->Children.Namespaces.push_back(RD);
Expected->Children.Records.emplace_back(EmptySID, "OtherChildStruct",
InfoType::IT_record);
Expected->Children.Functions.emplace_back();
Expected->Children.Functions.back().Name = "OneFunction";
Expected->Children.Functions.back().USR = NonEmptySID;
Expected->Children.Functions.emplace_back();
Expected->Children.Functions.back().Name = "TwoFunction";
Expected->Children.Enums.emplace_back();
Expected->Children.Enums.back().Name = "OneEnum";
Expected->Children.Enums.back().USR = NonEmptySID;
Expected->Children.Enums.emplace_back();
Expected->Children.Enums.back().Name = "TwoEnum";
auto Actual = mergeInfos(Infos);
assert(Actual);
CheckNamespaceInfo(InfoAsNamespace(&Expected), InfoAsNamespace(Actual.get()));
CheckNamespaceInfo(InfoAsNamespace(Expected.get()),
InfoAsNamespace(Actual.get().get()));
}
TEST_F(MergeTest, mergeRecordInfos) {
RecordInfo One;
One.Name = "r";
One.IsTypeDef = true;
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
One.Namespace = llvm::ArrayRef(Ns1);
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
One.DefLoc = Location(10, 10, "test.cpp");
MemberTypeInfo M1[] = {
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
One.Members = llvm::ArrayRef(M1);
One.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
One.TagType = TagTypeKind::Class;
Reference P1[] = {Reference(EmptySID, "F", InfoType::IT_record)};
One.Parents = llvm::ArrayRef(P1);
Reference VP1[] = {Reference(EmptySID, "G", InfoType::IT_record)};
One.VirtualParents = llvm::ArrayRef(VP1);
One.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
One.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
BaseRecordInfo B1[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_protected, true)};
One.Bases = llvm::ArrayRef(B1);
Reference RCShared1(NonEmptySID, "SharedChildStruct", InfoType::IT_record);
One.Children.Records.push_back(RCShared1);
FunctionInfo F1;
F1.Name = "OneFunction";
F1.USR = NonEmptySID;
One.Children.Functions.push_back(F1);
EnumInfo E1;
E1.Name = "OneEnum";
E1.USR = NonEmptySID;
One.Children.Enums.push_back(E1);
One.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_protected, true);
One.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
InfoType::IT_record);
One.Children.Functions.emplace_back();
One.Children.Functions.back().Name = "OneFunction";
One.Children.Functions.back().USR = NonEmptySID;
One.Children.Enums.emplace_back();
One.Children.Enums.back().Name = "OneEnum";
One.Children.Enums.back().USR = NonEmptySID;
RecordInfo Two;
Two.Name = "r";
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Two.Namespace = llvm::ArrayRef(Ns2);
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Location Loc2(12, 12, "test.cpp");
Two.Loc.push_back(Loc2);
Two.Loc.emplace_back(12, 12, "test.cpp");
Two.TagType = TagTypeKind::Class;
Reference RCShared2(NonEmptySID, "SharedChildStruct", InfoType::IT_record,
"path");
Two.Children.Records.push_back(RCShared2);
FunctionInfo F2;
F2.Name = "TwoFunction";
Two.Children.Functions.push_back(F2);
EnumInfo E2;
E2.Name = "TwoEnum";
Two.Children.Enums.push_back(E2);
Two.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
InfoType::IT_record, "path");
Two.Children.Functions.emplace_back();
Two.Children.Functions.back().Name = "TwoFunction";
Two.Children.Enums.emplace_back();
Two.Children.Enums.back().Name = "TwoEnum";
OwningPtrVec<Info> Infos;
Infos.push_back(&One);
Infos.push_back(&Two);
Infos.emplace_back(allocatePtr<RecordInfo>(std::move(One)));
Infos.emplace_back(allocatePtr<RecordInfo>(std::move(Two)));
RecordInfo Expected;
Expected.Name = "r";
Expected.IsTypeDef = true;
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Expected.Namespace = llvm::ArrayRef(NsE);
auto Expected = allocatePtr<RecordInfo>();
Expected->Name = "r";
Expected->IsTypeDef = true;
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Expected.DefLoc = Location(10, 10, "test.cpp");
Location LocE(12, 12, "test.cpp");
Expected.Loc.push_back(LocE);
Expected->DefLoc = Location(10, 10, "test.cpp");
Expected->Loc.emplace_back(12, 12, "test.cpp");
MemberTypeInfo ME[] = {
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
Expected.Members = llvm::ArrayRef(ME);
Expected.TagType = TagTypeKind::Class;
Reference PE[] = {Reference(EmptySID, "F", InfoType::IT_record)};
Expected.Parents = llvm::ArrayRef(PE);
Reference VPE[] = {Reference(EmptySID, "G", InfoType::IT_record)};
Expected.VirtualParents = llvm::ArrayRef(VPE);
BaseRecordInfo BE[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_protected, true)};
Expected.Bases = llvm::ArrayRef(BE);
Expected->Members.emplace_back(TypeInfo("int"), "X",
AccessSpecifier::AS_private);
Expected->TagType = TagTypeKind::Class;
Expected->Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
Expected->VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
Expected->Bases.emplace_back(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_protected, true);
Reference RCSharedE(NonEmptySID, "SharedChildStruct", InfoType::IT_record,
"path");
Expected.Children.Records.push_back(RCSharedE);
FunctionInfo FE1;
FE1.Name = "OneFunction";
FE1.USR = NonEmptySID;
Expected.Children.Functions.push_back(FE1);
FunctionInfo FE2;
FE2.Name = "TwoFunction";
Expected.Children.Functions.push_back(FE2);
EnumInfo EE1;
EE1.Name = "OneEnum";
EE1.USR = NonEmptySID;
Expected.Children.Enums.push_back(EE1);
EnumInfo EE2;
EE2.Name = "TwoEnum";
Expected.Children.Enums.push_back(EE2);
Expected->Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
InfoType::IT_record, "path");
Expected->Children.Functions.emplace_back();
Expected->Children.Functions.back().Name = "OneFunction";
Expected->Children.Functions.back().USR = NonEmptySID;
Expected->Children.Functions.emplace_back();
Expected->Children.Functions.back().Name = "TwoFunction";
Expected->Children.Enums.emplace_back();
Expected->Children.Enums.back().Name = "OneEnum";
Expected->Children.Enums.back().USR = NonEmptySID;
Expected->Children.Enums.emplace_back();
Expected->Children.Enums.back().Name = "TwoEnum";
auto Actual = mergeInfos(Infos);
assert(Actual);
CheckRecordInfo(InfoAsRecord(&Expected), InfoAsRecord(Actual.get()));
CheckRecordInfo(InfoAsRecord(Expected.get()),
InfoAsRecord(Actual.get().get()));
}
TEST_F(MergeTest, mergeFunctionInfos) {
FunctionInfo One;
One.Name = "f";
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
One.Namespace = llvm::ArrayRef(Ns1);
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
One.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
One.Loc.push_back(Loc1);
One.Loc.emplace_back(12, 12, "test.cpp");
One.IsMethod = true;
One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
@@ -220,106 +170,89 @@ TEST_F(MergeTest, mergeFunctionInfos) {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo OnePara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, OneText)};
CommentInfo TopOne(CommentKind::CK_FullComment, OnePara);
One.Description.push_back(TopOne);
One.Description.emplace_back(CommentKind::CK_FullComment, OnePara);
FunctionInfo Two;
Two.Name = "f";
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Two.Namespace = llvm::ArrayRef(Ns2);
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Location Loc2(12, 12, "test.cpp");
Two.Loc.push_back(Loc2);
Two.Loc.emplace_back(12, 12, "test.cpp");
Two.ReturnType = TypeInfo("void");
FieldTypeInfo P2(TypeInfo("int"), "P");
FieldTypeInfo Params2[] = {std::move(P2)};
Two.Params = llvm::ArrayRef(Params2);
Two.Params.emplace_back(TypeInfo("int"), "P");
CommentInfo TwoText[] = {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo TwoPara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, TwoText)};
CommentInfo TopTwo(CommentKind::CK_FullComment, TwoPara);
Two.Description.push_back(TopTwo);
Two.Description.emplace_back(CommentKind::CK_FullComment, TwoPara);
OwningPtrVec<Info> Infos;
Infos.push_back(&One);
Infos.push_back(&Two);
Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(One)));
Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(Two)));
FunctionInfo Expected;
Expected.Name = "f";
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Expected.Namespace = llvm::ArrayRef(NsE);
auto Expected = allocatePtr<FunctionInfo>();
Expected->Name = "f";
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Expected.DefLoc = Location(10, 10, "test.cpp");
Location LocE(12, 12, "test.cpp");
Expected.Loc.push_back(LocE);
Expected->DefLoc = Location(10, 10, "test.cpp");
Expected->Loc.emplace_back(12, 12, "test.cpp");
Expected.ReturnType = TypeInfo("void");
FieldTypeInfo PE(TypeInfo("int"), "P");
FieldTypeInfo ParamsE[] = {std::move(PE)};
Expected.Params = llvm::ArrayRef(ParamsE);
Expected.IsMethod = true;
Expected.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
Expected->ReturnType = TypeInfo("void");
Expected->Params.emplace_back(TypeInfo("int"), "P");
Expected->IsMethod = true;
Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
CommentInfo ExpectedText[] = {
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
CommentInfo ExpectedPara[] = {
CommentInfo(CommentKind::CK_ParagraphComment, ExpectedText)};
CommentInfo TopE(CommentKind::CK_FullComment, ExpectedPara);
Expected.Description.push_back(TopE);
Expected->Description.emplace_back(CommentKind::CK_FullComment, ExpectedPara);
auto Actual = mergeInfos(Infos);
assert(Actual);
CheckFunctionInfo(InfoAsFunction(&Expected), InfoAsFunction(Actual.get()));
CheckFunctionInfo(InfoAsFunction(Expected.get()),
InfoAsFunction(Actual.get().get()));
}
TEST_F(MergeTest, mergeEnumInfos) {
EnumInfo One;
One.Name = "e";
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
One.Namespace = llvm::ArrayRef(Ns1);
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
One.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
One.Loc.push_back(Loc1);
One.Loc.emplace_back(12, 12, "test.cpp");
One.Scoped = true;
EnumInfo Two;
Two.Name = "e";
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Two.Namespace = llvm::ArrayRef(Ns2);
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Location Loc2(20, 20, "test.cpp");
Two.Loc.push_back(Loc2);
Two.Loc.emplace_back(20, 20, "test.cpp");
EnumValueInfo EV2[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
Two.Members = llvm::ArrayRef(EV2);
Two.Members.emplace_back("X");
Two.Members.emplace_back("Y");
OwningPtrVec<Info> Infos;
Infos.push_back(&One);
Infos.push_back(&Two);
Infos.emplace_back(allocatePtr<EnumInfo>(std::move(One)));
Infos.emplace_back(allocatePtr<EnumInfo>(std::move(Two)));
EnumInfo Expected;
Expected.Name = "e";
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
Expected.Namespace = llvm::ArrayRef(NsE);
auto Expected = allocatePtr<EnumInfo>();
Expected->Name = "e";
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Expected.DefLoc = Location(10, 10, "test.cpp");
Location LocE1(12, 12, "test.cpp");
Expected.Loc.push_back(LocE1);
Location LocE2(20, 20, "test.cpp");
Expected.Loc.push_back(LocE2);
Expected->DefLoc = Location(10, 10, "test.cpp");
Expected->Loc.emplace_back(12, 12, "test.cpp");
Expected->Loc.emplace_back(20, 20, "test.cpp");
EnumValueInfo EV_E[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
Expected.Members = llvm::ArrayRef(EV_E);
Expected.Scoped = true;
Expected->Members.emplace_back("X");
Expected->Members.emplace_back("Y");
Expected->Scoped = true;
auto Actual = mergeInfos(Infos);
assert(Actual);
CheckEnumInfo(InfoAsEnum(&Expected), InfoAsEnum(Actual.get()));
CheckEnumInfo(InfoAsEnum(Expected.get()), InfoAsEnum(Actual.get().get()));
}
} // namespace doc

View File

@@ -117,27 +117,25 @@ TEST_F(SerializeTest, emitNamespaceInfo) {
extractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
/*Public=*/false, Infos, this->Diags);
NamespaceInfo *A = InfoAsNamespace(Infos[0]);
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedA(EmptySID, "A");
CheckNamespaceInfo(&ExpectedA, A);
NamespaceInfo *B = InfoAsNamespace(Infos[2]);
NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
Reference NsB[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
ExpectedB.Namespace = llvm::ArrayRef(NsB);
ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
CheckNamespaceInfo(&ExpectedB, B);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4]);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "f";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
Reference NsF[] = {Reference(EmptySID, "B", InfoType::IT_namespace),
Reference(EmptySID, "A", InfoType::IT_namespace)};
F.Namespace = llvm::ArrayRef(NsF);
F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
F.Access = AccessSpecifier::AS_none;
ExpectedBWithFunction.Children.Functions.push_back(F);
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -146,7 +144,7 @@ TEST_F(SerializeTest, emitAnonymousNamespaceInfo) {
extractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos,
this->Diags);
NamespaceInfo *A = InfoAsNamespace(Infos[0]);
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedA(EmptySID);
ExpectedA.Name = "@nonymous_namespace";
CheckNamespaceInfo(&ExpectedA, A);
@@ -172,103 +170,95 @@ void F<int>::TemplateMethod();
typedef struct {} G;)raw",
10, /*Public=*/false, Infos, this->Diags);
RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo *E = InfoAsRecord(Infos[0].get());
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
Reference NsE[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedE.TagType = TagTypeKind::Class;
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
MemberTypeInfo MemE[] = {
MemberTypeInfo(TypeInfo("int"), "value", AccessSpecifier::AS_public)};
ExpectedE.Members = llvm::ArrayRef(MemE);
ExpectedE.Members.emplace_back(TypeInfo("int"), "value",
AccessSpecifier::AS_public);
// TODO the data member should have the docstring on it:
//ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
CheckRecordInfo(&ExpectedE, E);
RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2]);
RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
RecordInfo ExpectedRecordWithEConstructor(EmptySID);
FunctionInfo EConstructor;
EConstructor.Name = "E";
EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
EConstructor.ReturnType = TypeInfo("void");
EConstructor.DefLoc = Location(0, 0, "test.cpp");
Reference NsEC[] = {
Reference(EmptySID, "E", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
EConstructor.Namespace = llvm::ArrayRef(NsEC);
EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
EConstructor.Access = AccessSpecifier::AS_public;
EConstructor.IsMethod = true;
ExpectedRecordWithEConstructor.Children.Functions.push_back(EConstructor);
ExpectedRecordWithEConstructor.Children.Functions.emplace_back(
std::move(EConstructor));
CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3]);
RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
RecordInfo ExpectedRecordWithMethod(EmptySID);
FunctionInfo Method;
Method.Name = "ProtectedMethod";
Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
Method.ReturnType = TypeInfo("void");
Location LMethod(0, 0, "test.cpp");
Method.Loc.push_back(LMethod);
Reference NsMethod[] = {
Reference(EmptySID, "E", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
Method.Namespace = llvm::ArrayRef(NsMethod);
Method.Loc.emplace_back(0, 0, "test.cpp");
Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
Method.Access = AccessSpecifier::AS_protected;
Method.IsMethod = true;
ExpectedRecordWithMethod.Children.Functions.push_back(Method);
ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method));
CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
RecordInfo *F = InfoAsRecord(Infos[4]);
RecordInfo *F = InfoAsRecord(Infos[4].get());
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
Reference NsF3[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedF.Namespace = llvm::ArrayRef(NsF3);
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedF.TagType = TagTypeKind::Struct;
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedF, F);
RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6]);
RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
FunctionInfo TemplateMethod;
TemplateMethod.Name = "TemplateMethod";
TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
TemplateMethod.ReturnType = TypeInfo("void");
Location LTemp1(0, 0, "test.cpp");
TemplateMethod.Loc.push_back(LTemp1);
Reference NsT1[] = {
Reference(EmptySID, "F", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
TemplateMethod.Namespace = llvm::ArrayRef(NsT1);
TemplateMethod.Loc.emplace_back(0, 0, "test.cpp");
TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
TemplateMethod.Access = AccessSpecifier::AS_public;
TemplateMethod.IsMethod = true;
ExpectedRecordWithTemplateMethod.Children.Functions.push_back(TemplateMethod);
ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back(
std::move(TemplateMethod));
CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7]);
RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
RecordInfo ExpectedTemplatedRecord(EmptySID);
FunctionInfo SpecializedTemplateMethod;
SpecializedTemplateMethod.Name = "TemplateMethod";
SpecializedTemplateMethod.Parent =
Reference(EmptySID, "F", InfoType::IT_record);
SpecializedTemplateMethod.ReturnType = TypeInfo("void");
Location LTemp2(0, 0, "test.cpp");
SpecializedTemplateMethod.Loc.push_back(LTemp2);
Reference NsT2[] = {
Reference(EmptySID, "F", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
SpecializedTemplateMethod.Namespace = llvm::ArrayRef(NsT2);
SpecializedTemplateMethod.Loc.emplace_back(0, 0, "test.cpp");
SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
InfoType::IT_record);
SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
SpecializedTemplateMethod.IsMethod = true;
ExpectedTemplatedRecord.Children.Functions.push_back(
SpecializedTemplateMethod);
ExpectedTemplatedRecord.Children.Functions.emplace_back(
std::move(SpecializedTemplateMethod));
CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
RecordInfo *G = InfoAsRecord(Infos[8]);
RecordInfo *G = InfoAsRecord(Infos[8].get());
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
Reference NsG[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedG.Namespace = llvm::ArrayRef(NsG);
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedG.TagType = TagTypeKind::Struct;
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
ExpectedG.IsTypeDef = true;
@@ -281,25 +271,25 @@ TEST_F(SerializeTest, emitEnumInfo) {
extractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
/*Public=*/false, Infos, this->Diags);
NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0]);
NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
EnumInfo E;
E.Name = "E";
E.DefLoc = Location(0, 0, "test.cpp");
EnumValueInfo EMem[] = {EnumValueInfo("X", "0"), EnumValueInfo("Y", "1")};
E.Members = llvm::ArrayRef(EMem);
ExpectedNamespaceWithEnum.Children.Enums.push_back(E);
E.Members.emplace_back("X", "0");
E.Members.emplace_back("Y", "1");
ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E));
CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1]);
NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
EnumInfo G;
G.Name = "G";
G.Scoped = true;
G.DefLoc = Location(0, 0, "test.cpp");
EnumValueInfo GMem[] = {EnumValueInfo("A", "0"), EnumValueInfo("B", "1")};
G.Members = llvm::ArrayRef(GMem);
ExpectedNamespaceWithScopedEnum.Children.Enums.push_back(G);
G.Members.emplace_back("A", "0");
G.Members.emplace_back("B", "1");
ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G));
CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
}
@@ -307,14 +297,12 @@ TEST_F(SerializeTest, emitUndefinedRecordInfo) {
EmittedInfoList Infos;
extractInfosFromCode("class E;", 2, /*Public=*/false, Infos, this->Diags);
RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo *E = InfoAsRecord(Infos[0].get());
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
Reference NsE[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedE.TagType = TagTypeKind::Class;
Location LE(0, 0, "test.cpp");
ExpectedE.Loc.push_back(LE);
ExpectedE.Loc.emplace_back(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedE, E);
}
@@ -323,16 +311,14 @@ TEST_F(SerializeTest, emitRecordMemberInfo) {
extractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos,
this->Diags);
RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo *E = InfoAsRecord(Infos[0].get());
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
Reference NsE[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedE.TagType = TagTypeKind::Struct;
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
MemberTypeInfo MemE[] = {
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_public)};
ExpectedE.Members = llvm::ArrayRef(MemE);
ExpectedE.Members.emplace_back(TypeInfo("int"), "I",
AccessSpecifier::AS_public);
CheckRecordInfo(&ExpectedE, E);
}
@@ -341,25 +327,23 @@ TEST_F(SerializeTest, emitInternalRecordInfo) {
extractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos,
this->Diags);
RecordInfo *E = InfoAsRecord(Infos[0]);
RecordInfo *E = InfoAsRecord(Infos[0].get());
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
Reference NsE[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedE.Namespace = llvm::ArrayRef(NsE);
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
ExpectedE.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedE, E);
RecordInfo *G = InfoAsRecord(Infos[2]);
RecordInfo *G = InfoAsRecord(Infos[2].get());
llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
llvm::sys::path::native(ExpectedGPath);
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
ExpectedG.TagType = TagTypeKind::Class;
Reference NsG[] = {
Reference(EmptySID, "E", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedG.Namespace = llvm::ArrayRef(NsG);
ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
CheckRecordInfo(&ExpectedG, G);
}
@@ -374,14 +358,14 @@ TEST_F(SerializeTest, emitPublicFunctionInternalInfo) {
extractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
Infos, this->Diags);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "F";
F.ReturnType = TypeInfo("int");
F.DefLoc = Location(0, 0, "test.cpp");
F.Access = AccessSpecifier::AS_none;
ExpectedBWithFunction.Children.Functions.push_back(F);
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -390,16 +374,15 @@ TEST_F(SerializeTest, emitInlinedFunctionInfo) {
extractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos,
this->Diags);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "F";
F.ReturnType = TypeInfo("void");
F.DefLoc = Location(0, 0, "test.cpp");
FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I")};
F.Params = llvm::ArrayRef(Params);
F.Params.emplace_back(TypeInfo("int"), "I");
F.Access = AccessSpecifier::AS_none;
ExpectedBWithFunction.Children.Functions.push_back(F);
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
}
@@ -414,169 +397,132 @@ class I {} ;
class J : public I<int> {} ;)raw",
14, /*Public=*/false, Infos, this->Diags);
RecordInfo *F = InfoAsRecord(Infos[0]);
RecordInfo *F = InfoAsRecord(Infos[0].get());
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
Reference NsF[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedF.Namespace = llvm::ArrayRef(NsF);
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace, "");
ExpectedF.TagType = TagTypeKind::Class;
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedF, F);
RecordInfo *G = InfoAsRecord(Infos[3]);
RecordInfo *G = InfoAsRecord(Infos[3].get());
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
Reference NsG[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedG.Namespace = llvm::ArrayRef(NsG);
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedG.TagType = TagTypeKind::Class;
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
MemberTypeInfo MemG[] = {
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_protected)};
ExpectedG.Members = llvm::ArrayRef(MemG);
ExpectedG.Members.emplace_back(TypeInfo("int"), "I",
AccessSpecifier::AS_protected);
CheckRecordInfo(&ExpectedG, G);
RecordInfo *E = InfoAsRecord(Infos[6]);
RecordInfo *E = InfoAsRecord(Infos[6].get());
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
Reference NsE[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedE.Namespace = llvm::ArrayRef(NsE);
Reference ParE[] = {Reference(EmptySID, /*Name=*/"F", InfoType::IT_record,
/*QualName=*/"", /*Path=*/"GlobalNamespace")};
ExpectedE.Parents = llvm::ArrayRef(ParE);
Reference VParE[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record,
/*QualName=*/"G",
/*Path=*/"GlobalNamespace")};
ExpectedE.VirtualParents = llvm::ArrayRef(VParE);
BaseRecordInfo BaseF(EmptySID, /*Name=*/"F",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_public, true);
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
/*QualName=*/"", /*Path*=*/"GlobalNamespace");
ExpectedE.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
InfoType::IT_record, /*QualName=*/"G",
/*Path*=*/"GlobalNamespace");
ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_public, true);
FunctionInfo FunctionSet;
FunctionSet.Name = "set";
FunctionSet.ReturnType = TypeInfo("void");
Location LSet;
FunctionSet.Loc.push_back(LSet);
FieldTypeInfo ParamsSet[] = {FieldTypeInfo(TypeInfo("int"), "N")};
FunctionSet.Params = llvm::ArrayRef(ParamsSet);
Reference NsSet[] = {
Reference(EmptySID, "F", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
FunctionSet.Namespace = llvm::ArrayRef(NsSet);
FunctionSet.Access =
AccessSpecifier::AS_none; // Wait, previous had AS_protected, but wait,
// F.Access was AS_protected. FunctionSet.Access
// should be AS_protected if it was so. In the
// original it was AS_protected.
FunctionSet.Loc.emplace_back();
FunctionSet.Params.emplace_back(TypeInfo("int"), "N");
FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
FunctionSet.Access = AccessSpecifier::AS_protected;
FunctionSet.IsMethod = true;
BaseF.Children.Functions.push_back(FunctionSet);
BaseRecordInfo BaseG(EmptySID, /*Name=*/"G",
/*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, true);
ExpectedE.Bases.back().Children.Functions.emplace_back(
std::move(FunctionSet));
ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
/*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, true);
FunctionInfo FunctionGet;
FunctionGet.Name = "get";
FunctionGet.ReturnType = TypeInfo("int");
Location LGet;
FunctionGet.DefLoc = LGet;
Reference NsGet[] = {
Reference(EmptySID, "G", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
FunctionGet.Namespace = llvm::ArrayRef(NsGet);
FunctionGet.DefLoc = Location();
FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
FunctionGet.Access = AccessSpecifier::AS_private;
FunctionGet.IsMethod = true;
BaseG.Children.Functions.push_back(FunctionGet);
MemberTypeInfo MemG2[] = {
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)};
BaseG.Members = llvm::ArrayRef(MemG2);
BaseRecordInfo BasesE[] = {std::move(BaseF), std::move(BaseG)};
ExpectedE.Bases = llvm::ArrayRef(BasesE);
ExpectedE.Bases.back().Children.Functions.emplace_back(
std::move(FunctionGet));
ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
AccessSpecifier::AS_private);
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
ExpectedE.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedE, E);
RecordInfo *H = InfoAsRecord(Infos[8]);
RecordInfo *H = InfoAsRecord(Infos[8].get());
RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
Reference NsH[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedH.Namespace = llvm::ArrayRef(NsH);
ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedH.TagType = TagTypeKind::Class;
ExpectedH.DefLoc = Location(0, 0, "test.cpp");
Reference ParH[] = {Reference(EmptySID, /*Name=*/"E", InfoType::IT_record,
/*QualName=*/"E", /*Path=*/"GlobalNamespace")};
ExpectedH.Parents = llvm::ArrayRef(ParH);
Reference VParH[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record,
/*QualName=*/"G",
/*Path=*/"GlobalNamespace")};
ExpectedH.VirtualParents = llvm::ArrayRef(VParH);
BaseRecordInfo BaseHE(EmptySID, /*Name=*/"E",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, true);
BaseRecordInfo BaseHF(EmptySID, /*Name=*/"F",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, false);
ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
/*QualName=*/"E", /*Path=*/"GlobalNamespace");
ExpectedH.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
InfoType::IT_record, /*QualName=*/"G",
/*Path=*/"GlobalNamespace");
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, true);
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
/*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, false);
FunctionInfo FunctionSetNew;
FunctionSetNew.Name = "set";
FunctionSetNew.ReturnType = TypeInfo("void");
Location LSetNew;
FunctionSetNew.Loc.push_back(LSetNew);
FieldTypeInfo ParamsSetNew[] = {FieldTypeInfo(TypeInfo("int"), "N")};
FunctionSetNew.Params = llvm::ArrayRef(ParamsSetNew);
Reference NsSetNew[] = {
Reference(EmptySID, "F", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
FunctionSetNew.Namespace = llvm::ArrayRef(NsSetNew);
FunctionSetNew.Loc.emplace_back();
FunctionSetNew.Params.emplace_back(TypeInfo("int"), "N");
FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
FunctionSetNew.Access = AccessSpecifier::AS_private;
FunctionSetNew.IsMethod = true;
BaseHF.Children.Functions.push_back(FunctionSetNew);
BaseRecordInfo BaseHG(EmptySID, /*Name=*/"G",
/*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, false);
ExpectedH.Bases.back().Children.Functions.emplace_back(
std::move(FunctionSetNew));
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
/*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, false);
FunctionInfo FunctionGetNew;
FunctionGetNew.Name = "get";
FunctionGetNew.ReturnType = TypeInfo("int");
Location LGetNew;
FunctionGetNew.DefLoc = LGetNew;
Reference NsGetNew[] = {
Reference(EmptySID, "G", InfoType::IT_record),
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
FunctionGetNew.Namespace = llvm::ArrayRef(NsGetNew);
FunctionGetNew.DefLoc = Location();
FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
FunctionGetNew.Access = AccessSpecifier::AS_private;
FunctionGetNew.IsMethod = true;
BaseHG.Children.Functions.push_back(FunctionGetNew);
MemberTypeInfo MemHG[] = {
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)};
BaseHG.Members = llvm::ArrayRef(MemHG);
BaseRecordInfo BasesH[] = {std::move(BaseHE), std::move(BaseHF),
std::move(BaseHG)};
ExpectedH.Bases = llvm::ArrayRef(BasesH);
ExpectedH.Bases.back().Children.Functions.emplace_back(
std::move(FunctionGetNew));
ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
AccessSpecifier::AS_private);
CheckRecordInfo(&ExpectedH, H);
RecordInfo *I = InfoAsRecord(Infos[10]);
RecordInfo *I = InfoAsRecord(Infos[10].get());
RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
Reference NsI[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedI.Namespace = llvm::ArrayRef(NsI);
ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
InfoType::IT_namespace);
ExpectedI.TagType = TagTypeKind::Class;
ExpectedI.DefLoc = Location(0, 0, "test.cpp");
CheckRecordInfo(&ExpectedI, I);
RecordInfo *J = InfoAsRecord(Infos[12]);
RecordInfo *J = InfoAsRecord(Infos[12].get());
RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
Reference NsJ[] = {
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
ExpectedJ.Namespace = llvm::ArrayRef(NsJ);
Reference ParJ[] = {
Reference(EmptySID, /*Name=*/"I<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.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);
ExpectedJ.DefLoc = Location(0, 0, "test.cpp");
ExpectedJ.TagType = TagTypeKind::Class;
CheckRecordInfo(&ExpectedJ, J);
@@ -592,33 +538,30 @@ static int staticModuleFunction(int x);
export double exportedModuleFunction(double y);)raw",
2, /*Public=*/true, Infos, Args, this->Diags);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
NamespaceInfo ExpectedBWithFunction(EmptySID);
FunctionInfo F;
F.Name = "moduleFunction";
F.ReturnType = TypeInfo("int");
Location LF1(0, 0, "test.cpp");
F.Loc.push_back(LF1);
FieldTypeInfo ParamsF[] = {FieldTypeInfo(TypeInfo("int"), "x"),
FieldTypeInfo(TypeInfo("double"), "d")};
ParamsF[1].DefaultValue = "3.2 - 1.0";
F.Params = llvm::ArrayRef(ParamsF);
F.Loc.emplace_back(0, 0, "test.cpp");
F.Params.emplace_back(TypeInfo("int"), "x");
F.Params.emplace_back(TypeInfo("double"), "d");
F.Params.back().DefaultValue = "3.2 - 1.0";
F.Access = AccessSpecifier::AS_none;
ExpectedBWithFunction.Children.Functions.push_back(F);
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1]);
NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
FunctionInfo ExportedF;
ExportedF.Name = "exportedModuleFunction";
ExportedF.ReturnType =
TypeInfo(Reference(EmptySID, "double", InfoType::IT_default));
Location LF2(0, 0, "test.cpp");
ExportedF.Loc.push_back(LF2);
FieldTypeInfo ParamsExportedF[] = {FieldTypeInfo(TypeInfo("double"), "y")};
ExportedF.Params = llvm::ArrayRef(ParamsExportedF);
ExportedF.Loc.emplace_back(0, 0, "test.cpp");
ExportedF.Params.emplace_back(TypeInfo("double"), "y");
ExportedF.Access = AccessSpecifier::AS_none;
ExpectedBWithExportedFunction.Children.Functions.push_back(ExportedF);
ExpectedBWithExportedFunction.Children.Functions.emplace_back(
std::move(ExportedF));
CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
}
@@ -628,24 +571,24 @@ TEST_F(SerializeTest, emitChildRecords) {
extractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
/*Public=*/false, Infos, this->Diags);
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
NamespaceInfo ExpectedParentA(EmptySID);
Reference RA(EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
ExpectedParentA.Children.Records.push_back(RA);
ExpectedParentA.Children.Records.emplace_back(
EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
CheckNamespaceInfo(&ExpectedParentA, ParentA);
RecordInfo *ParentB = InfoAsRecord(Infos[3]);
RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
RecordInfo ExpectedParentB(EmptySID);
llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
llvm::sys::path::native(ExpectedParentBPath);
Reference RB(EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
ExpectedParentB.Children.Records.push_back(RB);
ExpectedParentB.Children.Records.emplace_back(
EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
CheckRecordInfo(&ExpectedParentB, ParentB);
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7]);
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
NamespaceInfo ExpectedParentC(EmptySID);
Reference RC(EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
ExpectedParentC.Children.Records.push_back(RC);
ExpectedParentC.Children.Records.emplace_back(
EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
CheckNamespaceInfo(&ExpectedParentC, ParentC);
}
@@ -655,13 +598,13 @@ TEST_F(SerializeTest, emitChildNamespaces) {
extractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
Infos, this->Diags);
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
NamespaceInfo ExpectedParentA(EmptySID);
Reference RA(EmptySID, "A", InfoType::IT_namespace);
ExpectedParentA.Children.Namespaces.push_back(RA);
CheckNamespaceInfo(&ExpectedParentA, ParentA);
NamespaceInfo *ParentB = InfoAsNamespace(Infos[3]);
NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
NamespaceInfo ExpectedParentB(EmptySID);
Reference RB(EmptySID, "B", InfoType::IT_namespace, "A::B", "A");
ExpectedParentB.Children.Namespaces.push_back(RB);
@@ -674,10 +617,10 @@ TEST_F(SerializeTest, emitTypedefs) {
/*Public=*/false, Infos, this->Diags);
// First info will be the global namespace with the typedef in it.
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size());
const TypedefInfo &FirstTD = *GlobalNS1->Children.Typedefs.begin();
const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0];
EXPECT_EQ("MyInt", FirstTD.Name);
EXPECT_FALSE(FirstTD.IsUsing);
EXPECT_EQ("int", FirstTD.Underlying.Type.Name);
@@ -685,11 +628,11 @@ TEST_F(SerializeTest, emitTypedefs) {
// The second will be another global namespace with the using in it (the
// global namespace is duplicated because the items haven't been merged at the
// serialization phase of processing).
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size());
// Second is the "using" typedef.
const TypedefInfo &SecondTD = *GlobalNS2->Children.Typedefs.begin();
const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0];
EXPECT_EQ("MyDouble", SecondTD.Name);
EXPECT_TRUE(SecondTD.IsUsing);
EXPECT_EQ("double", SecondTD.Underlying.Type.Name);
@@ -704,10 +647,10 @@ TEST_F(SerializeTest, emitFunctionTemplate) {
/*Public=*/false, Infos, this->Diags);
// First info will be the global namespace.
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
ASSERT_EQ(1u, GlobalNS1->Children.Functions.size());
const FunctionInfo &Func1 = *GlobalNS1->Children.Functions.begin();
const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0];
EXPECT_EQ("GetFoo", Func1.Name);
ASSERT_TRUE(Func1.Template);
EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization.
@@ -719,11 +662,11 @@ TEST_F(SerializeTest, emitFunctionTemplate) {
// The second will be another global namespace with the function in it (the
// global namespace is duplicated because the items haven't been merged at the
// serialization phase of processing).
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
ASSERT_EQ(1u, GlobalNS2->Children.Functions.size());
// This one is a template specialization.
const FunctionInfo &Func2 = *GlobalNS2->Children.Functions.begin();
const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0];
EXPECT_EQ("GetFoo", Func2.Name);
ASSERT_TRUE(Func2.Template);
EXPECT_TRUE(Func2.Template->Params.empty()); // No template params.
@@ -751,7 +694,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
/*Public=*/false, Infos, this->Diags);
// First record.
const RecordInfo *Rec1 = InfoAsRecord(Infos[0]);
const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get());
EXPECT_EQ("MyTemplate", Rec1->Name);
ASSERT_TRUE(Rec1->Template);
EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization.
@@ -761,7 +704,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ("int I", Rec1->Template->Params[0].Contents);
// Second record.
const RecordInfo *Rec2 = InfoAsRecord(Infos[2]);
const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get());
EXPECT_EQ("MyTemplate", Rec2->Name);
ASSERT_TRUE(Rec2->Template);
EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params.
@@ -773,7 +716,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf);
// Third record.
const RecordInfo *Rec3 = InfoAsRecord(Infos[4]);
const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get());
EXPECT_EQ("OtherTemplate", Rec3->Name);
ASSERT_TRUE(Rec3->Template);
@@ -783,7 +726,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents);
// Fourth record.
const RecordInfo *Rec4 = InfoAsRecord(Infos[6]);
const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get());
EXPECT_EQ("OtherTemplate", Rec3->Name);
ASSERT_TRUE(Rec4->Template);
ASSERT_TRUE(Rec4->Template->Specialization);

View File

@@ -28,25 +28,20 @@ TEST_F(YAMLGeneratorTest, emitNamespaceYAML) {
NamespaceInfo I;
I.Name = "Namespace";
I.Path = "path/to/A";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
"path::to::A::Namespace::ChildNamespace",
"path/to/A/Namespace");
I.Children.Namespaces.push_back(NewNamespace);
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::Namespace::ChildStruct",
"path/to/A/Namespace");
I.Children.Records.push_back(ChildStruct);
FunctionInfo F;
F.Name = "OneFunction";
F.Access = AccessSpecifier::AS_none;
I.Children.Functions.push_back(F);
EnumInfo E;
E.Name = "OneEnum";
I.Children.Enums.push_back(E);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::Namespace::ChildStruct",
"path/to/A/Namespace");
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "OneEnum";
auto G = getYAMLGenerator();
assert(G);
@@ -90,14 +85,12 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
I.Name = "r";
I.Path = "path/to/A";
I.IsTypeDef = true;
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
// Member documentation.
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
@@ -106,39 +99,26 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
CommentInfo TopCommentChildren[] = {
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
M.Description.push_back(TopComment);
MemberTypeInfo MemArr[] = {std::move(M)};
I.Members = llvm::ArrayRef(MemArr);
I.Members.back().Description.push_back(std::move(TopComment));
I.TagType = TagTypeKind::Class;
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
true);
FunctionInfo F;
F.Name = "InheritedFunctionOne";
B.Children.Functions.push_back(F);
MemberTypeInfo BMem[] = {
MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_private)};
B.Members = llvm::ArrayRef(BMem);
BaseRecordInfo Bases[] = {std::move(B)};
I.Bases = llvm::ArrayRef(Bases);
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
AccessSpecifier::AS_public, true);
I.Bases.back().Children.Functions.emplace_back();
I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";
I.Bases.back().Members.emplace_back(TypeInfo("int"), "N",
AccessSpecifier::AS_private);
// F is in the global namespace
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")};
I.Parents = llvm::ArrayRef(Parents);
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record,
"path::to::G::G", "path/to/G")};
I.VirtualParents = llvm::ArrayRef(VParents);
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
"path::to::G::G", "path/to/G");
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::r::ChildStruct", "path/to/A/r");
I.Children.Records.push_back(ChildStruct);
FunctionInfo F2;
F2.Name = "OneFunction";
I.Children.Functions.push_back(F2);
EnumInfo E;
E.Name = "OneEnum";
I.Children.Enums.push_back(E);
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
"path::to::A::r::ChildStruct", "path/to/A/r");
I.Children.Functions.emplace_back();
I.Children.Functions.back().Name = "OneFunction";
I.Children.Enums.emplace_back();
I.Children.Enums.back().Name = "OneEnum";
auto G = getYAMLGenerator();
assert(G);
@@ -225,22 +205,17 @@ ChildEnums:
TEST_F(YAMLGeneratorTest, emitFunctionYAML) {
FunctionInfo I;
I.Name = "f";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
I.Access = AccessSpecifier::AS_none;
I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default));
FieldTypeInfo P1(TypeInfo("int"), "P");
FieldTypeInfo D(TypeInfo("double"), "D");
D.DefaultValue = "2.0 * M_PI";
FieldTypeInfo Params[] = {std::move(P1), std::move(D)};
I.Params = llvm::ArrayRef(Params);
I.Params.emplace_back(TypeInfo("int"), "P");
I.Params.emplace_back(TypeInfo("double"), "D");
I.Params.back().DefaultValue = "2.0 * M_PI";
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -295,15 +270,12 @@ ReturnType:
TEST_F(YAMLGeneratorTest, emitSimpleEnumYAML) {
EnumInfo I;
I.Name = "e";
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
I.Namespace = llvm::ArrayRef(Ns);
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, 10, "test.cpp");
Location Loc1(12, 12, "test.cpp");
I.Loc.push_back(Loc1);
I.Loc.emplace_back(12, 12, "test.cpp");
EnumValueInfo EV[] = {EnumValueInfo("X")};
I.Members = llvm::ArrayRef(EV);
I.Members.emplace_back("X");
I.Scoped = false;
auto G = getYAMLGenerator();
@@ -340,8 +312,7 @@ TEST_F(YAMLGeneratorTest, enumTypedScopedEnumYAML) {
EnumInfo I;
I.Name = "e";
EnumValueInfo EV[] = {EnumValueInfo("X", "-9876", "FOO_BAR + 2")};
I.Members = llvm::ArrayRef(EV);
I.Members.emplace_back("X", "-9876", "FOO_BAR + 2");
I.Scoped = true;
I.BaseType = TypeInfo("short");
@@ -399,9 +370,8 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
I.Name = "f";
I.DefLoc = Location(10, 10, "test.cpp");
I.ReturnType = TypeInfo("void");
FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I"),
FieldTypeInfo(TypeInfo("int"), "J")};
I.Params = llvm::ArrayRef(Params);
I.Params.emplace_back(TypeInfo("int"), "I");
I.Params.emplace_back(TypeInfo("int"), "J");
I.Access = AccessSpecifier::AS_none;
// BlankLine
@@ -474,7 +444,7 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
Verbatim, ParamOut, ParamIn, Return};
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
I.Description.push_back(Top);
I.Description.emplace_back(std::move(Top));
auto G = getYAMLGenerator();
assert(G);