[llvm] [TableGen] Fix null-pointer assert in RecordVal::setValue on failed cast (PR #195492)

Prerona Chaudhuri via llvm-commits llvm-commits at lists.llvm.org
Sat May 2 16:49:50 PDT 2026


https://github.com/pchaudhuri-nv created https://github.com/llvm/llvm-project/pull/195492

When setValue's getCastTo failed, Value was overwritten with nullptr instead of being left untouched. 
The "no value set" sentinel is UnsetInit, not nullptr, so a downstream RecordResolver::resolve that called isa<UnsetInit>(RV->getValue()) would assert on the null pointer when a later def tried to resolve an expression referring to that field.

Compute the cast into a local and only commit to Value on success, so a type-incompatible override (e.g. redeclaring an int field as string in a subclass) reports the existing "is incompatible" error and exits cleanly instead of aborting.

Fixes issue : https://github.com/llvm/llvm-project/issues/184879
Assisted by Claude.

>From 062f54701b6eae6c74c4bc3313667952e0fd5dbf Mon Sep 17 00:00:00 2001
From: pchaudhuri-nv <pchaudhuri at nvidia.com>
Date: Sat, 2 May 2026 23:34:17 +0000
Subject: [PATCH] [TableGen] Fix null-pointer assert in RecordVal::setValue on
 failed cast

When setValue's getCastTo failed, Value was overwritten with nullptr
instead of being left untouched. The "no value set" sentinel is
UnsetInit, not nullptr, so a downstream RecordResolver::resolve that
called isa<UnsetInit>(RV->getValue()) would assert on the null pointer
when a later def tried to resolve an expression referring to that field.

Compute the cast into a local and only commit to Value on success, so a
type-incompatible override (e.g. redeclaring an int field as string in a
subclass) reports the existing "is incompatible" error and exits cleanly
instead of aborting.

Assisted by Claude.
---
 llvm/lib/TableGen/Record.cpp                  |  5 +++--
 .../TableGen/incompatible-field-override.td   | 20 +++++++++++++++++++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/TableGen/incompatible-field-override.td

diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 4e931209e3e7c..3395d2dd10a1b 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -2891,10 +2891,11 @@ bool RecordVal::setValue(const Init *V) {
     return false;
   }
 
-  Value = V->getCastTo(getType());
-  if (!Value)
+  const Init *NewValue = V->getCastTo(getType());
+  if (!NewValue)
     return true;
 
+  Value = NewValue;
   assert(!isa<TypedInit>(Value) ||
          cast<TypedInit>(Value)->getType()->typeIsA(getType()));
   if (const auto *BTy = dyn_cast<BitsRecTy>(getType())) {
diff --git a/llvm/test/TableGen/incompatible-field-override.td b/llvm/test/TableGen/incompatible-field-override.td
new file mode 100644
index 0000000000000..869b1870e26bb
--- /dev/null
+++ b/llvm/test/TableGen/incompatible-field-override.td
@@ -0,0 +1,20 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
+// XFAIL: vg_leak
+
+// Redeclaring a field with an incompatible type used to leave the field's
+// Value as nullptr, causing an isa<UnsetInit>(nullptr) assert when a later
+// def tried to resolve an expression referring to that field.
+
+class X {
+  int F = 0;
+  int D = !add(F, 1);
+}
+
+// CHECK: error: Field 'F' of type 'int' is incompatible with value '"0"' of type 'string'
+// CHECK-NOT: Assertion `Val && "isa<> used on a null pointer"'
+// CHECK-NOT: PLEASE submit a bug report
+class Y : X  {
+  string F = "0";
+}
+
+def y : Y;



More information about the llvm-commits mailing list