[clang-doc] serialize friends - #146165
Merged
Merged
Conversation
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Jun 27, 2025
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
ilovepi
reviewed
Jun 27, 2025
ilovepi
approved these changes
Jun 27, 2025
ilovepi
left a comment
Contributor
There was a problem hiding this comment.
LGTM, modulo formatting and 1 small suggestion.
evelez7
force-pushed
the
users/evelez7/clang-doc-precommit-friends
branch
from
June 27, 2025 23:19
bf66a99 to
111fe87
Compare
evelez7
force-pushed
the
users/evelez7/clang-doc-friends
branch
from
June 27, 2025 23:19
a373ecb to
8dd16ca
Compare
evelez7
marked this pull request as ready for review
June 30, 2025 16:50
Member
|
@llvm/pr-subscribers-clang-tools-extra Author: Erick Velez (evelez7) ChangesPatch is 24.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146165.diff 13 Files Affected:
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index fd6f40cff1a4e..2cbf8bf6b2879 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -94,6 +94,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field,
case InfoType::IT_typedef:
case InfoType::IT_concept:
case InfoType::IT_variable:
+ case InfoType::IT_friend:
Field = IT;
return llvm::Error::success();
}
@@ -111,6 +112,7 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
case FieldId::F_child_namespace:
case FieldId::F_child_record:
case FieldId::F_concept:
+ case FieldId::F_friend:
case FieldId::F_default:
Field = F;
return llvm::Error::success();
@@ -450,6 +452,15 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
}
}
+static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
+ FriendInfo *F) {
+ if (ID == FRIEND_IS_CLASS) {
+ return decodeRecord(R, F->IsClass, Blob);
+ }
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "invalid field for Friend");
+}
+
template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid type cannot contain CommentInfo");
@@ -525,6 +536,18 @@ template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
return llvm::Error::success();
}
+template <> llvm::Error addTypeInfo(FriendInfo *I, FieldTypeInfo &&T) {
+ if (!I->Params)
+ I->Params.emplace();
+ 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();
+}
+
template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
I->BaseType = std::move(T);
return llvm::Error::success();
@@ -667,6 +690,16 @@ llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) {
"ConstraintInfo cannot contain this Reference");
}
+template <>
+llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
+ if (F == FieldId::F_friend) {
+ Friend->Ref = std::move(R);
+ return llvm::Error::success();
+ }
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Friend cannot contain this Reference");
+}
+
template <typename T, typename ChildInfoType>
static void addChild(T I, ChildInfoType &&R) {
llvm::errs() << "invalid child type for info";
@@ -700,6 +733,9 @@ template <> void addChild(RecordInfo *I, EnumInfo &&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) {
@@ -741,6 +777,9 @@ template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
I->Template = std::move(P);
}
+template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
+ I->Template.emplace(std::move(P));
+}
// Template specializations go only into template records.
template <typename T>
@@ -921,6 +960,10 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
case BI_VAR_BLOCK_ID: {
return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));
}
+ case BI_FRIEND_BLOCK_ID: {
+ return handleSubBlock<FriendInfo>(ID, I,
+ CreateAddFunc(addChild<T, FriendInfo>));
+ }
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid subblock type");
@@ -1032,6 +1075,8 @@ ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
return createInfo<FunctionInfo>(ID);
case BI_VAR_BLOCK_ID:
return createInfo<VarInfo>(ID);
+ case BI_FRIEND_BLOCK_ID:
+ return createInfo<FriendInfo>(ID);
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"cannot create info");
@@ -1072,6 +1117,7 @@ ClangDocBitcodeReader::readBitcode() {
case BI_TYPEDEF_BLOCK_ID:
case BI_CONCEPT_BLOCK_ID:
case BI_VAR_BLOCK_ID:
+ case BI_FRIEND_BLOCK_ID:
case BI_FUNCTION_BLOCK_ID: {
auto InfoOrErr = readBlockToInfo(ID);
if (!InfoOrErr)
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index 006ddda1b75e7..3cc0d4ad332f0 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -131,7 +131,8 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
{BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"},
{BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"},
{BI_CONCEPT_BLOCK_ID, "ConceptBlock"},
- {BI_VAR_BLOCK_ID, "VarBlock"}};
+ {BI_VAR_BLOCK_ID, "VarBlock"},
+ {BI_FRIEND_BLOCK_ID, "FriendBlock"}};
assert(Inits.size() == BlockIdCount);
for (const auto &Init : Inits)
BlockIdNameMap[Init.first] = Init.second;
@@ -224,7 +225,8 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
{VAR_USR, {"USR", &genSymbolIdAbbrev}},
{VAR_NAME, {"Name", &genStringAbbrev}},
{VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
- {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}}};
+ {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}},
+ {FRIEND_IS_CLASS, {"IsClass", &genBoolAbbrev}}};
assert(Inits.size() == RecordIdCount);
for (const auto &Init : Inits) {
@@ -293,7 +295,8 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
CONCEPT_CONSTRAINT_EXPRESSION}},
// Constraint Block
{BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}},
- {BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}}};
+ {BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}},
+ {BI_FRIEND_BLOCK_ID, {FRIEND_IS_CLASS}}};
// AbbreviationMap
@@ -476,6 +479,19 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
emitRecord((unsigned)Field, REFERENCE_FIELD);
}
+void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) {
+ StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID);
+ emitBlock(R.Ref, FieldId::F_friend);
+ emitRecord(R.IsClass, FRIEND_IS_CLASS);
+ if (R.Template)
+ emitBlock(*R.Template);
+ if (R.Params)
+ for (const auto &P : *R.Params)
+ emitBlock(P);
+ if (R.ReturnType)
+ emitBlock(*R.ReturnType);
+}
+
void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
emitBlock(T.Type, FieldId::F_type);
@@ -628,6 +644,8 @@ void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
emitBlock(C);
if (I.Template)
emitBlock(*I.Template);
+ for (const auto &C : I.Friends)
+ emitBlock(C);
}
void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
@@ -744,6 +762,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
case InfoType::IT_variable:
emitBlock(*static_cast<VarInfo *>(I));
break;
+ case InfoType::IT_friend:
+ emitBlock(*static_cast<FriendInfo *>(I));
+ break;
case InfoType::IT_default:
llvm::errs() << "Unexpected info, unable to write.\n";
return true;
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h
index f1325094f957a..d09ec4ca34006 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.h
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -70,6 +70,7 @@ enum BlockId {
BI_TYPEDEF_BLOCK_ID,
BI_CONCEPT_BLOCK_ID,
BI_VAR_BLOCK_ID,
+ BI_FRIEND_BLOCK_ID,
BI_LAST,
BI_FIRST = BI_VERSION_BLOCK_ID
};
@@ -153,6 +154,7 @@ enum RecordId {
VAR_NAME,
VAR_DEFLOCATION,
VAR_IS_STATIC,
+ FRIEND_IS_CLASS,
RI_LAST,
RI_FIRST = VERSION
};
@@ -169,7 +171,8 @@ enum class FieldId {
F_type,
F_child_namespace,
F_child_record,
- F_concept
+ F_concept,
+ F_friend
};
class ClangDocBitcodeWriter {
@@ -201,6 +204,7 @@ class ClangDocBitcodeWriter {
void emitBlock(const ConceptInfo &T);
void emitBlock(const ConstraintInfo &T);
void emitBlock(const Reference &B, FieldId F);
+ void emitBlock(const FriendInfo &R);
void emitBlock(const VarInfo &B);
private:
diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
index c4303d287da9e..8294ff9118558 100644
--- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -987,6 +987,7 @@ llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
break;
case InfoType::IT_concept:
case InfoType::IT_variable:
+ case InfoType::IT_friend:
break;
case InfoType::IT_default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -1018,6 +1019,8 @@ static std::string getRefType(InfoType IT) {
return "concept";
case InfoType::IT_variable:
return "variable";
+ case InfoType::IT_friend:
+ return "friend";
}
llvm_unreachable("Unknown InfoType");
}
diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index c611c946b3937..7aeaa1b7cf67d 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -588,6 +588,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
case InfoType::IT_concept:
break;
case InfoType::IT_variable:
+ case InfoType::IT_friend:
break;
case InfoType::IT_default:
return createStringError(inconvertibleErrorCode(), "unexpected InfoType");
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 1f6167f7f9b8d..0e1a0cc347e45 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -39,8 +39,7 @@ static void serializeArray(const Container &Records, Object &Obj,
static auto SerializeInfoLambda = [](const auto &Info, Object &Object) {
serializeInfo(Info, Object);
};
-static auto SerializeReferenceLambda = [](const Reference &Ref,
- Object &Object) {
+static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) {
serializeReference(Ref, Object);
};
@@ -365,6 +364,22 @@ static void serializeInfo(const BaseRecordInfo &I, Object &Obj,
Obj["IsParent"] = I.IsParent;
}
+static void serializeInfo(const FriendInfo &I, Object &Obj) {
+ auto FriendRef = Object();
+ serializeReference(I.Ref, FriendRef);
+ Obj["Reference"] = std::move(FriendRef);
+ Obj["IsClass"] = I.IsClass;
+ if (I.Template)
+ serializeInfo(I.Template.value(), Obj);
+ if (I.Params)
+ serializeArray(I.Params.value(), Obj, "Params", SerializeInfoLambda);
+ if (I.ReturnType) {
+ auto ReturnTypeObj = Object();
+ serializeInfo(I.ReturnType.value(), ReturnTypeObj);
+ Obj["ReturnType"] = std::move(ReturnTypeObj);
+ }
+}
+
static void serializeInfo(const RecordInfo &I, json::Object &Obj,
const std::optional<StringRef> &RepositoryUrl) {
serializeCommonAttributes(I, Obj, RepositoryUrl);
@@ -436,6 +451,9 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
if (I.Template)
serializeInfo(I.Template.value(), Obj);
+ if (!I.Friends.empty())
+ serializeArray(I.Friends, Obj, "Friends", SerializeInfoLambda);
+
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
}
@@ -525,6 +543,7 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
case InfoType::IT_function:
case InfoType::IT_typedef:
case InfoType::IT_variable:
+ case InfoType::IT_friend:
break;
case InfoType::IT_default:
return createStringError(inconvertibleErrorCode(), "unexpected info type");
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 608a7f6d4a9d3..6f16f5bd2f528 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -378,6 +378,9 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
case InfoType::IT_variable:
Type = "Variable";
break;
+ case InfoType::IT_friend:
+ Type = "Friend";
+ break;
case InfoType::IT_default:
Type = "Other";
}
@@ -472,6 +475,7 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
break;
case InfoType::IT_concept:
case InfoType::IT_variable:
+ case InfoType::IT_friend:
break;
case InfoType::IT_default:
return createStringError(llvm::inconvertibleErrorCode(),
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 5b94d37d868b4..ba53329a41789 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -147,6 +147,8 @@ mergeInfos(std::vector<std::unique_ptr<Info>> &Values) {
return reduce<ConceptInfo>(Values);
case InfoType::IT_variable:
return reduce<VarInfo>(Values);
+ case InfoType::IT_friend:
+ return reduce<FriendInfo>(Values);
case InfoType::IT_default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"unexpected info type");
@@ -247,6 +249,15 @@ void Reference::merge(Reference &&Other) {
Path = Other.Path;
}
+bool FriendInfo::mergeable(const FriendInfo &Other) {
+ return Ref.USR == Other.Ref.USR && Ref.Name == Other.Ref.Name;
+}
+
+void FriendInfo::merge(FriendInfo &&Other) {
+ assert(mergeable(Other));
+ Ref.merge(std::move(Other.Ref));
+}
+
void Info::mergeBase(Info &&Other) {
assert(mergeable(Other));
if (USR == EmptySID)
@@ -313,6 +324,8 @@ void RecordInfo::merge(RecordInfo &&Other) {
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));
@@ -422,6 +435,9 @@ llvm::SmallString<16> Info::extractName() const {
case InfoType::IT_variable:
return llvm::SmallString<16>("@nonymous_variable_" +
toHex(llvm::toStringRef(USR)));
+ case InfoType::IT_friend:
+ return llvm::SmallString<16>("@nonymous_friend_" +
+ toHex(llvm::toStringRef(USR)));
case InfoType::IT_default:
return llvm::SmallString<16>("@nonymous_" + toHex(llvm::toStringRef(USR)));
}
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 59874f0cfcedf..fe5cc48069d58 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -46,7 +46,8 @@ enum class InfoType {
IT_enum,
IT_typedef,
IT_concept,
- IT_variable
+ IT_variable,
+ IT_friend
};
enum class CommentKind {
@@ -379,6 +380,22 @@ struct SymbolInfo : public Info {
bool IsStatic = false;
};
+struct FriendInfo : SymbolInfo {
+ FriendInfo() : SymbolInfo(InfoType::IT_friend) {}
+ FriendInfo(SymbolID USR) : SymbolInfo(InfoType::IT_friend, USR) {}
+ FriendInfo(const InfoType IT, const SymbolID &USR,
+ const StringRef Name = StringRef())
+ : SymbolInfo(IT, USR, Name) {}
+ bool mergeable(const FriendInfo &Other);
+ void merge(FriendInfo &&Other);
+
+ Reference Ref;
+ std::optional<TemplateInfo> Template;
+ std::optional<TypeInfo> ReturnType;
+ std::optional<SmallVector<FieldTypeInfo, 4>> Params;
+ bool IsClass = false;
+};
+
struct VarInfo : SymbolInfo {
VarInfo() : SymbolInfo(InfoType::IT_variable) {}
explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {}
@@ -454,6 +471,8 @@ struct RecordInfo : public SymbolInfo {
Bases; // List of base/parent records; this includes inherited methods and
// attributes
+ std::vector<FriendInfo> Friends;
+
ScopeChildren Children;
};
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 7a9cb8a1eddb9..12ef8891c720e 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -7,9 +7,12 @@
//===----------------------------------------------------------------------===//
#include "Serialize.h"
+#include "../clangd/CodeCompletionStrings.h"
#include "BitcodeWriter.h"
+
#include "clang/AST/Attr.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringExtras.h"
@@ -403,6 +406,7 @@ std::string serialize(std::unique_ptr<Info> &I) {
return serialize(*static_cast<ConceptInfo *>(I.get()));
case InfoType::IT_variable:
return serialize(*static_cast<VarInfo *>(I.get()));
+ case InfoType::IT_friend:
case InfoType::IT_typedef:
case InfoType::IT_default:
return "";
@@ -556,6 +560,7 @@ static std::unique_ptr<Info> makeAndInsertIntoParent(ChildType Child) {
case InfoType::IT_typedef:
case InfoType::IT_concept:
case InfoType::IT_variable:
+ case InfoType::IT_friend:
break;
}
llvm_unreachable("Invalid reference type for parent namespace");
@@ -947,6 +952,53 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc,
return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
}
+static void parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
+ if (D->hasDefinition() && D->hasFriends())
+ for (const FriendDecl *FD : D->friends()) {
+ if (FD->isUnsupportedFriend())
+ continue;
+
+ FriendInfo F(InfoType::IT_friend, getUSRForDecl(FD));
+ const auto *ActualDecl = FD->getFriendDecl();
+ if (!ActualDecl) {
+ const auto *FriendTypeInfo = FD->getFriendType();
+ if (!FriendTypeInfo)
+ continue;
+ ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();
+
+ if (!ActualDecl)
+ continue;
+ F.IsClass = true;
+ }
+
+ if (const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
+ if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
+ F.IsClass = true;
+ F.Template.emplace();
+ for (const auto *Param : ActualTD->getTemplateParameters()->asArray())
+ F.Template->Params.emplace_back(
+ getSourceCode(Param, Param->getSourceRange()));
+ ActualDecl = ActualTD->getTemplatedDecl();
+ }
+
+ if (auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
+ FunctionInfo TempInfo;
+ parseParameters(TempInfo, FuncDecl);
+ F.Params.emplace();
+ F.Params = std::move(TempInfo.Params);
+ F.ReturnType = getTypeInfoForType(FuncDecl->getReturnType(),
+ FuncDecl->getLangOpts());
+ }
+
+ F.Ref = Reference(getUSRForDecl(ActualDecl),
+ ActualDecl->getNameAsString(), InfoType::IT_default,
+ ActualDecl->getQualifiedNameAsString(),
+ getInfoRelativePath(ActualDecl));
+
+ RI.Friends.push_back(std::move(F));
+ }
+}
+
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
bool PublicOnly) {
@@ -970,6 +1022,7 @@ emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
// TODO: remove first call to parseBases, that function should be deleted
parseBases(*RI, C);
parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true);
+ parseFriends(*RI, C);
}
RI->Path = getInfoRelativePath(RI->Namespace);
diff --git a/clang-tools-extra/cl...
[truncated]
|
evelez7
force-pushed
the
users/evelez7/clang-doc-friends
branch
from
June 30, 2025 18:10
8dd16ca to
318f0c8
Compare
evelez7
force-pushed
the
users/evelez7/clang-doc-precommit-friends
branch
from
June 30, 2025 18:10
111fe87 to
41027d6
Compare
Base automatically changed from
users/evelez7/clang-doc-precommit-friends
to
main
June 30, 2025 18:47
evelez7
force-pushed
the
users/evelez7/clang-doc-friends
branch
from
June 30, 2025 18:48
318f0c8 to
6a10b9c
Compare
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Parse friends into a new FriendInfo and serialize them in JSON. We keep track of the friend declaration's template and function information if applicable.