Skip to content

Commit 8dd16ca

Browse files
committed
[clang-doc] serialize friends
1 parent 111fe87 commit 8dd16ca

File tree

13 files changed

+234
-45
lines changed

13 files changed

+234
-45
lines changed

clang-tools-extra/clang-doc/BitcodeReader.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field,
9494
case InfoType::IT_typedef:
9595
case InfoType::IT_concept:
9696
case InfoType::IT_variable:
97+
case InfoType::IT_friend:
9798
Field = IT;
9899
return llvm::Error::success();
99100
}
@@ -111,6 +112,7 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
111112
case FieldId::F_child_namespace:
112113
case FieldId::F_child_record:
113114
case FieldId::F_concept:
115+
case FieldId::F_friend:
114116
case FieldId::F_default:
115117
Field = F;
116118
return llvm::Error::success();
@@ -450,6 +452,15 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
450452
}
451453
}
452454

455+
static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
456+
FriendInfo *F) {
457+
if (ID == FRIEND_IS_CLASS) {
458+
return decodeRecord(R, F->IsClass, Blob);
459+
}
460+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
461+
"invalid field for Friend");
462+
}
463+
453464
template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
454465
return llvm::createStringError(llvm::inconvertibleErrorCode(),
455466
"invalid type cannot contain CommentInfo");
@@ -525,6 +536,18 @@ template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
525536
return llvm::Error::success();
526537
}
527538

539+
template <> llvm::Error addTypeInfo(FriendInfo *I, FieldTypeInfo &&T) {
540+
if (!I->Params)
541+
I->Params.emplace();
542+
I->Params->emplace_back(std::move(T));
543+
return llvm::Error::success();
544+
}
545+
546+
template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
547+
I->ReturnType.emplace(std::move(T));
548+
return llvm::Error::success();
549+
}
550+
528551
template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
529552
I->BaseType = std::move(T);
530553
return llvm::Error::success();
@@ -667,6 +690,16 @@ llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) {
667690
"ConstraintInfo cannot contain this Reference");
668691
}
669692

693+
template <>
694+
llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
695+
if (F == FieldId::F_friend) {
696+
Friend->Ref = std::move(R);
697+
return llvm::Error::success();
698+
}
699+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
700+
"Friend cannot contain this Reference");
701+
}
702+
670703
template <typename T, typename ChildInfoType>
671704
static void addChild(T I, ChildInfoType &&R) {
672705
llvm::errs() << "invalid child type for info";
@@ -700,6 +733,9 @@ template <> void addChild(RecordInfo *I, EnumInfo &&R) {
700733
template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
701734
I->Children.Typedefs.emplace_back(std::move(R));
702735
}
736+
template <> void addChild(RecordInfo *I, FriendInfo &&R) {
737+
I->Friends.emplace_back(std::move(R));
738+
}
703739

704740
// Other types of children:
705741
template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
@@ -741,6 +777,9 @@ template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
741777
template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
742778
I->Template = std::move(P);
743779
}
780+
template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
781+
I->Template.emplace(std::move(P));
782+
}
744783

