OSDN Git Service

TableGen: Generate valid identifiers for anonymous records
authorAlp Toker <alp@nuanti.com>
Sat, 21 Dec 2013 18:51:00 +0000 (18:51 +0000)
committerAlp Toker <alp@nuanti.com>
Sat, 21 Dec 2013 18:51:00 +0000 (18:51 +0000)
Backends like OptParserEmitter assume that record names can be used as valid
identifiers.

The period '.' in generated anonymous names broke that assumption, causing a
build-time error and in practice forcing all records to be named.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197869 91177308-0d34-0410-b5e6-96231b3b80d8

lib/TableGen/TGParser.cpp
lib/TableGen/TGParser.h
test/TableGen/ValidIdentifiers.td [new file with mode: 0644]

index daac574..38ab711 100644 (file)
@@ -380,10 +380,11 @@ static bool isObjectStart(tgtok::TokKind K) {
          K == tgtok::MultiClass || K == tgtok::Foreach;
 }
 
-static std::string GetNewAnonymousName() {
-  static unsigned AnonCounter = 0;
+/// GetNewAnonymousName - Generate a unique anonymous name that can be used as
+/// an identifier.
+std::string TGParser::GetNewAnonymousName() {
   unsigned Tmp = AnonCounter++; // MSVC2012 ICEs without this.
-  return "anonymous." + utostr(Tmp);
+  return "anonymous_" + utostr(Tmp);
 }
 
 /// ParseObjectName - If an object name is specified, return it.  Otherwise,
@@ -1215,10 +1216,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
     SMLoc EndLoc = Lex.getLoc();
 
     // Create the new record, set it as CurRec temporarily.
-    static unsigned AnonCounter = 0;
-    Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),
-                                NameLoc,
-                                Records,
+    Record *NewRec = new Record(GetNewAnonymousName(), NameLoc, Records,
                                 /*IsAnonymous=*/true);
     SubClassReference SCRef;
     SCRef.RefRange = SMRange(NameLoc, EndLoc);
index 044e3a0..a575345 100644 (file)
@@ -69,6 +69,8 @@ class TGParser {
   // Record tracker
   RecordKeeper &Records;
 
+  unsigned AnonCounter;
+
   // A "named boolean" indicating how to parse identifiers.  Usually
   // identifiers map to some existing object but in special cases
   // (e.g. parsing def names) no such object exists yet because we are
@@ -82,8 +84,8 @@ class TGParser {
   };
 
 public:
-  TGParser(SourceMgr &SrcMgr, RecordKeeper &records) :
-    Lex(SrcMgr), CurMultiClass(0), Records(records) {}
+  TGParser(SourceMgr &SrcMgr, RecordKeeper &records)
+      : Lex(SrcMgr), CurMultiClass(0), Records(records), AnonCounter(0) {}
 
   /// ParseFile - Main entrypoint for parsing a tblgen file.  These parser
   /// routines return true on error, or false on success.
@@ -112,6 +114,8 @@ private:  // Semantic analysis methods.
   bool AddSubMultiClass(MultiClass *CurMC,
                         SubMultiClassReference &SubMultiClass);
 
+  std::string GetNewAnonymousName();
+
   // IterRecord: Map an iterator name to a value.
   struct IterRecord {
     VarInit *IterVar;
diff --git a/test/TableGen/ValidIdentifiers.td b/test/TableGen/ValidIdentifiers.td
new file mode 100644 (file)
index 0000000..899ae0e
--- /dev/null
@@ -0,0 +1,13 @@
+// Ensure that anonymous names are valid identifiers via the ctags index
+// RUN: llvm-tblgen -gen-ctags %s | grep -v '^!' | not grep -viE '^[a-z_][a-z0-9_]*\t'
+// Test validation
+// RUN: llvm-tblgen -gen-ctags %s | grep '^anonymous' > /dev/null
+// XFAIL: vg_leak
+
+class foo<int X> { int THEVAL = X; }
+
+def : foo<2>;
+
+def X {
+  foo Y = foo<1>;
+}