[llvm] [TableGen] Support type aliases via new keyword deftype (PR #79570)
Wang Pengcheng via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 31 22:12:46 PST 2024
https://github.com/wangpc-pp updated https://github.com/llvm/llvm-project/pull/79570
>From 867058380e5b02f1fc7fa0d00a0122ec03d7f82b Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Fri, 26 Jan 2024 18:22:49 +0800
Subject: [PATCH 1/7] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.4
---
llvm/docs/TableGen/ProgRef.rst | 18 ++++++++++++---
llvm/lib/TableGen/TGLexer.cpp | 1 +
llvm/lib/TableGen/TGLexer.h | 1 +
llvm/lib/TableGen/TGParser.cpp | 41 +++++++++++++++++++++++++++++++++-
llvm/lib/TableGen/TGParser.h | 2 ++
llvm/test/TableGen/deftype.td | 22 ++++++++++++++++++
6 files changed, 81 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/TableGen/deftype.td
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index 59ddef975c487..f1bbe32ec2047 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -570,8 +570,8 @@ files.
.. productionlist::
TableGenFile: (`Statement` | `IncludeDirective`
:| `PreprocessorDirective`)*
- Statement: `Assert` | `Class` | `Def` | `Defm` | `Defset` | `Defvar`
- :| `Dump` | `Foreach` | `If` | `Let` | `MultiClass`
+ Statement: `Assert` | `Class` | `Def` | `Defm` | `Defset` | `Deftype`
+ :| `Defvar` | `Dump` | `Foreach` | `If` | `Let` | `MultiClass`
The following sections describe each of these top-level statements.
@@ -931,7 +931,8 @@ template that expands into multiple records.
: `ParentClassList`
: "{" `MultiClassStatement`+ "}"
MultiClassID: `TokIdentifier`
- MultiClassStatement: `Assert` | `Def` | `Defm` | `Defvar` | `Foreach` | `If` | `Let`
+ MultiClassStatement: `Assert` | `Def` | `Defm` | `Deftype` | `Defvar`
+ :| `Foreach` | `If` | `Let`
As with regular classes, the multiclass has a name and can accept template
arguments. A multiclass can inherit from other multiclasses, which causes
@@ -1215,6 +1216,17 @@ set.
Anonymous records created inside initialization expressions using the
``ClassID<...>`` syntax are not collected in the set.
+``deftype`` --- define a type
+--------------------------------
+
+A ``deftype`` statement defines a type. Its value can be used
+throughout the statements that follow the definition.
+
+.. productionlist::
+ Deftype: "deftype" `TokIdentifier` "=" `Value` ";"
+
+The identifier on the left of the ``=`` is defined to be a type name
+whose actual type is given by the type expression on the right of the ``=``.
``defvar`` --- define a variable
--------------------------------
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index c811a67d930d4..545643234f699 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -360,6 +360,7 @@ tgtok::TokKind TGLexer::LexIdentifier() {
.Case("foreach", tgtok::Foreach)
.Case("defm", tgtok::Defm)
.Case("defset", tgtok::Defset)
+ .Case("deftype", tgtok::Deftype)
.Case("multiclass", tgtok::MultiClass)
.Case("field", tgtok::Field)
.Case("let", tgtok::Let)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 2e2aa59f34408..25dcd9fbadef7 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -97,6 +97,7 @@ enum TokKind {
Def,
Defm,
Defset,
+ Deftype,
Defvar,
Dump,
Foreach,
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index e7dcb91ba20a6..1574505ded33a 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1103,11 +1103,17 @@ RecTy *TGParser::ParseType() {
case tgtok::Dag:
Lex.Lex();
return DagRecTy::get(Records);
- case tgtok::Id:
+ case tgtok::Id: {
+ std::string TypeName = Lex.getCurStrVal();
+ if (TypeAliases.count(TypeName)) {
+ Lex.Lex();
+ return TypeAliases[TypeName];
+ }
if (Record *R = ParseClassID())
return RecordRecTy::get(R);
TokError("unknown class name");
return nullptr;
+ }
case tgtok::Bits: {
if (Lex.Lex() != tgtok::less) { // Eat 'bits'
TokError("expected '<' after bits type");
@@ -3665,6 +3671,36 @@ bool TGParser::ParseDefset() {
return false;
}
+/// ParseDeftype - Parse a defvar statement.
+///
+/// Deftype ::= DEFTYPE Id '=' Value ';'
+///
+bool TGParser::ParseDeftype() {
+ assert(Lex.getCode() == tgtok::Deftype);
+ Lex.Lex(); // Eat the 'deftype' token
+
+ if (Lex.getCode() != tgtok::Id)
+ return TokError("expected identifier");
+
+ std::string TypeName = Lex.getCurStrVal();
+ if (TypeAliases.count(TypeName))
+ return TokError("type of this name already exists");
+
+ Lex.Lex();
+ if (!consume(tgtok::equal))
+ return TokError("expected '='");
+
+ RecTy *Type = ParseType();
+ if (!Type)
+ return true;
+ TypeAliases[TypeName] = Type;
+
+ if (!consume(tgtok::semi))
+ return TokError("expected ';'");
+
+ return false;
+}
+
/// ParseDefvar - Parse a defvar statement.
///
/// Defvar ::= DEFVAR Id '=' Value ';'
@@ -4265,6 +4301,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
/// Object ::= LETCommand '{' ObjectList '}'
/// Object ::= LETCommand Object
/// Object ::= Defset
+/// Object ::= Deftype
/// Object ::= Defvar
/// Object ::= Assert
/// Object ::= Dump
@@ -4276,6 +4313,8 @@ bool TGParser::ParseObject(MultiClass *MC) {
case tgtok::Assert: return ParseAssert(MC);
case tgtok::Def: return ParseDef(MC);
case tgtok::Defm: return ParseDefm(MC);
+ case tgtok::Deftype:
+ return ParseDeftype();
case tgtok::Defvar: return ParseDefvar();
case tgtok::Dump:
return ParseDump(MC);
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index 0929154fed3d4..b08e250870901 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -143,6 +143,7 @@ class TGParser {
TGLexer Lex;
std::vector<SmallVector<LetRecord, 4>> LetStack;
std::map<std::string, std::unique_ptr<MultiClass>> MultiClasses;
+ std::map<std::string, RecTy *> TypeAliases;
/// Loops - Keep track of any foreach loops we are within.
///
@@ -264,6 +265,7 @@ class TGParser {
bool ParseDefm(MultiClass *CurMultiClass);
bool ParseDef(MultiClass *CurMultiClass);
bool ParseDefset();
+ bool ParseDeftype();
bool ParseDefvar(Record *CurRec = nullptr);
bool ParseDump(MultiClass *CurMultiClass, Record *CurRec = nullptr);
bool ParseForeach(MultiClass *CurMultiClass);
diff --git a/llvm/test/TableGen/deftype.td b/llvm/test/TableGen/deftype.td
new file mode 100644
index 0000000000000..ee430cbdaf7a2
--- /dev/null
+++ b/llvm/test/TableGen/deftype.td
@@ -0,0 +1,22 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+
+deftype Byte = bits<8>;
+deftype IntList = list<int>;
+deftype ByteList = list<Byte>;
+class Class<Byte b> {
+ Byte byte = b;
+}
+deftype ClassList = list<Class>;
+
+// CHECK: def test {
+// CHECK-NEXT: bits<8> byte = { 0, 1, 1, 1, 1, 0, 1, 1 };
+// CHECK-NEXT: list<int> ints = [1, 2, 3];
+// CHECK-NEXT: list<bits<8>> bytes = [{ 0, 0, 0, 0, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 1, 1 }];
+// CHECK-NEXT: list<Class> defs = [anonymous_0, anonymous_1, anonymous_2];
+// CHECK-NEXT: }
+def test {
+ Byte byte = 123;
+ IntList ints = [1, 2, 3];
+ ByteList bytes = [1, 2, 3];
+ ClassList defs = [Class<1>, Class<2>, Class<3>];
+}
>From 3f642857652aeecc140eaf0641e73f789945f733 Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Fri, 26 Jan 2024 18:29:19 +0800
Subject: [PATCH 2/7] Reword doc
Created using spr 1.3.4
---
llvm/docs/TableGen/ProgRef.rst | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index f1bbe32ec2047..41196d7cdc6ce 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -931,8 +931,7 @@ template that expands into multiple records.
: `ParentClassList`
: "{" `MultiClassStatement`+ "}"
MultiClassID: `TokIdentifier`
- MultiClassStatement: `Assert` | `Def` | `Defm` | `Deftype` | `Defvar`
- :| `Foreach` | `If` | `Let`
+ MultiClassStatement: `Assert` | `Def` | `Defm` | `Defvar` | `Foreach` | `If` | `Let`
As with regular classes, the multiclass has a name and can accept template
arguments. A multiclass can inherit from other multiclasses, which causes
@@ -1219,15 +1218,18 @@ Anonymous records created inside initialization expressions using the
``deftype`` --- define a type
--------------------------------
-A ``deftype`` statement defines a type. Its value can be used
-throughout the statements that follow the definition.
+A ``deftype`` statement defines a type. The type can be used throughout the
+statements that follow the definition.
.. productionlist::
- Deftype: "deftype" `TokIdentifier` "=" `Value` ";"
+ Deftype: "deftype" `TokIdentifier` "=" `Type` ";"
The identifier on the left of the ``=`` is defined to be a type name
whose actual type is given by the type expression on the right of the ``=``.
+Currently, only primitive types are supported and ``deftype`` statements can
+only appear at the top level.
+
``defvar`` --- define a variable
--------------------------------
>From 14e3e83472c4d9391709e35dc29bce0735634a10 Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Fri, 26 Jan 2024 18:37:15 +0800
Subject: [PATCH 3/7] Type name should not be conflict with exited class
Created using spr 1.3.4
---
llvm/lib/TableGen/TGParser.cpp | 4 ++--
llvm/test/TableGen/deftype.td | 12 ++++++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 1574505ded33a..f6d82cddc6a05 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -3683,8 +3683,8 @@ bool TGParser::ParseDeftype() {
return TokError("expected identifier");
std::string TypeName = Lex.getCurStrVal();
- if (TypeAliases.count(TypeName))
- return TokError("type of this name already exists");
+ if (TypeAliases.count(TypeName) || Records.getClass(TypeName))
+ return TokError("type of this name '" + TypeName + "' already exists");
Lex.Lex();
if (!consume(tgtok::equal))
diff --git a/llvm/test/TableGen/deftype.td b/llvm/test/TableGen/deftype.td
index ee430cbdaf7a2..baf403e27ab04 100644
--- a/llvm/test/TableGen/deftype.td
+++ b/llvm/test/TableGen/deftype.td
@@ -1,4 +1,6 @@
// RUN: llvm-tblgen %s | FileCheck %s
+// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
+// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s
deftype Byte = bits<8>;
deftype IntList = list<int>;
@@ -20,3 +22,13 @@ def test {
ByteList bytes = [1, 2, 3];
ClassList defs = [Class<1>, Class<2>, Class<3>];
}
+
+#ifdef ERROR1
+// ERROR1: [[@LINE+1]]:9: error: type of this name 'Byte' already exists
+deftype Byte = bits<8>;
+#endif
+
+#ifdef ERROR2
+// ERROR2: [[@LINE+1]]:9: error: type of this name 'Class' already exists
+deftype Class = int;
+#endif
>From 96f1649803d6cef1aaa2222481b2b9921d5dc08d Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Mon, 29 Jan 2024 16:15:49 +0800
Subject: [PATCH 4/7] Address comments and add more tests
Created using spr 1.3.4
---
llvm/docs/TableGen/ProgRef.rst | 4 ++--
llvm/lib/TableGen/TGParser.cpp | 8 ++++++-
llvm/test/TableGen/deftype.td | 44 ++++++++++++++++++++++++++--------
3 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index 41196d7cdc6ce..45fda317ef643 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -1227,8 +1227,8 @@ statements that follow the definition.
The identifier on the left of the ``=`` is defined to be a type name
whose actual type is given by the type expression on the right of the ``=``.
-Currently, only primitive types are supported and ``deftype`` statements can
-only appear at the top level.
+Currently, only primitive types and type aliases are supported to be the source
+type and `deftype` statements can only appear at the top level.
``defvar`` --- define a variable
--------------------------------
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index f6d82cddc6a05..0f054c8fdd539 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -3673,7 +3673,7 @@ bool TGParser::ParseDefset() {
/// ParseDeftype - Parse a defvar statement.
///
-/// Deftype ::= DEFTYPE Id '=' Value ';'
+/// Deftype ::= DEFTYPE Id '=' Type ';'
///
bool TGParser::ParseDeftype() {
assert(Lex.getCode() == tgtok::Deftype);
@@ -3690,9 +3690,15 @@ bool TGParser::ParseDeftype() {
if (!consume(tgtok::equal))
return TokError("expected '='");
+ SMLoc Loc = Lex.getLoc();
RecTy *Type = ParseType();
if (!Type)
return true;
+
+ if (Type->getRecTyKind() == RecTy::RecordRecTyKind)
+ return Error(Loc, "cannot define type alias for class type '" +
+ Type->getAsString() + "'");
+
TypeAliases[TypeName] = Type;
if (!consume(tgtok::semi))
diff --git a/llvm/test/TableGen/deftype.td b/llvm/test/TableGen/deftype.td
index baf403e27ab04..666c3a2a57d96 100644
--- a/llvm/test/TableGen/deftype.td
+++ b/llvm/test/TableGen/deftype.td
@@ -1,26 +1,45 @@
// RUN: llvm-tblgen %s | FileCheck %s
// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s
+// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s
-deftype Byte = bits<8>;
-deftype IntList = list<int>;
-deftype ByteList = list<Byte>;
-class Class<Byte b> {
- Byte byte = b;
+class Class<int v> {
+ int value = v;
}
-deftype ClassList = list<Class>;
+
+deftype StringAlias = string;
+deftype CodeAlias = code;
+deftype DagAlias = dag;
+deftype Boolean = bit;
+deftype Byte = bits<8>;
+deftype Integer = int;
+deftype IntList = list<int>;
+deftype ByteList = list<Byte>;
+deftype ClassList = list<Class>;
+// The type can be another type alias.
+deftype ClassListAlias = ClassList;
// CHECK: def test {
+// CHECK-NEXT: string str = "string";
+// CHECK-NEXT: string codeStr = "code";
+// CHECK-NEXT: dag dagExpr = ("string" "code");
+// CHECK-NEXT: bit bool = 0;
// CHECK-NEXT: bits<8> byte = { 0, 1, 1, 1, 1, 0, 1, 1 };
+// CHECK-NEXT: int integer = 123;
// CHECK-NEXT: list<int> ints = [1, 2, 3];
// CHECK-NEXT: list<bits<8>> bytes = [{ 0, 0, 0, 0, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 1, 1 }];
// CHECK-NEXT: list<Class> defs = [anonymous_0, anonymous_1, anonymous_2];
// CHECK-NEXT: }
def test {
- Byte byte = 123;
- IntList ints = [1, 2, 3];
- ByteList bytes = [1, 2, 3];
- ClassList defs = [Class<1>, Class<2>, Class<3>];
+ StringAlias str = "string";
+ CodeAlias codeStr = "code";
+ DagAlias dagExpr = (str codeStr);
+ Boolean bool = false;
+ Byte byte = 123;
+ Integer integer = 123;
+ IntList ints = [1, 2, 3];
+ ByteList bytes = [1, 2, 3];
+ ClassListAlias defs = [Class<1>, Class<2>, Class<3>];
}
#ifdef ERROR1
@@ -32,3 +51,8 @@ deftype Byte = bits<8>;
// ERROR2: [[@LINE+1]]:9: error: type of this name 'Class' already exists
deftype Class = int;
#endif
+
+#ifdef ERROR3
+// ERROR3: [[@LINE+1]]:22: error: cannot define type alias for class type 'Class'
+deftype ClassAlias = Class;
+#endif
>From 5031d0495e408f141e9c7457463b5af505974d61 Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Tue, 30 Jan 2024 14:41:39 +0800
Subject: [PATCH 5/7] Add const to TypeName
Created using spr 1.3.4
---
llvm/lib/TableGen/TGParser.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 0f054c8fdd539..01e69ca589e3f 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1104,7 +1104,7 @@ RecTy *TGParser::ParseType() {
Lex.Lex();
return DagRecTy::get(Records);
case tgtok::Id: {
- std::string TypeName = Lex.getCurStrVal();
+ const std::string TypeName = Lex.getCurStrVal();
if (TypeAliases.count(TypeName)) {
Lex.Lex();
return TypeAliases[TypeName];
@@ -3682,7 +3682,7 @@ bool TGParser::ParseDeftype() {
if (Lex.getCode() != tgtok::Id)
return TokError("expected identifier");
- std::string TypeName = Lex.getCurStrVal();
+ const std::string TypeName = Lex.getCurStrVal();
if (TypeAliases.count(TypeName) || Records.getClass(TypeName))
return TokError("type of this name '" + TypeName + "' already exists");
>From e36c58e8f01b600afcb3a006636d70e080e74227 Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Tue, 30 Jan 2024 16:02:22 +0800
Subject: [PATCH 6/7] Use find
Created using spr 1.3.4
---
llvm/lib/TableGen/TGParser.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 01e69ca589e3f..2fe98d22870c8 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1104,10 +1104,10 @@ RecTy *TGParser::ParseType() {
Lex.Lex();
return DagRecTy::get(Records);
case tgtok::Id: {
- const std::string TypeName = Lex.getCurStrVal();
- if (TypeAliases.count(TypeName)) {
+ auto I = TypeAliases.find(Lex.getCurStrVal());
+ if (I != TypeAliases.end()) {
Lex.Lex();
- return TypeAliases[TypeName];
+ return I->second;
}
if (Record *R = ParseClassID())
return RecordRecTy::get(R);
>From b1fdd69296b39f041335eee0e7298df6adbe7f7d Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Thu, 1 Feb 2024 14:12:34 +0800
Subject: [PATCH 7/7] check class conflict with alias; add release note
Created using spr 1.3.4
---
llvm/docs/ReleaseNotes.rst | 2 ++
llvm/lib/TableGen/TGParser.cpp | 7 ++++++-
llvm/test/TableGen/deftype.td | 12 ++++++++++++
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 300c9687e8c00..0e3924f4de3cb 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -59,6 +59,8 @@ Changes to building LLVM
Changes to TableGen
-------------------
+- We can define type aliases via new keyword ``deftype``.
+
Changes to Interprocedural Optimizations
----------------------------------------
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 2fe98d22870c8..f899fdb68f758 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -3956,7 +3956,8 @@ bool TGParser::ParseClass() {
if (Lex.getCode() != tgtok::Id)
return TokError("expected class name after 'class' keyword");
- Record *CurRec = Records.getClass(Lex.getCurStrVal());
+ const std::string &Name = Lex.getCurStrVal();
+ Record *CurRec = Records.getClass(Name);
if (CurRec) {
// If the body was previously defined, this is an error.
if (!CurRec->getValues().empty() ||
@@ -3973,6 +3974,10 @@ bool TGParser::ParseClass() {
CurRec = NewRec.get();
Records.addClass(std::move(NewRec));
}
+
+ if (TypeAliases.count(Name))
+ return TokError("there is already a defined type alias '" + Name + "'");
+
Lex.Lex(); // eat the name.
// A class definition introduces a new scope.
diff --git a/llvm/test/TableGen/deftype.td b/llvm/test/TableGen/deftype.td
index 666c3a2a57d96..7323fc77c35dc 100644
--- a/llvm/test/TableGen/deftype.td
+++ b/llvm/test/TableGen/deftype.td
@@ -2,6 +2,8 @@
// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s
// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s
+// RUN: not llvm-tblgen -DERROR4 %s 2>&1 | FileCheck --check-prefix=ERROR4 %s
+// RUN: not llvm-tblgen -DERROR5 %s 2>&1 | FileCheck --check-prefix=ERROR5 %s
class Class<int v> {
int value = v;
@@ -56,3 +58,13 @@ deftype Class = int;
// ERROR3: [[@LINE+1]]:22: error: cannot define type alias for class type 'Class'
deftype ClassAlias = Class;
#endif
+
+#ifdef ERROR4
+// ERROR4: [[@LINE+1]]:7: error: there is already a defined type alias 'Byte'
+class Byte; // incomplete class definition.
+#endif
+
+#ifdef ERROR5
+// ERROR5: [[@LINE+1]]:7: error: there is already a defined type alias 'Byte'
+class Byte {}
+#endif
More information about the llvm-commits
mailing list