From cd1f0648bfc23915304946e8ace4cfdb6ff6d580 Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Mon, 19 Mar 2018 14:14:28 +0000 Subject: [PATCH] TableGen: Explicitly forbid self-references to field members Summary: Otherwise, patterns like in the test case produce cryptic error messages about fields being resolved incompletely. Change-Id: I713c0191f00fe140ad698675803ab1f8823dc5bd Reviewers: arsenm, craig.topper, tra, MartinO Subscribers: wdng, llvm-commits Differential Revision: https://reviews.llvm.org/D44476 llvm-svn: 327850 --- include/llvm/TableGen/Record.h | 2 +- lib/TableGen/Record.cpp | 12 +++++++++--- lib/TableGen/TGParser.cpp | 2 +- test/TableGen/self-reference-recursion.td | 9 +++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test/TableGen/self-reference-recursion.td diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 9aaf121e64b..8ba1992083f 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1200,7 +1200,7 @@ public: Init *getBit(unsigned Bit) const override; Init *resolveReferences(Resolver &R) const override; - Init *Fold() const; + Init *Fold(Record *CurRec) const; std::string getAsString() const override { return Rec->getAsString() + "." + FieldName->getValue().str(); diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 333f45b7be9..866cda3152f 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -1684,13 +1684,19 @@ Init *FieldInit::getBit(unsigned Bit) const { Init *FieldInit::resolveReferences(Resolver &R) const { Init *NewRec = Rec->resolveReferences(R); if (NewRec != Rec) - return FieldInit::get(NewRec, FieldName)->Fold(); + return FieldInit::get(NewRec, FieldName)->Fold(R.getCurrentRecord()); return const_cast(this); } -Init *FieldInit::Fold() const { +Init *FieldInit::Fold(Record *CurRec) const { if (DefInit *DI = dyn_cast(Rec)) { - Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue(); + Record *Def = DI->getDef(); + if (Def == CurRec) + PrintFatalError(CurRec->getLoc(), + Twine("Attempting to access field '") + + FieldName->getAsUnquotedString() + "' of '" + + Rec->getAsString() + "' is a forbidden self-reference"); + Init *FieldVal = Def->getValue(FieldName)->getValue(); if (FieldVal->isComplete()) return FieldVal; } diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 0c92cf74965..0eb75424db5 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -1943,7 +1943,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { Result->getAsString() + "'"); return nullptr; } - Result = FieldInit::get(Result, FieldName)->Fold(); + Result = FieldInit::get(Result, FieldName)->Fold(CurRec); Lex.Lex(); // eat field name break; } diff --git a/test/TableGen/self-reference-recursion.td b/test/TableGen/self-reference-recursion.td new file mode 100644 index 00000000000..7eadfb7cf78 --- /dev/null +++ b/test/TableGen/self-reference-recursion.td @@ -0,0 +1,9 @@ +// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s +// XFAIL: vg_leak + +class A { + int x = !cast(self).x; +} + +// CHECK: error: Attempting to access field 'x' of 'A0' is a forbidden self-reference +def A0 : A<"A0">;