[clang-tools-extra] [clang-doc] Add Start and End Line Numbers (PR #135081)

via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 9 14:27:00 PDT 2025


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.chou at mail.utoronto.ca>
Date: Thu, 3 Apr 2025 17:07:01 -0400
Subject: [PATCH 1/5] [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.chou at mail.utoronto.ca>
Date: Mon, 7 Apr 2025 15:41:29 -0400
Subject: [PATCH 2/5] 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.chou at mail.utoronto.ca>
Date: Wed, 9 Apr 2025 17:01:43 -0400
Subject: [PATCH 3/5] 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.chou at mail.utoronto.ca>
Date: Wed, 9 Apr 2025 17:19:32 -0400
Subject: [PATCH 4/5] 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.

>From 93f30bca2b5902f128824ee3a8ba9e1e78c0be09 Mon Sep 17 00:00:00 2001
From: PeterChou1 <peter.chou at mail.utoronto.ca>
Date: Wed, 9 Apr 2025 17:26:37 -0400
Subject: [PATCH 5/5] clang-format

---
 clang-tools-extra/clang-doc/HTMLGenerator.cpp | 11 +++++------
 clang-tools-extra/clang-doc/MDGenerator.cpp   |  5 ++---
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
index cf998a4948369..b9be8ceb3f66c 100644
--- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -512,15 +512,14 @@ static std::unique_ptr<TagNode> writeSourceFileRef(const ClangDocContext &CDCtx,
           llvm::sys::path::Style::windows));
   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.StartLineNumber));
+  auto LocNumberNode = 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.StartLineNumber));
+      "href",
+      formatv("{0}#{1}{2}", FileURL, 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 ac7e20b27db23..ce147de5e54d8 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -56,9 +56,8 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
                                raw_ostream &OS) {
 
   if (!CDCtx.RepositoryUrl) {
-    OS << "*Defined at " << L.Filename << "#" 
-       << std::to_string(L.StartLineNumber)
-       << "*";
+    OS << "*Defined at " << L.Filename << "#"
+       << std::to_string(L.StartLineNumber) << "*";
   } else {
 
     OS << formatv("*Defined at [#{0}{1}{2}](#{0}{1}{3})*",



More information about the cfe-commits mailing list