From 43df8c474aa960c39f67cce2b1a2c70be84cdcb2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 22 Jul 2026 13:25:41 -0700 Subject: [PATCH] Replace `typeid(T).name()` with `llvm::getTypeName()`. (#7554) This produces prettier, demangled type names, and works when building with `-fno-rtti`. Before: ``` Optional N6Carbon5Parse13NodeIdForKindIL_ZNS0_8NodeKind16LibrarySpecifierEEEE: begin ``` After: ``` Optional Carbon::Parse::NodeIdForKind: begin ``` Assisted-by: Gemini via Antigravity --- toolchain/diagnostics/emitter.h | 3 +- toolchain/parse/extract.cpp | 14 ++--- toolchain/parse/tree.h | 4 +- toolchain/parse/typed_nodes_test.cpp | 82 +++++++++++++------------ toolchain/sem_ir/formatter.cpp | 3 +- toolchain/sem_ir/inst_fingerprinter.cpp | 4 +- 6 files changed, 61 insertions(+), 49 deletions(-) diff --git a/toolchain/diagnostics/emitter.h b/toolchain/diagnostics/emitter.h index a21da0507438..4ab7799fd381 100644 --- a/toolchain/diagnostics/emitter.h +++ b/toolchain/diagnostics/emitter.h @@ -14,6 +14,7 @@ #include "llvm/ADT/Any.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/TypeName.h" #include "toolchain/diagnostics/consumer.h" #include "toolchain/diagnostics/diagnostic.h" #include "toolchain/diagnostics/kind.h" @@ -530,7 +531,7 @@ auto Emitter::MakeAny(Arg arg) -> llvm::Any { using Storage = Internal::DiagnosticTypeForArg::StorageType; CARBON_CHECK(llvm::any_cast(&converted), "Failed to convert argument of type {0} to its storage type {1}", - typeid(Arg).name(), typeid(Storage).name()); + llvm::getTypeName(), llvm::getTypeName()); return converted; } diff --git a/toolchain/parse/extract.cpp b/toolchain/parse/extract.cpp index a4b8d890073f..faba878cfe74 100644 --- a/toolchain/parse/extract.cpp +++ b/toolchain/parse/extract.cpp @@ -5,12 +5,12 @@ #include #include #include -#include #include #include "common/error.h" #include "common/find.h" #include "common/struct_reflection.h" +#include "llvm/Support/TypeName.h" #include "toolchain/parse/tree.h" #include "toolchain/parse/tree_and_subtrees.h" #include "toolchain/parse/typed_nodes.h" @@ -288,13 +288,13 @@ template struct Extractable> { static auto Extract(NodeExtractor& extractor) -> std::optional> { - extractor.MaybeTrace("Optional {0}: begin\n", typeid(T).name()); + extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName()); auto checkpoint = extractor.Checkpoint(); std::optional value = Extractable::Extract(extractor); if (value) { - extractor.MaybeTrace("Optional {0}: found\n", typeid(T).name()); + extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName()); } else { - extractor.MaybeTrace("Optional {0}: missing\n", typeid(T).name()); + extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName()); extractor.RestoreCheckpoint(checkpoint); } return value; @@ -349,7 +349,7 @@ auto NodeExtractor::ExtractTupleLikeType( std::index_sequence /*indices*/, std::tuple* /*type*/) -> std::optional { std::tuple...> fields; - MaybeTrace("Aggregate {0}: begin\n", typeid(T).name()); + MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName()); // Use a fold over the `=` operator to parse fields from right to left. [[maybe_unused]] int unused; bool ok = true; @@ -358,11 +358,11 @@ auto NodeExtractor::ExtractTupleLikeType( .has_value()), unused) = ... = 0)); if (!ok) { - MaybeTrace("Aggregate {0}: error\n", typeid(T).name()); + MaybeTrace("Aggregate {0}: error\n", llvm::getTypeName()); return std::nullopt; } - MaybeTrace("Aggregate {0}: success\n", typeid(T).name()); + MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName()); return T{std::move(std::get(fields).value())...}; } diff --git a/toolchain/parse/tree.h b/toolchain/parse/tree.h index aa92e2862989..85798beb945e 100644 --- a/toolchain/parse/tree.h +++ b/toolchain/parse/tree.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Support/TypeName.h" #include "toolchain/base/value_store.h" #include "toolchain/lex/tokenized_buffer.h" #include "toolchain/parse/node_ids.h" @@ -156,7 +157,8 @@ class Tree : public Printable { auto As(NodeId n) const -> T { CARBON_DCHECK(n.has_value()); CARBON_DCHECK(ConvertTo::AllowedFor(node_kind(n)), - "cannot convert {0} to {1}", node_kind(n), typeid(T).name()); + "cannot convert {0} to {1}", node_kind(n), + llvm::getTypeName()); return T::UnsafeMake(n); } diff --git a/toolchain/parse/typed_nodes_test.cpp b/toolchain/parse/typed_nodes_test.cpp index a0ebbb143cbd..9de998d31b9b 100644 --- a/toolchain/parse/typed_nodes_test.cpp +++ b/toolchain/parse/typed_nodes_test.cpp @@ -151,19 +151,20 @@ TEST_F(TypedNodeTest, VerifyExtractTracePackage) { Peer::VerifyExtractAs(tree, file.decls[0], &trace); EXPECT_TRUE(library.has_value()); Error err = trace; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin -Optional [^:]*: begin + R"Trace(Aggregate .*: begin +Optional .*: begin NodeIdForKind error: wrong kind IdentifierPackageName, expected LibrarySpecifier -Optional [^:]*: missing +Optional .*: missing NodeIdInCategory PackageName: kind IdentifierPackageName consumed Vector: begin NodeIdInCategory Modifier: kind ImplModifier consumed NodeIdInCategory Modifier error: kind PackageIntroducer doesn't match Vector: end NodeIdForKind: PackageIntroducer consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); } @@ -179,16 +180,17 @@ TEST_F(TypedNodeTest, VerifyExtractTraceLibrary) { Peer::VerifyExtractAs(tree, file.decls[0], &trace); EXPECT_TRUE(library.has_value()); Error err = trace; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin + R"Trace(Aggregate .*: begin NodeIdOneOf LibraryName or DefaultLibrary: DefaultLibrary consumed Vector: begin NodeIdInCategory Modifier: kind ImplModifier consumed NodeIdInCategory Modifier error: kind LibraryIntroducer doesn't match Vector: end NodeIdForKind: LibraryIntroducer consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); } @@ -203,23 +205,24 @@ TEST_F(TypedNodeTest, VerifyExtractTraceVarNoInit) { auto var = Peer::VerifyExtractAs(tree, file.decls[0], &trace); ASSERT_TRUE(var.has_value()); Error err = trace; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin -Optional [^:]*: begin -Aggregate [^:]*: begin + R"Trace(Aggregate .*: begin +Optional .*: begin +Aggregate .*: begin NodeIdInCategory Expr error: kind VariablePattern doesn't match -Aggregate [^:]*: error -Optional [^:]*: missing +Aggregate .*: error +Optional .*: missing NodeIdForKind: VariablePattern consumed -Optional [^:]*: begin +Optional .*: begin NodeIdForKind error: wrong kind VariableIntroducer, expected ReturnedModifier -Optional [^:]*: missing +Optional .*: missing Vector: begin NodeIdInCategory Modifier error: kind VariableIntroducer doesn't match Vector: end NodeIdForKind: VariableIntroducer consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); } @@ -234,24 +237,25 @@ TEST_F(TypedNodeTest, VerifyExtractTraceExpression) { auto var = Peer::VerifyExtractAs(tree, file.decls[0], &trace1); ASSERT_TRUE(var.has_value()); Error err1 = trace1; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err1.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin -Optional [^:]*: begin -Aggregate [^:]*: begin + R"Trace(Aggregate .*: begin +Optional .*: begin +Aggregate .*: begin NodeIdInCategory Expr: kind MemberAccessExpr consumed NodeIdForKind: VariableInitializer consumed -Aggregate [^:]*: success -Optional [^:]*: found +Aggregate .*: success +Optional .*: found NodeIdForKind: VariablePattern consumed -Optional [^:]*: begin +Optional .*: begin NodeIdForKind error: wrong kind VariableIntroducer, expected ReturnedModifier -Optional [^:]*: missing +Optional .*: missing Vector: begin NodeIdInCategory Modifier error: kind VariableIntroducer doesn't match Vector: end NodeIdForKind: VariableIntroducer consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); ASSERT_TRUE(var->initializer.has_value()); @@ -260,12 +264,13 @@ Aggregate [^:]*: success tree, var->initializer->value, &trace2); ASSERT_TRUE(value.has_value()); Error err2 = trace2; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err2.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin + R"Trace(Aggregate .*: begin NodeIdInCategory IntConst\|MemberExpr\|MemberName: kind IdentifierNameNotBeforeSignature consumed NodeIdInCategory Expr: kind PointerMemberAccessExpr consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); } @@ -281,29 +286,30 @@ TEST_F(TypedNodeTest, VerifyExtractTraceClassDecl) { Peer::VerifyExtractAs(tree, file.decls[0], &trace); EXPECT_TRUE(class_decl.has_value()); Error err = trace; - // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`. + // Use Regex matching to avoid hard-coding the result of + // `llvm::getTypeName()`. EXPECT_THAT(err.message(), testing::MatchesRegex( - R"Trace(Aggregate [^:]*: begin -Aggregate [^:]*: begin -Optional [^:]*: begin + R"Trace(Aggregate .*: begin +Aggregate .*: begin +Optional .*: begin NodeIdForKind: ExplicitParamList consumed -Optional [^:]*: found -Optional [^:]*: begin +Optional .*: found +Optional .*: begin NodeIdForKind error: wrong kind IdentifierNameMaybeBeforeSignature, expected ImplicitParamList -Optional [^:]*: missing +Optional .*: missing NodeIdInCategory NonExprName: kind IdentifierNameMaybeBeforeSignature consumed Vector: begin NodeIdOneOf IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams: IdentifierNameQualifierWithoutParams consumed NodeIdOneOf error: wrong kind AbstractModifier, expected IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams Vector: end -Aggregate [^:]*: success +Aggregate .*: success Vector: begin NodeIdInCategory Modifier: kind AbstractModifier consumed NodeIdInCategory Modifier: kind PrivateModifier consumed NodeIdInCategory Modifier error: kind ClassIntroducer doesn't match Vector: end NodeIdForKind: ClassIntroducer consumed -Aggregate [^:]*: success +Aggregate .*: success )Trace")); } diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 5eb71935792d..7a4151eb0732 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/TypeName.h" #include "toolchain/base/fixed_size_value_store.h" #include "toolchain/base/kind_switch.h" #include "toolchain/base/shared_value_stores.h" @@ -1086,7 +1087,7 @@ auto Formatter::FormatInstArgAndKind(IdAndKind arg_and_kind) -> void { } else if constexpr (std::is_same_v) { // Do nothing } else { - CARBON_FATAL("Missing FormatArg for {0}", typeid(IdT).name()); + CARBON_FATAL("Missing FormatArg for {0}", llvm::getTypeName()); } }); } diff --git a/toolchain/sem_ir/inst_fingerprinter.cpp b/toolchain/sem_ir/inst_fingerprinter.cpp index cbfd3bec7b06..94d514e8f0d6 100644 --- a/toolchain/sem_ir/inst_fingerprinter.cpp +++ b/toolchain/sem_ir/inst_fingerprinter.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StableHashing.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/TypeName.h" #include "llvm/Support/raw_ostream.h" #include "toolchain/base/fixed_size_value_store.h" #include "toolchain/base/kind_switch.h" @@ -651,7 +652,8 @@ struct Worklist { template requires(SameAsOneOf) auto Add(T /*arg*/) -> void { - CARBON_FATAL("Unexpected instruction operand kind {0}", typeid(T).name()); + CARBON_FATAL("Unexpected instruction operand kind {0}", + llvm::getTypeName()); } auto Add(IdAndKind::InvalidType /*invalid*/) -> void {