Index: llvm/include/llvm/TableGen/Error.h =================================================================== --- llvm/include/llvm/TableGen/Error.h +++ llvm/include/llvm/TableGen/Error.h @@ -15,6 +15,7 @@ #define LLVM_TABLEGEN_ERROR_H #include "llvm/Support/SourceMgr.h" +#include "llvm/TableGen/Record.h" namespace llvm { @@ -34,6 +35,10 @@ LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef ErrorLoc, const Twine &Msg); +LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Record *Rec, + const Twine &Msg); +LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const RecordVal *RecVal, + const Twine &Msg); extern SourceMgr SrcMgr; extern unsigned ErrorsPrinted; Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -1402,11 +1402,13 @@ friend class Record; Init *Name; + SMLoc Loc; // Source location of definition of name. PointerIntPair TyAndPrefix; Init *Value; public: RecordVal(Init *N, RecTy *T, bool P); + RecordVal(Init *N, SMLoc Loc, RecTy *T, bool P); StringRef getName() const; Init *getNameInit() const { return Name; } @@ -1415,11 +1417,13 @@ return getNameInit()->getAsUnquotedString(); } + const SMLoc &getLoc() const { return Loc; } bool getPrefix() const { return TyAndPrefix.getInt(); } RecTy *getType() const { return TyAndPrefix.getPointer(); } Init *getValue() const { return Value; } bool setValue(Init *V); + bool setValue(Init *V, SMLoc NewLoc); void dump() const; void print(raw_ostream &OS, bool PrintSem = true) const; Index: llvm/lib/TableGen/Error.cpp =================================================================== --- llvm/lib/TableGen/Error.cpp +++ llvm/lib/TableGen/Error.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/TableGen/Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Signals.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include namespace llvm { @@ -86,4 +87,22 @@ std::exit(1); } +// This method takes a Record and uses the source location +// stored in it. +void PrintFatalError(const Record *Rec, const Twine &Msg) { + PrintError(Rec->getLoc(), Msg); + // The following call runs the file cleanup handlers. + sys::RunInterruptHandlers(); + std::exit(1); +} + +// This method takes a RecordVal and uses the source location +// stored in it. +void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) { + PrintError(RecVal->getLoc(), Msg); + // The following call runs the file cleanup handlers. + sys::RunInterruptHandlers(); + std::exit(1); +} + } // end namespace llvm Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -2032,6 +2032,14 @@ assert(Value && "Cannot create unset value for current type!"); } +// This constructor accepts the same arguments as the above, but also +// a source location. +RecordVal::RecordVal(Init *N, SMLoc Loc, RecTy *T, bool P) + : Name(N), Loc(Loc), TyAndPrefix(T, P) { + setValue(UnsetInit::get()); + assert(Value && "Cannot create unset value for current type!"); +} + StringRef RecordVal::getName() const { return cast(getNameInit())->getValue(); } @@ -2046,8 +2054,8 @@ if (!isa(Value)) { SmallVector Bits; Bits.reserve(BTy->getNumBits()); - for (unsigned i = 0, e = BTy->getNumBits(); i < e; ++i) - Bits.push_back(Value->getBit(i)); + for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) + Bits.push_back(Value->getBit(I)); Value = BitsInit::get(Bits); } } @@ -2058,6 +2066,32 @@ return false; } +// This version of setValue takes an source location and resets the +// location in the RecordVal. +bool RecordVal::setValue(Init *V, SMLoc NewLoc) { + Loc = NewLoc; + if (V) { + Value = V->getCastTo(getType()); + if (Value) { + assert(!isa(Value) || + cast(Value)->getType()->typeIsA(getType())); + if (BitsRecTy *BTy = dyn_cast(getType())) { + if (!isa(Value)) { + SmallVector Bits; + Bits.reserve(BTy->getNumBits()); + for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) + Bits.push_back(Value->getBit(I)); + Value = BitsInit::get(Bits); + } + } + } + return Value == nullptr; + } + Value = nullptr; + return false; +} + +#include "llvm/TableGen/Record.h" #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; } #endif @@ -2215,8 +2249,8 @@ if (CodeInit *CI = dyn_cast(R->getValue())) return CI->getValue(); - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a string initializer!"); + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a string value"); } BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { @@ -2227,8 +2261,8 @@ if (BitsInit *BI = dyn_cast(R->getValue())) return BI; - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a BitsInit initializer!"); + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a bits value"); } ListInit *Record::getValueAsListInit(StringRef FieldName) const { @@ -2239,8 +2273,8 @@ if (ListInit *LI = dyn_cast(R->getValue())) return LI; - PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + - FieldName + "' does not have a list initializer!"); + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + FieldName + + "' exists but does not have a list value"); } std::vector @@ -2267,7 +2301,7 @@ return II->getValue(); PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have an int initializer: " + + "' exists but does not have an int value: " + R->getValue()->getAsString()); } @@ -2281,7 +2315,7 @@ else PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have a list of ints initializer: " + + "' exists but does not have a list of ints value: " + I->getAsString()); } return Ints; @@ -2299,7 +2333,7 @@ else PrintFatalError(getLoc(), Twine("Record `") + getName() + "', field `" + FieldName + - "' does not have a list of strings initializer: " + + "' exists but does not have a list of strings value: " + I->getAsString()); } return Strings; Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -209,16 +209,16 @@ V = BitsInit::get(NewBits); } - if (RV->setValue(V)) { + if (RV->setValue(V, Loc)) { std::string InitType; if (BitsInit *BI = dyn_cast(V)) InitType = (Twine("' of type bit initializer with length ") + Twine(BI->getNumBits())).str(); else if (TypedInit *TI = dyn_cast(V)) InitType = (Twine("' of type '") + TI->getType()->getAsString()).str(); - return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + return Error(Loc, "Field '" + ValName->getAsUnquotedString() + "' of type '" + RV->getType()->getAsString() + - "' is incompatible with initializer '" + + "' is incompatible with value '" + V->getAsString() + InitType + "'"); } return false; @@ -1294,7 +1294,8 @@ return nullptr; } - case tgtok::XForEach: { // Value ::= !foreach '(' Id ',' Value ',' Value ')' + case tgtok::XForEach: { + // Value ::= !foreach '(' Id ',' Value ',' Value ')' SMLoc OpLoc = Lex.getLoc(); Lex.Lex(); // eat the operation if (Lex.getCode() != tgtok::l_paren) { @@ -1367,8 +1368,8 @@ return nullptr; } - // We need to create a temporary record to provide a scope for the iteration - // variable while parsing top-level foreach's. + // We need to create a temporary record to provide a scope for the + // iteration variable. std::unique_ptr ParseRecTmp; Record *ParseRec = CurRec; if (!ParseRec) { @@ -1544,7 +1545,7 @@ return ParseOperationCond(CurRec, ItemType); case tgtok::XFoldl: { - // Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')' + // Value ::= !foldl '(' Value ',' Value ',' Id ',' Id ',' Expr ')' Lex.Lex(); // eat the operation if (!consume(tgtok::l_paren)) { TokError("expected '(' after !foldl"); @@ -1627,8 +1628,8 @@ } Lex.Lex(); // eat the ',' - // We need to create a temporary record to provide a scope for the iteration - // variable while parsing top-level foreach's. + // We need to create a temporary record to provide a scope for the + // two variables. std::unique_ptr ParseRecTmp; Record *ParseRec = CurRec; if (!ParseRec) { @@ -2419,7 +2420,7 @@ } // Add the value. - if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField))) + if (AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type, HasField))) return nullptr; // If a value is present, parse it. Index: llvm/test/TableGen/cond-type.td =================================================================== --- llvm/test/TableGen/cond-type.td +++ llvm/test/TableGen/cond-type.td @@ -5,7 +5,7 @@ class B : A {} class C : A {} -// CHECK: Value 'x' of type 'C' is incompatible with initializer '{{.*}}' of type 'A' +// CHECK: Field 'x' of type 'C' is incompatible with value '{{.*}}' of type 'A' class X { C x = !cond(cc: b, 1 : c); } Index: llvm/test/TableGen/generic-tables.td =================================================================== --- llvm/test/TableGen/generic-tables.td +++ llvm/test/TableGen/generic-tables.td @@ -146,7 +146,7 @@ } def DFoo : DEntry<"foo", 1>; -// ERROR1: [[@LINE+1]]:1: error: Record 'DBar' in table 'DTable' is missing field 'Val1' +// ERROR1: [[@LINE+1]]:1: error: Record 'DBar' for table 'DTable' is missing field 'Val1' def DBar : DEntry<"bar", ?>; def DTable : GenericTable { Index: llvm/test/TableGen/getsetop.td =================================================================== --- llvm/test/TableGen/getsetop.td +++ llvm/test/TableGen/getsetop.td @@ -38,7 +38,7 @@ // assignment whose LHS demands an instance of Base, so we expect a // static (parse-time) type-checking error. - // ERROR1: error: Value 'noCast' of type 'Base' is incompatible with initializer '!getop(orig)' of type '{}' + // ERROR1: error: Field 'noCast' of type 'Base' is incompatible with value '!getop(orig)' of type '{}' Base noCast = !getop(orig); #endif Index: llvm/test/TableGen/if-type.td =================================================================== --- llvm/test/TableGen/if-type.td +++ llvm/test/TableGen/if-type.td @@ -5,7 +5,7 @@ class B : A {} class C : A {} -// CHECK: Value 'x' of type 'C' is incompatible with initializer '{{.*}}' of type 'A' +// CHECK: Field 'x' of type 'C' is incompatible with value '{{.*}}' of type 'A' class X { C x = !if(cc, b, c); } Index: llvm/test/TableGen/self-reference-typeerror.td =================================================================== --- llvm/test/TableGen/self-reference-typeerror.td +++ llvm/test/TableGen/self-reference-typeerror.td @@ -9,5 +9,5 @@ // This kind of self-reference is discourage, but if you *really* want it, you // can force it with !cast. // -// CHECK: Value 'A:x' of type 'A' is incompatible with initializer +// CHECK: Field 'A:x' of type 'A' is incompatible with value def A0 : A; Index: llvm/utils/TableGen/SearchableTableEmitter.cpp =================================================================== --- llvm/utils/TableGen/SearchableTableEmitter.cpp +++ llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenIntrinsics.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Format.h" @@ -19,7 +21,6 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include "CodeGenIntrinsics.h" #include #include #include @@ -62,12 +63,14 @@ struct SearchIndex { std::string Name; + SMLoc Loc; // Source location of PrimaryKey or Key field definition. SmallVector Fields; bool EarlyOut = false; }; struct GenericTable { std::string Name; + ArrayRef Locs; // Source locations from the Record instance. std::string PreprocessorGuard; std::string CppTypeName; SmallVector Fields; @@ -106,7 +109,8 @@ TypeInArgument, }; - std::string primaryRepresentation(const GenericField &Field, Init *I) { + std::string primaryRepresentation(SMLoc Loc, const GenericField &Field, + Init *I) { if (StringInit *SI = dyn_cast(I)) return SI->getAsString(); else if (BitsInit *BI = dyn_cast(I)) @@ -122,11 +126,12 @@ else if (Field.Enum) { auto *Entry = Field.Enum->EntryMap[cast(I)->getDef()]; if (!Entry) - PrintFatalError(Twine("Entry for field '") + Field.Name + "' is null"); + PrintFatalError(Loc, + Twine("Entry for field '") + Field.Name + "' is null"); return std::string(Entry->first); } - PrintFatalError(Twine("invalid field type for field '") + Field.Name + - "', expected: string, bits, bit or code"); + PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name + + "'; expected: bit, bits, string, or code"); } bool isIntrinsic(Init *I) { @@ -149,7 +154,9 @@ return isa(I) || isa(I) || isIntrinsic(I); } - std::string searchableFieldType(const GenericField &Field, TypeContext Ctx) { + std::string searchableFieldType(const GenericTable &Table, + const SearchIndex &Index, + const GenericField &Field, TypeContext Ctx) { if (isa(Field.RecType)) { if (Ctx == TypeInStaticStruct) return "const char *"; @@ -166,12 +173,16 @@ return "uint32_t"; if (NumBits <= 64) return "uint64_t"; - PrintFatalError(Twine("bitfield '") + Field.Name + - "' too large to search"); + PrintFatalError(Index.Loc, Twine("In table '") + Table.Name + + "' lookup method '" + Index.Name + + "', key field '" + Field.Name + + "' of type bits is too large"); } else if (Field.Enum || Field.IsIntrinsic || Field.IsInstruction) return "unsigned"; - PrintFatalError(Twine("Field '") + Field.Name + "' has unknown type '" + - Field.RecType->getAsString() + "' to search by"); + PrintFatalError(Index.Loc, + Twine("In table '") + Table.Name + "' lookup method '" + + Index.Name + "', key field '" + Field.Name + + "' has invalid type: " + Field.RecType->getAsString()); } void emitGenericTable(const GenericTable &Table, raw_ostream &OS); @@ -184,7 +195,7 @@ bool parseFieldType(GenericField &Field, Init *II); std::unique_ptr - parseSearchIndex(GenericTable &Table, StringRef Name, + parseSearchIndex(GenericTable &Table, const RecordVal *RecVal, StringRef Name, const std::vector &Key, bool EarlyOut); void collectEnumEntries(GenericEnum &Enum, StringRef NameField, StringRef ValueField, @@ -259,8 +270,8 @@ if (LHSv > RHSv) return false; } else { - std::string LHSs = primaryRepresentation(Field, LHSI); - std::string RHSs = primaryRepresentation(Field, RHSI); + std::string LHSs = primaryRepresentation(Index.Loc, Field, LHSI); + std::string RHSs = primaryRepresentation(Index.Loc, Field, RHSI); if (isa(Field.RecType)) { LHSs = StringRef(LHSs).upper(); @@ -315,7 +326,8 @@ } else { OS << " struct IndexType {\n"; for (const auto &Field : Index.Fields) { - OS << " " << searchableFieldType(Field, TypeInStaticStruct) << " " + OS << " " + << searchableFieldType(Table, Index, Field, TypeInStaticStruct) << " " << Field.Name << ";\n"; } OS << " unsigned _index;\n"; @@ -345,8 +357,8 @@ OS << ", "; NeedComma = true; - std::string Repr = - primaryRepresentation(Field, Entry.first->getValueInit(Field.Name)); + std::string Repr = primaryRepresentation( + Index.Loc, Field, Entry.first->getValueInit(Field.Name)); if (isa(Field.RecType)) Repr = StringRef(Repr).upper(); OS << Repr; @@ -389,10 +401,10 @@ if (Index.EarlyOut) { const GenericField &Field = Index.Fields[0]; - std::string FirstRepr = - primaryRepresentation(Field, IndexRows[0]->getValueInit(Field.Name)); + std::string FirstRepr = primaryRepresentation( + Index.Loc, Field, IndexRows[0]->getValueInit(Field.Name)); std::string LastRepr = primaryRepresentation( - Field, IndexRows.back()->getValueInit(Field.Name)); + Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name)); OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n"; OS << " (" << Field.Name << " > " << LastRepr << "))\n"; OS << " return nullptr;\n\n"; @@ -400,8 +412,8 @@ OS << " struct KeyType {\n"; for (const auto &Field : Index.Fields) { - OS << " " << searchableFieldType(Field, TypeInTempStruct) << " " - << Field.Name << ";\n"; + OS << " " << searchableFieldType(Table, Index, Field, TypeInTempStruct) + << " " << Field.Name << ";\n"; } OS << " };\n"; OS << " KeyType Key = { "; @@ -415,9 +427,11 @@ if (isa(Field.RecType)) { OS << ".upper()"; if (IsPrimary) - PrintFatalError(Twine("Use a secondary index for case-insensitive " - "comparison of field '") + - Field.Name + "' in table '" + Table.Name + "'"); + PrintFatalError(Index.Loc, + Twine("In table '") + Table.Name + + "', use a secondary lookup method for " + "case-insensitive comparison of field '" + + Field.Name + "'"); } } OS << " };\n"; @@ -477,7 +491,8 @@ OS << ", "; NeedComma = true; - OS << searchableFieldType(Field, TypeInArgument) << " " << Field.Name; + OS << searchableFieldType(Table, Index, Field, TypeInArgument) << " " + << Field.Name; } OS << ")"; } @@ -512,7 +527,8 @@ OS << ", "; NeedComma = true; - OS << primaryRepresentation(Field, Entry->getValueInit(Field.Name)); + OS << primaryRepresentation(Table.Locs[0], Field, + Entry->getValueInit(Field.Name)); } OS << " }, // " << i << "\n"; @@ -542,27 +558,30 @@ return false; } -std::unique_ptr -SearchableTableEmitter::parseSearchIndex(GenericTable &Table, StringRef Name, - const std::vector &Key, - bool EarlyOut) { +std::unique_ptr SearchableTableEmitter::parseSearchIndex( + GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name, + const std::vector &Key, bool EarlyOut) { auto Index = std::make_unique(); Index->Name = std::string(Name); + Index->Loc = KeyRecVal->getLoc(); Index->EarlyOut = EarlyOut; for (const auto &FieldName : Key) { const GenericField *Field = Table.getFieldByName(FieldName); if (!Field) - PrintFatalError(Twine("Search index '") + Name + - "' refers to non-existing field '" + FieldName + - "' in table '" + Table.Name + "'"); + PrintFatalError( + KeyRecVal, + Twine("In table '") + Table.Name + + "', 'PrimaryKey' or 'Key' refers to nonexistent field '" + + FieldName + "'"); + Index->Fields.push_back(*Field); } if (EarlyOut && isa(Index->Fields[0].RecType)) { PrintFatalError( - "Early-out is not supported for string types (in search index '" + - Twine(Name) + "'"); + KeyRecVal, Twine("In lookup method '") + Name + "', early-out is not " + + "supported for a first key field of type string"); } return Index; @@ -601,31 +620,33 @@ void SearchableTableEmitter::collectTableEntries( GenericTable &Table, const std::vector &Items) { if (Items.empty()) - PrintWarning(Twine("Table '") + Table.Name + "' has no items"); + PrintFatalError(Table.Locs, + Twine("Table '") + Table.Name + "' has no entries"); for (auto EntryRec : Items) { for (auto &Field : Table.Fields) { auto TI = dyn_cast(EntryRec->getValueInit(Field.Name)); if (!TI || !TI->isComplete()) { - PrintFatalError(EntryRec->getLoc(), - Twine("Record '") + EntryRec->getName() + - "' in table '" + Table.Name + - "' is missing field '" + Field.Name + "'"); + PrintFatalError(EntryRec, Twine("Record '") + EntryRec->getName() + + "' for table '" + Table.Name + + "' is missing field '" + Field.Name + + "'"); } if (!Field.RecType) { Field.RecType = TI->getType(); } else { RecTy *Ty = resolveTypes(Field.RecType, TI->getType()); if (!Ty) - PrintFatalError(Twine("Field '") + Field.Name + "' of table '" + - Table.Name + "' has incompatible type: " + - Field.RecType->getAsString() + " vs. " + - TI->getType()->getAsString()); + PrintFatalError(EntryRec->getValue(Field.Name), + Twine("Field '") + Field.Name + "' of table '" + + Table.Name + "' entry has incompatible type: " + + TI->getType()->getAsString() + " vs. " + + Field.RecType->getAsString()); Field.RecType = Ty; } } - Table.Entries.push_back(EntryRec); + Table.Entries.push_back(EntryRec); // Add record to table's record list. } Record *IntrinsicClass = Records.getClass("Intrinsic"); @@ -666,8 +687,9 @@ StringRef FilterClass = EnumRec->getValueAsString("FilterClass"); Enum->Class = Records.getClass(FilterClass); if (!Enum->Class) - PrintFatalError(EnumRec->getLoc(), Twine("Enum FilterClass '") + - FilterClass + "' does not exist"); + PrintFatalError(EnumRec->getValue("FilterClass"), + Twine("Enum FilterClass '") + FilterClass + + "' does not exist"); collectEnumEntries(*Enum, NameField, ValueField, Records.getAllDerivedDefinitions(FilterClass)); @@ -678,29 +700,36 @@ for (auto TableRec : Records.getAllDerivedDefinitions("GenericTable")) { auto Table = std::make_unique(); Table->Name = std::string(TableRec->getName()); + Table->Locs = TableRec->getLoc(); Table->PreprocessorGuard = std::string(TableRec->getName()); Table->CppTypeName = std::string(TableRec->getValueAsString("CppTypeName")); std::vector Fields = TableRec->getValueAsListOfStrings("Fields"); for (const auto &FieldName : Fields) { - Table->Fields.emplace_back(FieldName); + Table->Fields.emplace_back(FieldName); // Construct a GenericField. if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) { if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) { - PrintFatalError(TableRec->getLoc(), + PrintFatalError(TypeOfVal, Twine("Table '") + Table->Name + - "' has bad 'TypeOf_" + FieldName + + "' has invalid 'TypeOf_" + FieldName + "': " + TypeOfVal->getValue()->getAsString()); } } } - collectTableEntries(*Table, Records.getAllDerivedDefinitions( - TableRec->getValueAsString("FilterClass"))); + StringRef FilterClass = TableRec->getValueAsString("FilterClass"); + if (!Records.getClass(FilterClass)) + PrintFatalError(TableRec->getValue("FilterClass"), + Twine("Table FilterClass '") + + FilterClass + "' does not exist"); + + collectTableEntries(*Table, Records.getAllDerivedDefinitions(FilterClass)); if (!TableRec->isValueUnset("PrimaryKey")) { Table->PrimaryKey = - parseSearchIndex(*Table, TableRec->getValueAsString("PrimaryKeyName"), + parseSearchIndex(*Table, TableRec->getValue("PrimaryKey"), + TableRec->getValueAsString("PrimaryKeyName"), TableRec->getValueAsListOfStrings("PrimaryKey"), TableRec->getValueAsBit("PrimaryKeyEarlyOut")); @@ -718,15 +747,16 @@ Record *TableRec = IndexRec->getValueAsDef("Table"); auto It = TableMap.find(TableRec); if (It == TableMap.end()) - PrintFatalError(IndexRec->getLoc(), + PrintFatalError(IndexRec->getValue("Table"), Twine("SearchIndex '") + IndexRec->getName() + - "' refers to non-existing table '" + + "' refers to nonexistent table '" + TableRec->getName()); GenericTable &Table = *It->second; - Table.Indices.push_back(parseSearchIndex( - Table, IndexRec->getName(), IndexRec->getValueAsListOfStrings("Key"), - IndexRec->getValueAsBit("EarlyOut"))); + Table.Indices.push_back( + parseSearchIndex(Table, IndexRec->getValue("Key"), IndexRec->getName(), + IndexRec->getValueAsListOfStrings("Key"), + IndexRec->getValueAsBit("EarlyOut"))); } // Translate legacy tables. @@ -757,6 +787,7 @@ auto Table = std::make_unique(); Table->Name = (Twine(Class->getName()) + "sList").str(); + Table->Locs = Class->getLoc(); Table->PreprocessorGuard = Class->getName().upper(); Table->CppTypeName = std::string(Class->getName()); @@ -779,7 +810,8 @@ Class->getValueAsListOfStrings("SearchableFields")) { std::string Name = (Twine("lookup") + Table->CppTypeName + "By" + Field).str(); - Table->Indices.push_back(parseSearchIndex(*Table, Name, {Field}, false)); + Table->Indices.push_back(parseSearchIndex(*Table, Class->getValue(Field), + Name, {Field}, false)); } Tables.emplace_back(std::move(Table));