745784
// Template specializations go only into template records.
746785
template <typename T>
@@ -921,6 +960,10 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
921960
case BI_VAR_BLOCK_ID: {
922961
return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));
923962
}
963+
case BI_FRIEND_BLOCK_ID: {
964+
return handleSubBlock<FriendInfo>(ID, I,
965+
CreateAddFunc(addChild<T, FriendInfo>));
966+
}
924967
default:
925968
return llvm::createStringError(llvm::inconvertibleErrorCode(),
926969
"invalid subblock type");
@@ -1032,6 +1075,8 @@ ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
10321075
return createInfo<FunctionInfo>(ID);
10331076
case BI_VAR_BLOCK_ID:
10341077
return createInfo<VarInfo>(ID);
1078+
case BI_FRIEND_BLOCK_ID:
1079+
return createInfo<FriendInfo>(ID);
10351080
default:
10361081
return llvm::createStringError(llvm::inconvertibleErrorCode(),
10371082
"cannot create info");
@@ -1072,6 +1117,7 @@ ClangDocBitcodeReader::readBitcode() {
10721117
case BI_TYPEDEF_BLOCK_ID:
10731118
case BI_CONCEPT_BLOCK_ID:
10741119
case BI_VAR_BLOCK_ID:
1120+
case BI_FRIEND_BLOCK_ID:
10751121
case BI_FUNCTION_BLOCK_ID: {
10761122
auto InfoOrErr = readBlockToInfo(ID);
10771123
if (!InfoOrErr)

clang-tools-extra/clang-doc/BitcodeWriter.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
131131
{BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"},
132132
{BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"},
133133
{BI_CONCEPT_BLOCK_ID, "ConceptBlock"},
134-
{BI_VAR_BLOCK_ID, "VarBlock"}};
134+
{BI_VAR_BLOCK_ID, "VarBlock"},
135+
{BI_FRIEND_BLOCK_ID, "FriendBlock"}};
135136
assert(Inits.size() == BlockIdCount);
136137
for (const auto &Init : Inits)
137138
BlockIdNameMap[Init.first] = Init.second;
@@ -224,7 +225,8 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
224225
{VAR_USR, {"USR", &genSymbolIdAbbrev}},
225226
{VAR_NAME, {"Name", &genStringAbbrev}},
226227
{VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
227-
{VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}}};
228+
{VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
229+
{FRIEND_IS_CLASS, {"IsClass", &genBoolAbbrev}}};
228230

229231
assert(Inits.size() == RecordIdCount);
230232
for (const auto &Init : Inits) {
@@ -293,7 +295,8 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
293295
CONCEPT_CONSTRAINT_EXPRESSION}},
294296
// Constraint Block
295297
{BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}},
296-
{BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}}};
298+
{BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}},
299+
{BI_FRIEND_BLOCK_ID, {FRIEND_IS_CLASS}}};
297300

298301
// AbbreviationMap
299302

@@ -476,6 +479,19 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
476479
emitRecord((unsigned)Field, REFERENCE_FIELD);
477480
}
478481

482+
void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) {
483+
StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);
484+
emitBlock(R.Ref, FieldId::F_friend);
485+
emitRecord(R.IsClass, FRIEND_IS_CLASS);
486+
if (R.Template)
487+
emitBlock(*R.Template);
488+
if (R.Params)
489+
for (const auto &P : *R.Params)
490+
emitBlock(P);
491+
if (R.ReturnType)
492+
emitBlock(*R.ReturnType);
493+
}
494+
479495
void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
480496
StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
481497
emitBlock(T.Type, FieldId::F_type);
@@ -628,6 +644,8 @@ void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
628644
emitBlock(C);
629645
if (I.Template)
630646
emitBlock(*I.Template);
647+
for (const auto &C : I.Friends)
648+
emitBlock(C);
631649
}
632650

633651
void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
@@ -744,6 +762,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
744762
case InfoType::IT_variable:
745763
emitBlock(*static_cast<VarInfo *>(I));
746764
break;
765+
case InfoType::IT_friend:
766+
emitBlock(*static_cast<FriendInfo *>(I));
767+
break;
747768
case InfoType::IT_default:
748769
llvm::errs() << "Unexpected info, unable to write.\n";
749770
return true;

clang-tools-extra/clang-doc/BitcodeWriter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ enum BlockId {
7070
BI_TYPEDEF_BLOCK_ID,
7171
BI_CONCEPT_BLOCK_ID,
7272
BI_VAR_BLOCK_ID,
73+
BI_FRIEND_BLOCK_ID,
7374
BI_LAST,
7475
BI_FIRST = BI_VERSION_BLOCK_ID
7576
};
@@ -153,6 +154,7 @@ enum RecordId {
153154
VAR_NAME,
154155
VAR_DEFLOCATION,
155156
VAR_IS_STATIC,
157+
FRIEND_IS_CLASS,
156158
RI_LAST,
157159
RI_FIRST = VERSION
158160
};
@@ -169,7 +171,8 @@ enum class FieldId {
169171
F_type,
170172
F_child_namespace,
171173
F_child_record,
172-
F_concept
174+
F_concept,
175+
F_friend
173176
};
174177

