[llvm-branch-commits] [clang-tools-extra] [clang-doc] Clean up implementation with better casting (PR #202060)

Paul Kirth via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jun 6 09:34:47 PDT 2026


https://github.com/ilovepi created https://github.com/llvm/llvm-project/pull/202060

Having access to RTTI style casting lets us use slightly nicer
structures to clean up the overly complicated dispatch logic in merging
and other places.

>From 9ef870aff6c58eb596edc69d8effe63b96f9069b Mon Sep 17 00:00:00 2001
From: Paul Kirth <pk1574 at gmail.com>
Date: Fri, 5 Jun 2026 22:26:47 -0700
Subject: [PATCH] [clang-doc] Clean up implementation with better casting

Having access to RTTI style casting lets us use slightly nicer
structures to clean up the overly complicated dispatch logic in merging
and other places.
---
 .../clang-doc/Representation.cpp              | 79 +++++--------------
 clang-tools-extra/clang-doc/Representation.h  |  5 --
 2 files changed, 19 insertions(+), 65 deletions(-)

diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 0284f5a70615f..bd363dc42f805 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -180,83 +180,42 @@ void mergeUnkeyed<CommentInfo>(DocList<CommentInfo> &Target,
   }
 }
 
+template <typename T>
+static llvm::Error mergeTypedInfo(Info *&Reduced, Info *NewInfo,
+                           llvm::BumpPtrAllocator &Arena) {
+  if (!Reduced)
+    Reduced = allocatePtr<T>(Arena, NewInfo->USR);
+  cast<T>(Reduced)->merge(std::move(*cast<T>(NewInfo)));
+  return llvm::Error::success();
+}
+
 llvm::Error mergeSingleInfo(doc::Info *&Reduced, doc::Info *NewInfo,
                             llvm::BumpPtrAllocator &Arena) {
-  if (!Reduced) {
-    switch (NewInfo->IT) {
-    case InfoType::IT_namespace:
-      Reduced = allocatePtr<NamespaceInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_record:
-      Reduced = allocatePtr<RecordInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_enum:
-      Reduced = allocatePtr<EnumInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_function:
-      Reduced = allocatePtr<FunctionInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_typedef:
-      Reduced = allocatePtr<TypedefInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_concept:
-      Reduced = allocatePtr<ConceptInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_variable:
-      Reduced = allocatePtr<VarInfo>(Arena, NewInfo->USR);
-      break;
-    case InfoType::IT_friend:
-      Reduced = allocatePtr<FriendInfo>(Arena, NewInfo->USR);
-      break;
-    default:
-      return llvm::createStringError(llvm::inconvertibleErrorCode(),
-                                     "unknown info type");
-    }
-  }
-
-  if (Reduced->IT != NewInfo->IT)
+  if (Reduced && Reduced->IT != NewInfo->IT)
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                    "info types mismatch");
 
-  switch (Reduced->IT) {
+  switch (NewInfo->IT) {
   case InfoType::IT_namespace:
-    cast<NamespaceInfo>(Reduced)->merge(
-        std::move(*cast<NamespaceInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<NamespaceInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_record:
-    cast<RecordInfo>(Reduced)->merge(
-        std::move(*cast<RecordInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<RecordInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_enum:
-    cast<EnumInfo>(Reduced)->merge(
-        std::move(*cast<EnumInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<EnumInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_function:
-    cast<FunctionInfo>(Reduced)->merge(
-        std::move(*cast<FunctionInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<FunctionInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_typedef:
-    cast<TypedefInfo>(Reduced)->merge(
-        std::move(*cast<TypedefInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<TypedefInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_concept:
-    cast<ConceptInfo>(Reduced)->merge(
-        std::move(*cast<ConceptInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<ConceptInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_variable:
-    cast<VarInfo>(Reduced)->merge(
-        std::move(*cast<VarInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<VarInfo>(Reduced, NewInfo, Arena);
   case InfoType::IT_friend:
-    cast<FriendInfo>(Reduced)->merge(
-        std::move(*cast<FriendInfo>(NewInfo)));
-    break;
+    return mergeTypedInfo<FriendInfo>(Reduced, NewInfo, Arena);
   default:
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                    "unknown info type");
   }
-
-  return llvm::Error::success();
 }
 
 // Dispatch function.
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index d135ba0cd09fa..e1e71decb3a78 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -603,8 +603,6 @@ struct SymbolInfo : public Info {
 
   SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena);
 
-  // SymbolInfo is an intermediate base with no InfoType of its own; it covers
-  // every kind that isn't a namespace.
   static bool classof(const Info *I) {
     switch (I->IT) {
     case InfoType::IT_record:
@@ -713,9 +711,6 @@ struct RecordInfo : public SymbolInfo {
 
   RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena);
 
-  // BaseRecordInfo also carries IT_record, so isa<RecordInfo> is true for it as
-  // well. BaseRecordInfo is never stored polymorphically as an Info*, so it has
-  // no classof of its own.
   static bool classof(const Info *I) { return I->IT == InfoType::IT_record; }
 
   void merge(RecordInfo &&I);



More information about the llvm-branch-commits mailing list