https://github.com/PeterChou1 updated https://github.com/llvm/llvm-project/pull/135081
>From 8fb896f16396c2e01427ac7baa8791461ff500a3 Mon Sep 17 00:00:00 2001 From: PeterChou1 <peter.c...@mail.utoronto.ca> Date: Thu, 3 Apr 2025 17:07:01 -0400 Subject: [PATCH 1/4] [clang-doc] add start and end line number --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 2 +- clang-tools-extra/clang-doc/BitcodeWriter.cpp | 9 +- clang-tools-extra/clang-doc/Mapper.cpp | 17 +++- clang-tools-extra/clang-doc/Mapper.h | 3 + clang-tools-extra/clang-doc/Representation.h | 22 ++--- clang-tools-extra/clang-doc/Serialize.cpp | 85 ++++++++++--------- 6 files changed, 82 insertions(+), 56 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 1f2fb0a8b2b85..c9f588303fd08 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -85,7 +85,7 @@ llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field, if (R[0] > INT_MAX) return llvm::createStringError(llvm::inconvertibleErrorCode(), "integer too large to parse"); - Field.emplace((int)R[0], Blob, (bool)R[1]); + Field.emplace((int)R[0], (int) R[1], Blob, (bool)R[2]); return llvm::Error::success(); } diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 06f30f76e33d8..8230097c0726d 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -77,13 +77,16 @@ static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) { {// 0. Fixed-size integer (line number) llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, BitCodeConstants::LineNumberSize), - // 1. Boolean (IsFileInRootDir) + // 1. Fixed-size integer (start line number) + llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, + BitCodeConstants::LineNumberSize), + // 2. Boolean (IsFileInRootDir) llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, BitCodeConstants::BoolSize), - // 2. Fixed-size integer (length of the following string (filename)) + // 3. Fixed-size integer (length of the following string (filename)) llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, BitCodeConstants::StringLengthSize), - // 3. The string blob + // 4. The string blob llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)}); } diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 6c90db03424c6..bdcf0c842b98f 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -28,6 +28,21 @@ template <typename T> bool isTypedefAnonRecord(const T *D) { return false; } +Location MapASTVisitor::getDeclLocation(const NamedDecl *D) const { + bool IsFileInRootDir; + llvm::SmallString<128> File = + getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); + ASTContext &Context = D->getASTContext(); + int Start = Context.getSourceManager() + .getPresumedLoc(D->getBeginLoc()) + .getLine(); + int End = Context.getSourceManager() + .getPresumedLoc(D->getEndLoc()) + .getLine(); + + return Location(Start, End, File, IsFileInRootDir); +} + void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) { TraverseDecl(Context.getTranslationUnitDecl()); } @@ -60,7 +75,7 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) { llvm::SmallString<128> File = getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()), - getLine(D, D->getASTContext()), File, + getDeclLocation(D), File, IsFileInRootDir, CDCtx.PublicOnly); // A null in place of I indicates that the serializer is skipping this decl diff --git a/clang-tools-extra/clang-doc/Mapper.h b/clang-tools-extra/clang-doc/Mapper.h index 75c8e947c8f90..3c3ebdb683911 100644 --- a/clang-tools-extra/clang-doc/Mapper.h +++ b/clang-tools-extra/clang-doc/Mapper.h @@ -46,6 +46,9 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>, template <typename T> bool mapDecl(const T *D, bool IsDefinition); int getLine(const NamedDecl *D, const ASTContext &Context) const; + + Location getDeclLocation(const NamedDecl *D) const; + llvm::SmallString<128> getFile(const NamedDecl *D, const ASTContext &Context, StringRef RootDir, bool &IsFileInRootDir) const; diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 2153b62864ee3..53a62edf3dbcf 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -238,19 +238,20 @@ struct MemberTypeInfo : public FieldTypeInfo { }; struct Location { - Location(int LineNumber = 0, StringRef Filename = StringRef(), + Location(int StartLineNumber = 0, + int EndLineNumber = 0, StringRef Filename = StringRef(), bool IsFileInRootDir = false) - : LineNumber(LineNumber), Filename(Filename), - IsFileInRootDir(IsFileInRootDir) {} + : StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber), + Filename(Filename), IsFileInRootDir(IsFileInRootDir) {} bool operator==(const Location &Other) const { - return std::tie(LineNumber, Filename) == - std::tie(Other.LineNumber, Other.Filename); + return std::tie(StartLineNumber, EndLineNumber, Filename) == + std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); } bool operator!=(const Location &Other) const { - return std::tie(LineNumber, Filename) != - std::tie(Other.LineNumber, Other.Filename); + return std::tie(StartLineNumber, Filename) != + std::tie(Other.StartLineNumber, Other.Filename); } // This operator is used to sort a vector of Locations. @@ -258,11 +259,12 @@ struct Location { // sort is enough, the order is only needed to call std::unique after sorting // the vector. bool operator<(const Location &Other) const { - return std::tie(LineNumber, Filename) < - std::tie(Other.LineNumber, Other.Filename); + return std::tie(StartLineNumber, Filename) < + std::tie(Other.StartLineNumber, Other.Filename); } - int LineNumber = 0; // Line number of this Location. + int StartLineNumber = 0; // Line number of this Location. + int EndLineNumber = 0; SmallString<32> Filename; // File for this Location. bool IsFileInRootDir = false; // Indicates if file is inside root directory }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index f737fc75135a1..aa3dff1d210b5 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -527,22 +527,20 @@ static void populateInfo(Info &I, const T *D, const FullComment *C, template <typename T> static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, - int LineNumber, StringRef Filename, - bool IsFileInRootDir, + Location Loc, bool &IsInAnonymousNamespace) { populateInfo(I, D, C, IsInAnonymousNamespace); if (D->isThisDeclarationADefinition()) - I.DefLoc.emplace(LineNumber, Filename, IsFileInRootDir); + I.DefLoc = Loc; else - I.Loc.emplace_back(LineNumber, Filename, IsFileInRootDir); + I.Loc.emplace_back(Loc); } static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, - const FullComment *FC, int LineNumber, - StringRef Filename, bool IsFileInRootDir, + const FullComment *FC, + Location Loc, bool &IsInAnonymousNamespace) { - populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir, - IsInAnonymousNamespace); + populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace); auto &LO = D->getLangOpts(); I.ReturnType = getTypeInfoForType(D->getReturnType(), LO); parseParameters(I, D); @@ -623,8 +621,7 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, // reference, its value is not relevant in here so it's not used // anywhere besides the function call. bool IsInAnonymousNamespace; - populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*LineNumber=*/{}, - /*FileName=*/{}, IsFileInRootDir, + populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*Location=*/{}, IsInAnonymousNamespace); FI.Access = getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe()); @@ -642,8 +639,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { auto I = std::make_unique<NamespaceInfo>(); bool IsInAnonymousNamespace = false; populateInfo(*I, D, FC, IsInAnonymousNamespace); @@ -663,12 +660,11 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const RecordDecl *D, const FullComment *FC, + Location Loc, bool PublicOnly) { auto I = std::make_unique<RecordInfo>(); bool IsInAnonymousNamespace = false; - populateSymbolInfo(*I, D, FC, LineNumber, File, IsFileInRootDir, - IsInAnonymousNamespace); + populateSymbolInfo(*I, D, FC, Loc, IsInAnonymousNamespace); if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; @@ -681,7 +677,7 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, } // TODO: remove first call to parseBases, that function should be deleted parseBases(*I, C); - parseBases(*I, C, IsFileInRootDir, PublicOnly, true); + parseBases(*I, C, true, PublicOnly, true); } I->Path = getInfoRelativePath(I->Namespace); @@ -730,30 +726,28 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const FunctionDecl *D, const FullComment *FC, + Location Loc, bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; - populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, - IsInAnonymousNamespace); + populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); Func.Access = clang::AccessSpecifier::AS_none; if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + // Info is wrapped in its parent scope so is returned in the second position. return {nullptr, MakeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))}; } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const CXXMethodDecl *D, const FullComment *FC, + Location Loc, bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; - populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, - IsInAnonymousNamespace); + populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + Func.IsMethod = true; const NamedDecl *Parent = nullptr; @@ -774,18 +768,21 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { + TypedefInfo Info; - + ASTContext& Context = D->getASTContext(); bool IsInAnonymousNamespace = false; populateInfo(Info, D, FC, IsInAnonymousNamespace); + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - - Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); + + Info.DefLoc = Loc; auto &LO = D->getLangOpts(); Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); + if (Info.Underlying.Type.Name.empty()) { // Typedef for an unnamed type. This is like "typedef struct { } Foo;" // The record serializer explicitly checks for this syntax and constructs @@ -793,7 +790,13 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber, return {}; } Info.IsUsing = false; - + if (RawComment *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) { + Comment->setAttached(); + if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) { + Info.Description.emplace_back(); + parseFullComment(Fc, Info.Description.back()); + } + } // Info is wrapped in its parent scope so is returned in the second position. return {nullptr, MakeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))}; } @@ -801,8 +804,8 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber, // A type alias is a C++ "using" declaration for a type. It gets mapped to a // TypedefInfo with the IsUsing flag set. std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const TypeAliasDecl *D, const FullComment *FC, + Location Loc, bool PublicOnly) { TypedefInfo Info; bool IsInAnonymousNamespace = false; @@ -810,7 +813,7 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); + Info.DefLoc = Loc; auto &LO = D->getLangOpts(); Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); Info.IsUsing = true; @@ -820,15 +823,15 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { +emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { EnumInfo Enum; bool IsInAnonymousNamespace = false; - populateSymbolInfo(Enum, D, FC, LineNumber, File, IsFileInRootDir, - IsInAnonymousNamespace); + populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace); + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + Enum.Scoped = D->isScoped(); if (D->isFixed()) { auto Name = D->getIntegerType().getAsString(); >From 7dd8ebe47b2a7669fdb9dbd2a5369b487831389f Mon Sep 17 00:00:00 2001 From: PeterChou1 <peter.c...@mail.utoronto.ca> Date: Mon, 7 Apr 2025 15:41:29 -0400 Subject: [PATCH 2/4] add number --- clang-tools-extra/clang-doc/Mapper.cpp | 3 +- clang-tools-extra/clang-doc/Serialize.h | 28 +++++++++---------- clang-tools-extra/clang-doc/YAMLGenerator.cpp | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index bdcf0c842b98f..4dadff41e96e8 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -75,8 +75,7 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) { llvm::SmallString<128> File = getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()), - getDeclLocation(D), File, - IsFileInRootDir, CDCtx.PublicOnly); + getDeclLocation(D), CDCtx.PublicOnly); // A null in place of I indicates that the serializer is skipping this decl // for some reason (e.g. we're only reporting public decls). diff --git a/clang-tools-extra/clang-doc/Serialize.h b/clang-tools-extra/clang-doc/Serialize.h index 4e203ca7891ac..8874299e9af9e 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -37,32 +37,32 @@ namespace serialize { // its parent scope. For NamespaceDecl and RecordDecl both elements are not // nullptr. std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool IsFileInRootDir, bool PublicOnly); +emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly); // Function to hash a given USR value for storage. // As USRs (Unified Symbol Resolution) could be large, especially for functions diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index ffabd2fd82229..d990dd4b647e8 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -169,7 +169,7 @@ static void CommentInfoMapping(IO &IO, CommentInfo &I) { template <> struct MappingTraits<Location> { static void mapping(IO &IO, Location &Loc) { - IO.mapOptional("LineNumber", Loc.LineNumber, 0); + IO.mapOptional("LineNumber", Loc.StartLineNumber, 0); IO.mapOptional("Filename", Loc.Filename, SmallString<32>()); } }; >From af43032429cef3ae328af88f5893bbc0f46eadee Mon Sep 17 00:00:00 2001 From: PeterChou1 <peter.c...@mail.utoronto.ca> Date: Wed, 9 Apr 2025 17:01:43 -0400 Subject: [PATCH 3/4] fix compilation error --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 2 +- clang-tools-extra/clang-doc/BitcodeWriter.cpp | 3 ++- clang-tools-extra/clang-doc/HTMLGenerator.cpp | 8 +++++--- clang-tools-extra/clang-doc/MDGenerator.cpp | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index c9f588303fd08..2334521db2860 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -135,7 +135,7 @@ llvm::Error decodeRecord(const Record &R, if (R[0] > INT_MAX) return llvm::createStringError(llvm::inconvertibleErrorCode(), "integer too large to parse"); - Field.emplace_back((int)R[0], Blob, (bool)R[1]); + Field.emplace_back((int)R[0], (int)R[1], Blob, (bool)R[2]); return llvm::Error::success(); } diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 8230097c0726d..402386443dbc0 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -355,7 +355,8 @@ void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) { if (!prepRecordData(ID, true)) return; // FIXME: Assert that the line number is of the appropriate size. - Record.push_back(Loc.LineNumber); + Record.push_back(Loc.StartLineNumber); + Record.push_back(Loc.EndLineNumber); assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize)); Record.push_back(Loc.IsFileInRootDir); Record.push_back(Loc.Filename.size()); diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index f559933fc2283..cf998a4948369 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -495,7 +495,7 @@ static std::unique_ptr<TagNode> writeSourceFileRef(const ClangDocContext &CDCtx, if (!L.IsFileInRootDir && !CDCtx.RepositoryUrl) return std::make_unique<TagNode>( - HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) + + HTMLTag::TAG_P, "Defined at line " + std::to_string(L.StartLineNumber) + " of file " + L.Filename); SmallString<128> FileURL(CDCtx.RepositoryUrl.value_or("")); @@ -513,12 +513,14 @@ static std::unique_ptr<TagNode> writeSourceFileRef(const ClangDocContext &CDCtx, auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P); Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line ")); auto LocNumberNode = - std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber)); + std::make_unique<TagNode>(HTMLTag::TAG_A, + std::to_string(L.StartLineNumber)); // The links to a specific line in the source code use the github / // googlesource notation so it won't work for all hosting pages. LocNumberNode->Attributes.emplace_back( "href", formatv("{0}#{1}{2}", FileURL, - CDCtx.RepositoryLinePrefix.value_or(""), L.LineNumber)); + CDCtx.RepositoryLinePrefix.value_or(""), + L.StartLineNumber)); Node->Children.emplace_back(std::move(LocNumberNode)); Node->Children.emplace_back(std::make_unique<TextNode>(" of file ")); auto LocFileNode = std::make_unique<TagNode>( diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index 5c782fcc10da5..ac7e20b27db23 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -56,12 +56,13 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L, raw_ostream &OS) { if (!CDCtx.RepositoryUrl) { - OS << "*Defined at " << L.Filename << "#" << std::to_string(L.LineNumber) + OS << "*Defined at " << L.Filename << "#" + << std::to_string(L.StartLineNumber) << "*"; } else { OS << formatv("*Defined at [#{0}{1}{2}](#{0}{1}{3})*", - CDCtx.RepositoryLinePrefix.value_or(""), L.LineNumber, + CDCtx.RepositoryLinePrefix.value_or(""), L.StartLineNumber, L.Filename, *CDCtx.RepositoryUrl); } OS << "\n\n"; >From 7563ec536d9698ebec57e070cc1a363f2b8d05e5 Mon Sep 17 00:00:00 2001 From: PeterChou1 <peter.c...@mail.utoronto.ca> Date: Wed, 9 Apr 2025 17:19:32 -0400 Subject: [PATCH 4/4] clang-format --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 2 +- clang-tools-extra/clang-doc/Mapper.cpp | 11 ++--- clang-tools-extra/clang-doc/Mapper.h | 4 +- clang-tools-extra/clang-doc/Representation.h | 7 ++- clang-tools-extra/clang-doc/Serialize.cpp | 48 +++++++++---------- clang-tools-extra/clang-doc/Serialize.h | 14 +++--- 6 files changed, 40 insertions(+), 46 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 2334521db2860..d7233459bdd61 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -85,7 +85,7 @@ llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field, if (R[0] > INT_MAX) return llvm::createStringError(llvm::inconvertibleErrorCode(), "integer too large to parse"); - Field.emplace((int)R[0], (int) R[1], Blob, (bool)R[2]); + Field.emplace((int)R[0], (int)R[1], Blob, (bool)R[2]); return llvm::Error::success(); } diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 4dadff41e96e8..c210338f7863f 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -33,13 +33,10 @@ Location MapASTVisitor::getDeclLocation(const NamedDecl *D) const { llvm::SmallString<128> File = getFile(D, D->getASTContext(), CDCtx.SourceRoot, IsFileInRootDir); ASTContext &Context = D->getASTContext(); - int Start = Context.getSourceManager() - .getPresumedLoc(D->getBeginLoc()) - .getLine(); - int End = Context.getSourceManager() - .getPresumedLoc(D->getEndLoc()) - .getLine(); - + int Start = + Context.getSourceManager().getPresumedLoc(D->getBeginLoc()).getLine(); + int End = Context.getSourceManager().getPresumedLoc(D->getEndLoc()).getLine(); + return Location(Start, End, File, IsFileInRootDir); } diff --git a/clang-tools-extra/clang-doc/Mapper.h b/clang-tools-extra/clang-doc/Mapper.h index 3c3ebdb683911..36322ea2bfb77 100644 --- a/clang-tools-extra/clang-doc/Mapper.h +++ b/clang-tools-extra/clang-doc/Mapper.h @@ -46,9 +46,9 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>, template <typename T> bool mapDecl(const T *D, bool IsDefinition); int getLine(const NamedDecl *D, const ASTContext &Context) const; - + Location getDeclLocation(const NamedDecl *D) const; - + llvm::SmallString<128> getFile(const NamedDecl *D, const ASTContext &Context, StringRef RootDir, bool &IsFileInRootDir) const; diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 53a62edf3dbcf..eebf0c799c1f0 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -238,9 +238,8 @@ struct MemberTypeInfo : public FieldTypeInfo { }; struct Location { - Location(int StartLineNumber = 0, - int EndLineNumber = 0, StringRef Filename = StringRef(), - bool IsFileInRootDir = false) + Location(int StartLineNumber = 0, int EndLineNumber = 0, + StringRef Filename = StringRef(), bool IsFileInRootDir = false) : StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber), Filename(Filename), IsFileInRootDir(IsFileInRootDir) {} @@ -263,7 +262,7 @@ struct Location { std::tie(Other.StartLineNumber, Other.Filename); } - int StartLineNumber = 0; // Line number of this Location. + int StartLineNumber = 0; // Line number of this Location. int EndLineNumber = 0; SmallString<32> Filename; // File for this Location. bool IsFileInRootDir = false; // Indicates if file is inside root directory diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index aa3dff1d210b5..ce21a9bc8c109 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -527,8 +527,7 @@ static void populateInfo(Info &I, const T *D, const FullComment *C, template <typename T> static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, - Location Loc, - bool &IsInAnonymousNamespace) { + Location Loc, bool &IsInAnonymousNamespace) { populateInfo(I, D, C, IsInAnonymousNamespace); if (D->isThisDeclarationADefinition()) I.DefLoc = Loc; @@ -537,8 +536,7 @@ static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, } static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, - const FullComment *FC, - Location Loc, + const FullComment *FC, Location Loc, bool &IsInAnonymousNamespace) { populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace); auto &LO = D->getLangOpts(); @@ -569,7 +567,7 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, static void populateMemberTypeInfo(MemberTypeInfo &I, const FieldDecl *D) { assert(D && "Expect non-null FieldDecl in populateMemberTypeInfo"); - ASTContext& Context = D->getASTContext(); + ASTContext &Context = D->getASTContext(); // TODO investigate whether we can use ASTContext::getCommentForDecl instead // of this logic. See also similar code in Mapper.cpp. RawComment *Comment = Context.getRawCommentForDeclNoCache(D); @@ -639,7 +637,7 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, +emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, bool PublicOnly) { auto I = std::make_unique<NamespaceInfo>(); bool IsInAnonymousNamespace = false; @@ -660,8 +658,8 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const RecordDecl *D, const FullComment *FC, - Location Loc, bool PublicOnly) { +emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { auto I = std::make_unique<RecordInfo>(); bool IsInAnonymousNamespace = false; populateSymbolInfo(*I, D, FC, Loc, IsInAnonymousNamespace); @@ -726,28 +724,28 @@ emitInfo(const RecordDecl *D, const FullComment *FC, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const FunctionDecl *D, const FullComment *FC, - Location Loc, bool PublicOnly) { +emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); Func.Access = clang::AccessSpecifier::AS_none; if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + // Info is wrapped in its parent scope so is returned in the second position. return {nullptr, MakeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))}; } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const CXXMethodDecl *D, const FullComment *FC, - Location Loc, bool PublicOnly) { +emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace); if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + Func.IsMethod = true; const NamedDecl *Parent = nullptr; @@ -768,21 +766,21 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, +emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, bool PublicOnly) { - + TypedefInfo Info; - ASTContext& Context = D->getASTContext(); + ASTContext &Context = D->getASTContext(); bool IsInAnonymousNamespace = false; populateInfo(Info, D, FC, IsInAnonymousNamespace); - + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + Info.DefLoc = Loc; auto &LO = D->getLangOpts(); Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); - + if (Info.Underlying.Type.Name.empty()) { // Typedef for an unnamed type. This is like "typedef struct { } Foo;" // The record serializer explicitly checks for this syntax and constructs @@ -804,8 +802,8 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, // A type alias is a C++ "using" declaration for a type. It gets mapped to a // TypedefInfo with the IsUsing flag set. std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypeAliasDecl *D, const FullComment *FC, - Location Loc, bool PublicOnly) { +emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, + bool PublicOnly) { TypedefInfo Info; bool IsInAnonymousNamespace = false; @@ -823,15 +821,15 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, } std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, +emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, bool PublicOnly) { EnumInfo Enum; bool IsInAnonymousNamespace = false; populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace); - + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) return {}; - + Enum.Scoped = D->isScoped(); if (D->isFixed()) { auto Name = D->getIntegerType().getAsString(); diff --git a/clang-tools-extra/clang-doc/Serialize.h b/clang-tools-extra/clang-doc/Serialize.h index 8874299e9af9e..bdf969aa56b97 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -37,31 +37,31 @@ namespace serialize { // its parent scope. For NamespaceDecl and RecordDecl both elements are not // nullptr. std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, +emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, +emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, +emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc, +emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc, +emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, +emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> -emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, +emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, bool PublicOnly); // Function to hash a given USR value for storage. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits