Replace typeid(T).name() with llvm::getTypeName<T>(). (#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<Carbon::Parse::NodeKind::LibrarySpecifier>: begin
```

Assisted-by: Gemini via Antigravity
This commit is contained in:
Richard Smith
2026-07-22 20:25:41 +00:00
committed by GitHub
parent 453b5474e4
commit 43df8c474a
6 changed files with 61 additions and 49 deletions
+2 -1
View File
@@ -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<LocT>::MakeAny(Arg arg) -> llvm::Any {
using Storage = Internal::DiagnosticTypeForArg<Arg>::StorageType;
CARBON_CHECK(llvm::any_cast<Storage>(&converted),
"Failed to convert argument of type {0} to its storage type {1}",
typeid(Arg).name(), typeid(Storage).name());
llvm::getTypeName<Arg>(), llvm::getTypeName<Storage>());
return converted;
}
+7 -7
View File
@@ -5,12 +5,12 @@
#include <initializer_list>
#include <optional>
#include <tuple>
#include <typeinfo>
#include <utility>
#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 <typename T>
struct Extractable<std::optional<T>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<std::optional<T>> {
extractor.MaybeTrace("Optional {0}: begin\n", typeid(T).name());
extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName<T>());
auto checkpoint = extractor.Checkpoint();
std::optional<T> value = Extractable<T>::Extract(extractor);
if (value) {
extractor.MaybeTrace("Optional {0}: found\n", typeid(T).name());
extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName<T>());
} else {
extractor.MaybeTrace("Optional {0}: missing\n", typeid(T).name());
extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName<T>());
extractor.RestoreCheckpoint(checkpoint);
}
return value;
@@ -349,7 +349,7 @@ auto NodeExtractor::ExtractTupleLikeType(
std::index_sequence<Index...> /*indices*/, std::tuple<U...>* /*type*/)
-> std::optional<T> {
std::tuple<std::optional<U>...> fields;
MaybeTrace("Aggregate {0}: begin\n", typeid(T).name());
MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName<T>());
// 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<T>());
return std::nullopt;
}
MaybeTrace("Aggregate {0}: success\n", typeid(T).name());
MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName<T>());
return T{std::move(std::get<Index>(fields).value())...};
}
+3 -1
View File
@@ -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<Tree> {
auto As(NodeId n) const -> T {
CARBON_DCHECK(n.has_value());
CARBON_DCHECK(ConvertTo<T>::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<T>());
return T::UnsafeMake(n);
}
+44 -38
View File
@@ -151,19 +151,20 @@ TEST_F(TypedNodeTest, VerifyExtractTracePackage) {
Peer::VerifyExtractAs<PackageDecl>(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<T>()`.
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<LibraryDecl>(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<T>()`.
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<VariableDecl>(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<T>()`.
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<VariableDecl>(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<T>()`.
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<T>()`.
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<ClassDecl>(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<T>()`.
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"));
}
+2 -1
View File
@@ -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<IdT, IdAndKind::NoneType>) {
// Do nothing
} else {
CARBON_FATAL("Missing FormatArg for {0}", typeid(IdT).name());
CARBON_FATAL("Missing FormatArg for {0}", llvm::getTypeName<IdT>());
}
});
}
+3 -1
View File
@@ -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 <typename T>
requires(SameAsOneOf<T, AnyRawId, LocId>)
auto Add(T /*arg*/) -> void {
CARBON_FATAL("Unexpected instruction operand kind {0}", typeid(T).name());
CARBON_FATAL("Unexpected instruction operand kind {0}",
llvm::getTypeName<T>());
}
auto Add(IdAndKind::InvalidType /*invalid*/) -> void {