[llvm] [TableGen] Add submulticlass typechecking to template arg values (PR #197128)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 12 01:52:40 PDT 2026


https://github.com/jofrn created https://github.com/llvm/llvm-project/pull/197128

## Summary
- Add a `CheckTemplateArgValues` call in `ParseSubMultiClassReference` so submulticlass references type-check their template arg values, matching the behavior already in `ParseSubClassReference`.
- Pass the per-argument `ArgLocs` (already collected by `ParseTemplateArgValueList`) so diagnostics point at the offending argument instead of the start of the submulticlass reference.
- Add `submulticlass-typecheck.td` covering the new diagnostic, and `submulticlass-leteq.td` exercising the resulting `!eq` resolution behavior.

This is a rebased + cleaned-up version of #112904 (LGTM'd by @jayfoad), with the suggested change to use `ArgLocs` rather than `Result.RefRange.Start`. The original PR's collateral .td fixups have since landed separately on main, so none are needed here.

Resolves #84910.

## Test plan
- [x] `ninja -C build llvm-tblgen`
- [x] `llvm-lit llvm/test/TableGen/` (411/411 passing, including the two new tests)

>From ef366bc82dd573130320651fe60550ddc57139df Mon Sep 17 00:00:00 2001
From: jofrn <165626406+jofrn at users.noreply.github.com>
Date: Tue, 12 May 2026 01:50:39 -0700
Subject: [PATCH] [TableGen] Added submulticlass typechecking to template arg
 values.

Some typechecking was missing when parsing a submulticlass reference. Add the
CheckTemplateArgValues call in ParseSubMultiClassReference, using the per-arg
ArgLocs captured by ParseTemplateArgValueList so diagnostics point at the
offending argument.

Resolves https://github.com/llvm/llvm-project/issues/84910.
---
 llvm/lib/TableGen/TGParser.cpp                |  5 +++++
 llvm/test/TableGen/submulticlass-leteq.td     | 21 +++++++++++++++++++
 llvm/test/TableGen/submulticlass-typecheck.td | 12 +++++++++++
 3 files changed, 38 insertions(+)
 create mode 100644 llvm/test/TableGen/submulticlass-leteq.td
 create mode 100644 llvm/test/TableGen/submulticlass-typecheck.td

diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 25405eef60366..c44e067a9da9f 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -863,6 +863,11 @@ TGParser::ParseSubMultiClassReference(MultiClass *CurMC) {
     return Result;
   }
 
+  if (CheckTemplateArgValues(Result.TemplateArgs, ArgLocs, &Result.MC->Rec)) {
+    Result.MC = nullptr; // Error checking value list.
+    return Result;
+  }
+
   Result.RefRange.End = Lex.getLoc();
 
   return Result;
diff --git a/llvm/test/TableGen/submulticlass-leteq.td b/llvm/test/TableGen/submulticlass-leteq.td
new file mode 100644
index 0000000000000..eeaa523d870ec
--- /dev/null
+++ b/llvm/test/TableGen/submulticlass-leteq.td
@@ -0,0 +1,21 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+// CHECK:      def X0 { // C
+// CHECK-NEXT:   bit x = 1;
+// CHECK-NEXT: }
+// CHECK-NEXT: def X1 { // C
+// CHECK-NEXT:   bit x = 0;
+// CHECK-NEXT: }
+class C {
+  bit x;
+}
+multiclass M0<bits<8> Val> {
+  let x = !eq(Val, !cast<bits<8>>(-1)) in def NAME : C;
+}
+multiclass M1<bits<8> Val> {
+  let x = !eq(Val, -1) in def NAME : C;
+}
+multiclass M2_0 : M0<-1>;
+multiclass M2_1 : M1<-1>;
+defm X0 : M2_0;
+defm X1 : M2_1;
diff --git a/llvm/test/TableGen/submulticlass-typecheck.td b/llvm/test/TableGen/submulticlass-typecheck.td
new file mode 100644
index 0000000000000..2abc892a7a211
--- /dev/null
+++ b/llvm/test/TableGen/submulticlass-typecheck.td
@@ -0,0 +1,12 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
+// XFAIL: vg_leak
+// CHECK: {{.*}}:11:30: error: Value specified for template argument 'B::op' is of type bits<4>; expected type bits<8>: C::op
+// CHECK-NEXT: multiclass C<bits<4> op> : B<op>;
+class A<bits<8> op> {
+  bits<8> f = op;
+}
+multiclass B<bits<8> op> {
+  def : A<op>;
+}
+multiclass C<bits<4> op> : B<op>;
+defm D : C<0>;



More information about the llvm-commits mailing list