Author: Paul Kirth Date: 2026-06-06T13:45:58-07:00 New Revision: 35823d13a8460f57be6b73f3dc4f3b93acbcf79d
URL: https://github.com/llvm/llvm-project/commit/35823d13a8460f57be6b73f3dc4f3b93acbcf79d DIFF: https://github.com/llvm/llvm-project/commit/35823d13a8460f57be6b73f3dc4f3b93acbcf79d.diff LOG: [clang-doc] Use llvm RTTI over handrolled casting (#202059) Clang-Doc has a limited amount of polymorphism over Info types. Historically, these have just been cast directly in a few places, but we can use the existing llvm RTTI implementation to more rigorously dispatch and query the types involved with only limited extra code. This should make future changes a bit harder to get wrong. Added: Modified: clang-tools-extra/clang-doc/BitcodeWriter.cpp clang-tools-extra/clang-doc/JSONGenerator.cpp clang-tools-extra/clang-doc/MDGenerator.cpp clang-tools-extra/clang-doc/Representation.cpp clang-tools-extra/clang-doc/Representation.h clang-tools-extra/clang-doc/Serialize.cpp clang-tools-extra/clang-doc/YAMLGenerator.cpp clang-tools-extra/clang-doc/tool/ClangDocMain.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 2ab1bbf4a8a16..ee5114b1af880 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -768,28 +768,28 @@ void ClangDocBitcodeWriter::emitBlock(const VarInfo &I) { bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) { switch (I->IT) { case InfoType::IT_namespace: - emitBlock(*static_cast<NamespaceInfo *>(I)); + emitBlock(*cast<NamespaceInfo>(I)); break; case InfoType::IT_record: - emitBlock(*static_cast<RecordInfo *>(I)); + emitBlock(*cast<RecordInfo>(I)); break; case InfoType::IT_enum: - emitBlock(*static_cast<EnumInfo *>(I)); + emitBlock(*cast<EnumInfo>(I)); break; case InfoType::IT_function: - emitBlock(*static_cast<FunctionInfo *>(I)); + emitBlock(*cast<FunctionInfo>(I)); break; case InfoType::IT_typedef: - emitBlock(*static_cast<TypedefInfo *>(I)); + emitBlock(*cast<TypedefInfo>(I)); break; case InfoType::IT_concept: - emitBlock(*static_cast<ConceptInfo *>(I)); + emitBlock(*cast<ConceptInfo>(I)); break; case InfoType::IT_variable: - emitBlock(*static_cast<VarInfo *>(I)); + emitBlock(*cast<VarInfo>(I)); break; case InfoType::IT_friend: - emitBlock(*static_cast<FriendInfo *>(I)); + emitBlock(*cast<FriendInfo>(I)); break; case InfoType::IT_default: unsigned ID = Diags.getCustomDiagID(DiagnosticsEngine::Error, diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 0ab71b4a5b5c9..fc629dc8449e0 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -451,7 +451,7 @@ void JSONGenerator::serializeCommonAttributes(const Info &I, // Namespaces aren't SymbolInfos, so they dont have a DefLoc if (I.IT != InfoType::IT_namespace) { - const auto *Symbol = static_cast<const SymbolInfo *>(&I); + const auto *Symbol = cast<SymbolInfo>(&I); if (Symbol->DefLoc) Obj["Location"] = serializeLocation(Symbol->DefLoc.value()); } @@ -491,7 +491,7 @@ void JSONGenerator::serializeClassSpecializations(SymbolID ClassUSR, auto *Class = Infos->lookup(toHex(ClassUSR)); if (!Class || Class->IT != InfoType::IT_record) return; - RecordInfo *ClassInfo = static_cast<RecordInfo *>(Class); + RecordInfo *ClassInfo = cast<RecordInfo>(Class); if (!ClassInfo->Template || !ClassInfo->Template->Specialization) return; serializeTemplateSpecialization(ClassInfo->Template.value(), ReferenceObj); @@ -865,7 +865,7 @@ SmallString<16> JSONGenerator::determineFileName(Info *I, SmallString<128> &Path) { SmallString<16> FileName; if (I->IT == InfoType::IT_record) { - auto *RecordSymbolInfo = static_cast<SymbolInfo *>(I); + auto *RecordSymbolInfo = cast<SymbolInfo>(I); FileName = RecordSymbolInfo->MangledName; } else if (I->IT == InfoType::IT_namespace) { FileName = "index"; @@ -1052,10 +1052,10 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS, switch (I->IT) { case InfoType::IT_namespace: - serializeInfo(*static_cast<NamespaceInfo *>(I), Obj); + serializeInfo(*cast<NamespaceInfo>(I), Obj); break; case InfoType::IT_record: - serializeInfo(*static_cast<RecordInfo *>(I), Obj); + serializeInfo(*cast<RecordInfo>(I), Obj); break; case InfoType::IT_concept: case InfoType::IT_enum: diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index df1ca6b868d43..4d412cde557ed 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -561,19 +561,19 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) { switch (I->IT) { case InfoType::IT_namespace: - genMarkdown(CDCtx, *static_cast<clang::doc::NamespaceInfo *>(I), OS); + genMarkdown(CDCtx, *cast<NamespaceInfo>(I), OS); break; case InfoType::IT_record: - genMarkdown(CDCtx, *static_cast<clang::doc::RecordInfo *>(I), OS); + genMarkdown(CDCtx, *cast<RecordInfo>(I), OS); break; case InfoType::IT_enum: - genMarkdown(CDCtx, *static_cast<clang::doc::EnumInfo *>(I), OS); + genMarkdown(CDCtx, *cast<EnumInfo>(I), OS); break; case InfoType::IT_function: - genMarkdown(CDCtx, *static_cast<clang::doc::FunctionInfo *>(I), OS); + genMarkdown(CDCtx, *cast<FunctionInfo>(I), OS); break; case InfoType::IT_typedef: - genMarkdown(CDCtx, *static_cast<clang::doc::TypedefInfo *>(I), OS); + genMarkdown(CDCtx, *cast<TypedefInfo>(I), OS); break; case InfoType::IT_concept: case InfoType::IT_variable: diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index bfa1150f9bc35..9c13f6bfa566d 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -108,7 +108,7 @@ static llvm::Expected<Info *> reduce(SmallVectorImpl<Info *> &Values) { "no value to reduce"); T *Merged = allocateTransient<T>(Values[0]->USR); for (auto &I : Values) - Merged->merge(std::move(*static_cast<T *>(I))); + Merged->merge(std::move(*cast<T>(I))); return Merged; } @@ -220,36 +220,29 @@ llvm::Error mergeSingleInfo(doc::Info *&Reduced, doc::Info *NewInfo, switch (Reduced->IT) { case InfoType::IT_namespace: - static_cast<NamespaceInfo *>(Reduced)->merge( - std::move(*static_cast<NamespaceInfo *>(NewInfo))); + cast<NamespaceInfo>(Reduced)->merge( + std::move(*cast<NamespaceInfo>(NewInfo))); break; case InfoType::IT_record: - static_cast<RecordInfo *>(Reduced)->merge( - std::move(*static_cast<RecordInfo *>(NewInfo))); + cast<RecordInfo>(Reduced)->merge(std::move(*cast<RecordInfo>(NewInfo))); break; case InfoType::IT_enum: - static_cast<EnumInfo *>(Reduced)->merge( - std::move(*static_cast<EnumInfo *>(NewInfo))); + cast<EnumInfo>(Reduced)->merge(std::move(*cast<EnumInfo>(NewInfo))); break; case InfoType::IT_function: - static_cast<FunctionInfo *>(Reduced)->merge( - std::move(*static_cast<FunctionInfo *>(NewInfo))); + cast<FunctionInfo>(Reduced)->merge(std::move(*cast<FunctionInfo>(NewInfo))); break; case InfoType::IT_typedef: - static_cast<TypedefInfo *>(Reduced)->merge( - std::move(*static_cast<TypedefInfo *>(NewInfo))); + cast<TypedefInfo>(Reduced)->merge(std::move(*cast<TypedefInfo>(NewInfo))); break; case InfoType::IT_concept: - static_cast<ConceptInfo *>(Reduced)->merge( - std::move(*static_cast<ConceptInfo *>(NewInfo))); + cast<ConceptInfo>(Reduced)->merge(std::move(*cast<ConceptInfo>(NewInfo))); break; case InfoType::IT_variable: - static_cast<VarInfo *>(Reduced)->merge( - std::move(*static_cast<VarInfo *>(NewInfo))); + cast<VarInfo>(Reduced)->merge(std::move(*cast<VarInfo>(NewInfo))); break; case InfoType::IT_friend: - static_cast<FriendInfo *>(Reduced)->merge( - std::move(*static_cast<FriendInfo *>(NewInfo))); + cast<FriendInfo>(Reduced)->merge(std::move(*cast<FriendInfo>(NewInfo))); break; default: return llvm::createStringError(llvm::inconvertibleErrorCode(), diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index c7921ff9de875..e3ad7fa3f375d 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -23,6 +23,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/simple_ilist.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/StringSaver.h" #include <array> @@ -585,6 +586,8 @@ struct NamespaceInfo : public Info { NamespaceInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()); + static bool classof(const Info *I) { return I->IT == InfoType::IT_namespace; } + void merge(NamespaceInfo &&I); ScopeChildren Children; @@ -598,6 +601,24 @@ struct SymbolInfo : public Info { SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena); + // SymbolInfo is an intermediate base without its own InfoType. It covers + // every Info* kind that relates to symbols, which mostly just excludes + // Namespace in the current schema. + static bool classof(const Info *I) { + switch (I->IT) { + case InfoType::IT_record: + case InfoType::IT_function: + case InfoType::IT_enum: + case InfoType::IT_typedef: + case InfoType::IT_concept: + case InfoType::IT_variable: + case InfoType::IT_friend: + return true; + default: + return false; + } + } + void merge(SymbolInfo &&I); bool operator<(const SymbolInfo &Other) const { @@ -627,6 +648,9 @@ struct FriendInfo : public SymbolInfo { const StringRef Name = StringRef()) : SymbolInfo(IT, USR, Name) {} FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena); + + static bool classof(const Info *I) { return I->IT == InfoType::IT_friend; } + bool mergeable(const FriendInfo &Other); void merge(FriendInfo &&Other); @@ -641,6 +665,8 @@ struct VarInfo : public SymbolInfo { VarInfo() : SymbolInfo(InfoType::IT_variable) {} explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {} + static bool classof(const Info *I) { return I->IT == InfoType::IT_variable; } + void merge(VarInfo &&I); TypeInfo Type; @@ -652,6 +678,8 @@ struct FunctionInfo : public SymbolInfo { FunctionInfo(SymbolID USR = SymbolID()) : SymbolInfo(InfoType::IT_function, USR) {} + static bool classof(const Info *I) { return I->IT == InfoType::IT_function; } + void merge(FunctionInfo &&I); Reference Parent; @@ -680,6 +708,8 @@ struct RecordInfo : public SymbolInfo { RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena); + static bool classof(const Info *I) { return I->IT == InfoType::IT_record; } + void merge(RecordInfo &&I); // Type of this record (struct, class, union, interface). @@ -715,6 +745,8 @@ struct TypedefInfo : public SymbolInfo { TypedefInfo(SymbolID USR = SymbolID()) : SymbolInfo(InfoType::IT_typedef, USR) {} + static bool classof(const Info *I) { return I->IT == InfoType::IT_typedef; } + void merge(TypedefInfo &&I); TypeInfo Underlying = {}; @@ -782,6 +814,8 @@ struct EnumInfo : public SymbolInfo { EnumInfo() : SymbolInfo(InfoType::IT_enum) {} EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {} + static bool classof(const Info *I) { return I->IT == InfoType::IT_enum; } + void merge(EnumInfo &&I); // Indicates whether this enum is scoped (e.g. enum class). @@ -799,6 +833,8 @@ struct ConceptInfo : public SymbolInfo { ConceptInfo() : SymbolInfo(InfoType::IT_concept) {} ConceptInfo(SymbolID USR) : SymbolInfo(InfoType::IT_concept, USR) {} + static bool classof(const Info *I) { return I->IT == InfoType::IT_concept; } + void merge(ConceptInfo &&I); bool IsType = false; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index c7481fa5bada6..50118e0472075 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -363,17 +363,17 @@ static std::string serialize(const T &I, DiagnosticsEngine &Diags) { std::string serialize(const Info &I, DiagnosticsEngine &Diags) { switch (I.IT) { case InfoType::IT_namespace: - return serialize(static_cast<const NamespaceInfo &>(I), Diags); + return serialize(cast<NamespaceInfo>(I), Diags); case InfoType::IT_record: - return serialize(static_cast<const RecordInfo &>(I), Diags); + return serialize(cast<RecordInfo>(I), Diags); case InfoType::IT_enum: - return serialize(static_cast<const EnumInfo &>(I), Diags); + return serialize(cast<EnumInfo>(I), Diags); case InfoType::IT_function: - return serialize(static_cast<const FunctionInfo &>(I), Diags); + return serialize(cast<FunctionInfo>(I), Diags); case InfoType::IT_concept: - return serialize(static_cast<const ConceptInfo &>(I), Diags); + return serialize(cast<ConceptInfo>(I), Diags); case InfoType::IT_variable: - return serialize(static_cast<const VarInfo &>(I), Diags); + return serialize(cast<VarInfo>(I), Diags); case InfoType::IT_friend: case InfoType::IT_typedef: case InfoType::IT_default: diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index 3d2bb97335b6f..5a1d822526daa 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -567,19 +567,19 @@ llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, llvm::yaml::Output InfoYAML(OS); switch (I->IT) { case InfoType::IT_namespace: - InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I); + InfoYAML << *cast<NamespaceInfo>(I); break; case InfoType::IT_record: - InfoYAML << *static_cast<clang::doc::RecordInfo *>(I); + InfoYAML << *cast<RecordInfo>(I); break; case InfoType::IT_enum: - InfoYAML << *static_cast<clang::doc::EnumInfo *>(I); + InfoYAML << *cast<EnumInfo>(I); break; case InfoType::IT_function: - InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I); + InfoYAML << *cast<FunctionInfo>(I); break; case InfoType::IT_typedef: - InfoYAML << *static_cast<clang::doc::TypedefInfo *>(I); + InfoYAML << *cast<TypedefInfo>(I); break; case InfoType::IT_concept: case InfoType::IT_variable: diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 5d1d88a228cc6..38002f5111a9f 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -231,14 +231,10 @@ static llvm::Error getMdFiles(const char *Argv0, static void sortUsrToInfo(llvm::StringMap<doc::Info *> &USRToInfo) { for (auto &I : USRToInfo) { auto &Info = I.second; - if (Info->IT == doc::InfoType::IT_namespace) { - auto *Namespace = static_cast<clang::doc::NamespaceInfo *>(Info); + if (auto *Namespace = dyn_cast<doc::NamespaceInfo>(Info)) Namespace->Children.sort(); - } - if (Info->IT == doc::InfoType::IT_record) { - auto *Record = static_cast<clang::doc::RecordInfo *>(Info); + else if (auto *Record = dyn_cast<doc::RecordInfo>(Info)) Record->Children.sort(); - } } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
