summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/TableGen/TGParser.cpp3
-rw-r--r--llvm/test/TableGen/MultiClass-defm-fail.td32
-rw-r--r--llvm/test/TableGen/MultiClass-defm.td50
3 files changed, 85 insertions, 0 deletions
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 10345b99706..baf97baa4c2 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -740,6 +740,9 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
}
if (CurMultiClass) {
+ if (Name->getValue() == "NAME")
+ return VarInit::get(Name, StringRecTy::get());
+
Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::");
if (CurMultiClass->Rec.isTemplateArg(MCName)) {
diff --git a/llvm/test/TableGen/MultiClass-defm-fail.td b/llvm/test/TableGen/MultiClass-defm-fail.td
new file mode 100644
index 00000000000..6642d330a1e
--- /dev/null
+++ b/llvm/test/TableGen/MultiClass-defm-fail.td
@@ -0,0 +1,32 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
+// XFAIL: vg_leak
+
+// This test verifies that tablegen does fail if it can't resolve an unresolved
+// !cast() during processing top-level defm.
+
+class A {}
+class B<A a> {
+ A ba = a;
+}
+
+multiclass M0<string s> {
+ // This should work fine.
+ def _m00 : B<!cast<A>(s)>;
+ // CHECK: error: Undefined reference:'d1_r1_no_such_record'
+ def _m01: B<!cast<A>(s#"_no_such_record")>;
+}
+
+multiclass M1<string s> {
+ def _r1 : A;
+ // It would be nice if we could refer to _r1's name without having to pass it
+ // explicitly via 's'.
+ // XCHECK-DAG: note: instantiated from multiclass
+ defm _m1: M0<s # "_r1">;
+}
+
+// CHECK: defm d1: M1
+// CHECK: note: instantiated from multiclass
+// CHECK: defm _m1: M0
+// CHECK: note: instantiated from multiclass
+// CHECK: def _m01: B
+defm d1: M1<"d1">;
diff --git a/llvm/test/TableGen/MultiClass-defm.td b/llvm/test/TableGen/MultiClass-defm.td
new file mode 100644
index 00000000000..d0a83e716ad
--- /dev/null
+++ b/llvm/test/TableGen/MultiClass-defm.td
@@ -0,0 +1,50 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class A {}
+class B<A a> {
+ A ba = a;
+}
+
+multiclass M0<string s> {
+ def _m0 : B<!cast<A>(s)>;
+
+ // Uncomment to test that !cast will eventually fail if the record it refers
+ // to does not exist by the time we instantiate this record from the top
+ // level.
+ //def _m1 : B<!cast<A>(s#"X")>;
+}
+
+multiclass M1<string s> {
+ def _r1 : A;
+ // It would be nice if we could refer to _r1's name without having to pass it
+ // explicitly via 's'.
+ defm _m1: M0<s # "_r1">;
+}
+
+multiclass M2 {
+ def _x : A {
+ string n = NAME;
+ }
+
+ def _y : B<!cast<A>(NAME # "_x")>;
+
+ // This used to throw an error during multiclass parsing as NAME was not
+ // recognized when parsing the template arguments.
+ defm NAME: M1<NAME>;
+}
+defm d0: M2;
+// CHECK-LABEL: def d0_m1_m0
+// CHECK: A ba = d0_r1;
+//
+// CHECK-LABEL: def d0_x {
+// CHECK: string n = "d0";
+//
+// CHECK-LABEL: def d0_y {
+// CHECK: A ba = d0_x;
+
+// This always works, because d1_r1 is instantiated before d1_m1 which would
+// attempt to !cast to it.
+defm d1: M1<"d1">;
+// CHECK-LABEL: def d1_m1_m0
+// CHECK: A ba = d1_r1;
OpenPOWER on IntegriCloud