CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
353 lines
13 KiB
C++
353 lines
13 KiB
C++
//===-- clang-doc/BitcodeTest.cpp -----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "BitcodeReader.h"
|
|
#include "BitcodeWriter.h"
|
|
#include "ClangDocTest.h"
|
|
#include "Representation.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
|
#include "llvm/Bitstream/BitstreamReader.h"
|
|
#include "llvm/Bitstream/BitstreamWriter.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace doc {
|
|
|
|
template <typename T>
|
|
static std::string writeInfo(T &I, DiagnosticsEngine &Diags) {
|
|
SmallString<2048> Buffer;
|
|
llvm::BitstreamWriter Stream(Buffer);
|
|
ClangDocBitcodeWriter Writer(Stream, Diags);
|
|
Writer.emitBlock(I);
|
|
return Buffer.str().str();
|
|
}
|
|
|
|
static std::string writeInfo(Info *I, DiagnosticsEngine &Diags) {
|
|
switch (I->IT) {
|
|
case InfoType::IT_namespace:
|
|
return writeInfo(*static_cast<NamespaceInfo *>(I), Diags);
|
|
case InfoType::IT_record:
|
|
return writeInfo(*static_cast<RecordInfo *>(I), Diags);
|
|
case InfoType::IT_enum:
|
|
return writeInfo(*static_cast<EnumInfo *>(I), Diags);
|
|
case InfoType::IT_function:
|
|
return writeInfo(*static_cast<FunctionInfo *>(I), Diags);
|
|
case InfoType::IT_typedef:
|
|
return writeInfo(*static_cast<TypedefInfo *>(I), Diags);
|
|
case InfoType::IT_concept:
|
|
return writeInfo(*static_cast<ConceptInfo *>(I), Diags);
|
|
case InfoType::IT_variable:
|
|
return writeInfo(*static_cast<VarInfo *>(I), Diags);
|
|
case InfoType::IT_friend:
|
|
return writeInfo(*static_cast<FriendInfo *>(I), Diags);
|
|
case InfoType::IT_default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
static std::vector<Info *> readInfo(StringRef Bitcode, size_t NumInfos,
|
|
DiagnosticsEngine &Diags) {
|
|
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);
|
|
return std::move(Infos.get());
|
|
}
|
|
|
|
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);
|
|
|
|
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
|
|
InfoNode<Reference> NewNamespaceNode(&NewNamespace);
|
|
I.Children.Namespaces.push_back(NewNamespaceNode);
|
|
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
|
InfoNode<Reference> ChildStructNode(&ChildStruct);
|
|
I.Children.Records.push_back(ChildStructNode);
|
|
FunctionInfo FI;
|
|
InfoNode<FunctionInfo> FINode(&FI);
|
|
I.Children.Functions.push_back(FINode);
|
|
EnumInfo EI;
|
|
InfoNode<EnumInfo> EINode(&EI);
|
|
I.Children.Enums.push_back(EINode);
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitRecordInfoBitcode) {
|
|
RecordInfo I;
|
|
I.Name = "r";
|
|
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
|
I.Namespace = llvm::ArrayRef(Ns);
|
|
|
|
I.DefLoc = Location(10, 10, "test.cpp");
|
|
Location Loc1(12, 12, "test.cpp");
|
|
InfoNode<Location> Loc1Node(&Loc1);
|
|
I.Loc.push_back(Loc1Node);
|
|
|
|
MemberTypeInfo M(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;
|
|
InfoNode<FunctionInfo> FINode(&FI);
|
|
B.Children.Functions.push_back(FINode);
|
|
MemberTypeInfo BM(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
|
|
|
// Documentation for the data member.
|
|
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
|
|
"Value of the thing.",
|
|
"ParagraphComment")};
|
|
CommentInfo TopCommentChildren[] = {
|
|
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
|
|
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
|
|
InfoNode<CommentInfo> TopCommentNode(&TopComment);
|
|
BM.Description.push_back(TopCommentNode);
|
|
MemberTypeInfo BMem[] = {std::move(BM)};
|
|
B.Members = llvm::ArrayRef(BMem);
|
|
BaseRecordInfo Bases[] = {std::move(B)};
|
|
I.Bases = llvm::ArrayRef(Bases);
|
|
|
|
MemberTypeInfo Mem[] = {std::move(M)};
|
|
I.Members = llvm::ArrayRef(Mem);
|
|
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)};
|
|
I.Parents = llvm::ArrayRef(Parents);
|
|
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)};
|
|
I.VirtualParents = llvm::ArrayRef(VParents);
|
|
|
|
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
|
InfoNode<Reference> ChildStructNode(&ChildStruct);
|
|
I.Children.Records.push_back(ChildStructNode);
|
|
FunctionInfo FI2;
|
|
InfoNode<FunctionInfo> FI2Node(&FI2);
|
|
I.Children.Functions.push_back(FI2Node);
|
|
EnumInfo EI;
|
|
InfoNode<EnumInfo> EINode(&EI);
|
|
I.Children.Enums.push_back(EINode);
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckRecordInfo(&I, InfoAsRecord(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
|
|
FunctionInfo I;
|
|
I.Name = "f";
|
|
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
|
I.Namespace = llvm::ArrayRef(Ns);
|
|
|
|
I.DefLoc = Location(10, 10, "test.cpp");
|
|
Location Loc1(12, 12, "test.cpp");
|
|
InfoNode<Location> Loc1Node(&Loc1);
|
|
I.Loc.push_back(Loc1Node);
|
|
|
|
I.ReturnType = TypeInfo("void");
|
|
FieldTypeInfo P(TypeInfo("int"), "P");
|
|
FieldTypeInfo Params[] = {std::move(P)};
|
|
I.Params = llvm::ArrayRef(Params);
|
|
|
|
I.Access = AccessSpecifier::AS_none;
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitMethodInfoBitcode) {
|
|
FunctionInfo I;
|
|
I.Name = "f";
|
|
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
|
I.Namespace = llvm::ArrayRef(Ns);
|
|
|
|
I.DefLoc = Location(10, 10, "test.cpp");
|
|
Location Loc1(12, 12, "test.cpp");
|
|
InfoNode<Location> Loc1Node(&Loc1);
|
|
I.Loc.push_back(Loc1Node);
|
|
|
|
I.ReturnType = TypeInfo("void");
|
|
FieldTypeInfo P(TypeInfo("int"), "P");
|
|
FieldTypeInfo Params[] = {std::move(P)};
|
|
I.Params = llvm::ArrayRef(Params);
|
|
I.IsMethod = true;
|
|
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
|
|
|
|
I.Access = AccessSpecifier::AS_public;
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitEnumInfoBitcode) {
|
|
EnumInfo I;
|
|
I.Name = "e";
|
|
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
|
I.Namespace = llvm::ArrayRef(Ns);
|
|
|
|
I.DefLoc = Location(10, 10, "test.cpp");
|
|
Location Loc1(12, 12, "test.cpp");
|
|
InfoNode<Location> Loc1Node(&Loc1);
|
|
I.Loc.push_back(Loc1Node);
|
|
|
|
EnumValueInfo EV("X");
|
|
EnumValueInfo Mems[] = {std::move(EV)};
|
|
I.Members = llvm::ArrayRef(Mems);
|
|
I.Scoped = true;
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckEnumInfo(&I, InfoAsEnum(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
|
|
TypedefInfo I;
|
|
I.Name = "MyInt";
|
|
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
|
I.Namespace = llvm::ArrayRef(Ns);
|
|
|
|
I.DefLoc = Location(10, 10, "test.cpp");
|
|
I.Underlying = TypeInfo("unsigned");
|
|
I.IsUsing = true;
|
|
|
|
CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
|
|
CommentInfo TopChildren[] = {
|
|
CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)};
|
|
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
|
|
|
|
InfoNode<CommentInfo> TopNode(&Top);
|
|
I.Description.push_back(TopNode);
|
|
|
|
std::string WriteResult = writeInfo(&I, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0]));
|
|
|
|
// Check one with no IsUsing set, no description, and no definition location.
|
|
TypedefInfo I2;
|
|
I2.Name = "SomethingElse";
|
|
I2.IsUsing = false;
|
|
I2.Underlying = TypeInfo("int");
|
|
|
|
WriteResult = writeInfo(&I2, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0]));
|
|
}
|
|
|
|
TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
|
|
FunctionInfo F;
|
|
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);
|
|
|
|
// BlankLine
|
|
CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
|
|
CommentInfo BlankLine(CommentKind::CK_ParagraphComment, BlankChildren);
|
|
|
|
// Brief
|
|
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
|
|
" Brief description.",
|
|
"ParagraphComment")};
|
|
CommentInfo Brief(CommentKind::CK_ParagraphComment, BriefChildren);
|
|
|
|
// Extended
|
|
CommentInfo ExtChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
|
|
" Extended description that"),
|
|
CommentInfo(CommentKind::CK_TextComment, {},
|
|
" continues onto the next line.")};
|
|
CommentInfo Extended(CommentKind::CK_ParagraphComment, ExtChildren);
|
|
|
|
// HTML
|
|
StringRef HtmlKeys[] = {"class"};
|
|
StringRef HtmlValues[] = {"test"};
|
|
CommentInfo HtmlStart(CommentKind::CK_HTMLStartTagComment, {}, "", "ul", "",
|
|
"", "", false, false, HtmlKeys, HtmlValues);
|
|
CommentInfo HtmlStartLi(CommentKind::CK_HTMLStartTagComment, {}, "", "li");
|
|
CommentInfo HtmlEnd(CommentKind::CK_HTMLEndTagComment, {}, "", "ul", "", "",
|
|
"", false, true);
|
|
|
|
CommentInfo HtmlChildren[] = {
|
|
CommentInfo(CommentKind::CK_TextComment), HtmlStart, HtmlStartLi,
|
|
CommentInfo(CommentKind::CK_TextComment, {}, " Testing."), HtmlEnd};
|
|
CommentInfo HTML(CommentKind::CK_ParagraphComment, HtmlChildren);
|
|
|
|
// Verbatim
|
|
CommentInfo VerbLine(CommentKind::CK_VerbatimBlockLineComment, {},
|
|
" The description continues.");
|
|
CommentInfo VerbChildren[] = {VerbLine};
|
|
CommentInfo Verbatim(CommentKind::CK_VerbatimBlockComment, VerbChildren, "",
|
|
"verbatim", "endverbatim");
|
|
|
|
// ParamOut
|
|
CommentInfo ParamOutParaChildren[] = {
|
|
CommentInfo(CommentKind::CK_TextComment),
|
|
CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter.")};
|
|
CommentInfo ParamOutPara(CommentKind::CK_ParagraphComment,
|
|
ParamOutParaChildren);
|
|
CommentInfo ParamOutChildren[] = {ParamOutPara};
|
|
CommentInfo ParamOut(CommentKind::CK_ParamCommandComment, ParamOutChildren,
|
|
"", "", "", "[out]", "I", true);
|
|
|
|
// ParamIn
|
|
CommentInfo ParamInParaChildren[] = {
|
|
CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter."),
|
|
CommentInfo(CommentKind::CK_TextComment)};
|
|
CommentInfo ParamInPara(CommentKind::CK_ParagraphComment,
|
|
ParamInParaChildren);
|
|
CommentInfo ParamInChildren[] = {ParamInPara};
|
|
CommentInfo ParamIn(CommentKind::CK_ParamCommandComment, ParamInChildren, "",
|
|
"", "", "[in]", "J");
|
|
|
|
// Return
|
|
CommentInfo ReturnParaChildren[] = {
|
|
CommentInfo(CommentKind::CK_TextComment, {}, "void")};
|
|
CommentInfo ReturnPara(CommentKind::CK_ParagraphComment, ReturnParaChildren);
|
|
CommentInfo ReturnChildren[] = {ReturnPara};
|
|
CommentInfo Return(CommentKind::CK_BlockCommandComment, ReturnChildren, "",
|
|
"return", "", "", "", true);
|
|
|
|
CommentInfo TopChildren[] = {BlankLine, Brief, Extended, HTML,
|
|
Verbatim, ParamOut, ParamIn, Return};
|
|
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
|
|
|
|
InfoNode<CommentInfo> TopNode(&Top);
|
|
F.Description.push_back(TopNode);
|
|
|
|
std::string WriteResult = writeInfo(&F, this->Diags);
|
|
EXPECT_TRUE(WriteResult.size() > 0);
|
|
std::vector<Info *> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
|
|
|
CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0]));
|
|
}
|
|
|
|
} // namespace doc
|
|
} // namespace clang
|