175178
class ClangDocBitcodeWriter {
@@ -201,6 +204,7 @@ class ClangDocBitcodeWriter {
201204
void emitBlock(const ConceptInfo &T);
202205
void emitBlock(const ConstraintInfo &T);
203206
void emitBlock(const Reference &B, FieldId F);
207+
void emitBlock(const FriendInfo &R);
204208
void emitBlock(const VarInfo &B);
205209

206210
private:

clang-tools-extra/clang-doc/HTMLGenerator.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
987987
break;
988988
case InfoType::IT_concept:
989989
case InfoType::IT_variable:
990+
case InfoType::IT_friend:
990991
break;
991992
case InfoType::IT_default:
992993
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -1018,6 +1019,8 @@ static std::string getRefType(InfoType IT) {
10181019
return "concept";
10191020
case InfoType::IT_variable:
10201021
return "variable";
1022+
case InfoType::IT_friend:
1023+
return "friend";
10211024
}
10221025
llvm_unreachable("Unknown InfoType");
10231026
}

clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
588588
case InfoType::IT_concept:
589589
break;
590590
case InfoType::IT_variable:
591+
case InfoType::IT_friend:
591592
break;
592593
case InfoType::IT_default:
593594
return createStringError(inconvertibleErrorCode(), "unexpected InfoType");

clang-tools-extra/clang-doc/JSONGenerator.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ static void serializeArray(const Container &Records, Object &Obj,
3939
static auto SerializeInfoLambda = [](const auto &Info, Object &Object) {
4040
serializeInfo(Info, Object);
4141
};
42-
static auto SerializeReferenceLambda = [](const Reference &Ref,
43-
Object &Object) {
42+
static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) {
4443
serializeReference(Ref, Object);
4544
};
4645

@@ -365,6 +364,22 @@ static void serializeInfo(const BaseRecordInfo &I, Object &Obj,
365364
Obj["IsParent"] = I.IsParent;
366365
}
367366

367+
static void serializeInfo(const FriendInfo &I, Object &Obj) {
368+
auto FriendRef = Object();
369+
serializeReference(I.Ref, FriendRef);
370+
Obj["Reference"] = std::move(FriendRef);
371+
Obj["IsClass"] = I.IsClass;
372+
if (I.Template)
373+
serializeInfo(I.Template.value(), Obj);
374+
if (I.Params)
375+
serializeArray(I.Params.value(), Obj, "Params", SerializeInfoLambda);
376+
if (I.ReturnType) {
377+
auto ReturnTypeObj = Object();
378+
serializeInfo(I.ReturnType.value(), ReturnTypeObj);
379+
Obj["ReturnType"] = std::move(ReturnTypeObj);
380+
}
381+
}
382+
368383
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
369384
const std::optional<StringRef> &RepositoryUrl) {
370385
serializeCommonAttributes(I, Obj, RepositoryUrl);
@@ -436,6 +451,9 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
436451
if (I.Template)
437452
serializeInfo(I.Template.value(), Obj);
438453

454+
if (!I.Friends.empty())
455+
serializeArray(I.Friends, Obj, "Friends", SerializeInfoLambda);
456+
439457
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
440458
}
441459

@@ -525,6 +543,7 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
525543
case InfoType::IT_function:
526544
case InfoType::IT_typedef:
527545
case InfoType::IT_variable:
546+
case InfoType::IT_friend:
528547
break;
529548
case InfoType::IT_default:
530549
return createStringError(inconvertibleErrorCode(), "unexpected info type");

clang-tools-extra/clang-doc/MDGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
378378
case InfoType::IT_variable:
379379
Type = "Variable";
380380
break;
381+
case InfoType::IT_friend:
382+
Type = "Friend";
383+
break;
381384
case InfoType::IT_default:
382385
Type = "Other";
383386
}
@@ -472,6 +475,7 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
472475
break;
473476
case InfoType::IT_concept:
474477
case InfoType::IT_variable:
478+
case InfoType::IT_friend:
475479
break;
476480
case InfoType::IT_default:
477481
return createStringError(llvm::inconvertibleErrorCode(),

clang-tools-extra/clang-doc/Representation.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ mergeInfos(std::vector<std::unique_ptr<Info>> &Values) {
147147
return reduce<ConceptInfo>(Values);
148148
case InfoType::IT_variable:
149149
return reduce<VarInfo>(Values);
150+
case InfoType::IT_friend:
151+
return reduce<FriendInfo>(Values);
150152
case InfoType::IT_default:
151153
return llvm::createStringError(llvm::inconvertibleErrorCode(),
152154
"unexpected info type");
@@ -247,6 +249,15 @@ void Reference::merge(Reference &&Other) {
247249
Path = Other.Path;
248250
}
249251

252+
bool FriendInfo::mergeable(const FriendInfo &Other) {
253+
return Ref.USR == Other.Ref.USR && Ref.Name == Other.Ref.Name;
254+
}
255+
256+
void FriendInfo::merge(FriendInfo &&Other) {
257+
assert(mergeable(Other));
258+
Ref.merge(std::move(Other.Ref));
259+
}
260+
250261
void Info::mergeBase(Info &&Other) {
251262
assert(mergeable(Other));
252263
if (USR == EmptySID)
@@ -313,6 +324,8 @@ void RecordInfo::merge(RecordInfo &&Other) {
313324
Parents = std::move(Other.Parents);
314325
if (VirtualParents.empty())
315326
VirtualParents = std::move(Other.VirtualParents);
327+
if (Friends.empty())
328+
Friends = std::move(Other.Friends);
316329
// Reduce children if necessary.
317330
reduceChildren(Children.Records, std::move(Other.Children.Records));
318331
reduceChildren(Children.Functions, std::move(Other.Children.Functions));
@@ -422,6 +435,9 @@ llvm::SmallString<16> Info::extractName() const {
422435
case InfoType::IT_variable:
423436
return llvm::SmallString<16>("@nonymous_variable_" +
424437
toHex(llvm::toStringRef(USR)));
438+
case InfoType::IT_friend:
439+
return llvm::SmallString<16>("@nonymous_friend_" +
440+
toHex(llvm::toStringRef(USR)));
425441
case InfoType::IT_default:
426442
return llvm::SmallString<16>("@nonymous_" + toHex(llvm::toStringRef(USR)));
427443
}

clang-tools-extra/clang-doc/Representation.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ enum class InfoType {
4646
IT_enum,
4747
IT_typedef,
4848
IT_concept,
49-
IT_variable
49+
IT_variable,
50+
IT_friend
5051
};
5152

5253
enum class CommentKind {
@@ -379,6 +380,22 @@ struct SymbolInfo : public Info {
379380
bool IsStatic = false;
380381
};
381382

383+
struct FriendInfo : SymbolInfo {
384+
FriendInfo() : SymbolInfo(InfoType::IT_friend) {}
385+
FriendInfo(SymbolID USR) : SymbolInfo(InfoType::IT_friend, USR) {}
386+
FriendInfo(const InfoType IT, const SymbolID &USR,
387+
const StringRef Name = StringRef())
388+
: SymbolInfo(IT, USR, Name) {}
389+
bool mergeable(const FriendInfo &Other);
390+
void merge(FriendInfo &&Other);
391+
392+
Reference Ref;
393+
std::optional<TemplateInfo> Template;
394+
std::optional<TypeInfo> ReturnType;
395+
std::optional<SmallVector<FieldTypeInfo, 4>> Params;
396+
bool IsClass = false;
397+
};
398+
382399
struct VarInfo : SymbolInfo {
383400
VarInfo() : SymbolInfo(InfoType::IT_variable) {}
384401
explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {}
@@ -454,6 +471,8 @@ struct RecordInfo : public SymbolInfo {
454471
Bases; // List of base/parent records; this includes inherited methods and
455472
// attributes
456473

474+
std::vector<FriendInfo> Friends;
475+
457476
ScopeChildren Children;
458477
};
459478

0 commit comments

Comments
 (0)