diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h index b615385d3a054..2853a471b67fc 100644 --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -1996,12 +1996,6 @@ class MapResolver final : public Resolver { void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; } - bool isComplete(Init *VarName) const { - auto It = Map.find(VarName); - assert(It != Map.end() && "key must be present in map"); - return It->second.V->isComplete(); - } - Init *resolve(Init *VarName) override; }; diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 966599e29e829..74786e040018f 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -2316,7 +2316,7 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { Type = (Twine("of type '") + VRT->getType()->getAsString() + "' ").str(); PrintFatalError(getLoc(), Twine("Invalid value ") + Type + - "found when setting field '" + + "is found when setting '" + Value.getNameInitAsString() + "' of type '" + Value.getType()->getAsString() + diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 63b304164d428..24949f0b2b4d5 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -229,33 +229,38 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, /// args as SubClass's template arguments. bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { Record *SC = SubClass.Rec; + // Add all of the values in the subclass into the current class. + for (const RecordVal &Val : SC->getValues()) + if (AddValue(CurRec, SubClass.RefRange.Start, Val)) + return true; + + ArrayRef TArgs = SC->getTemplateArgs(); + + // Ensure that an appropriate number of template arguments are specified. + if (TArgs.size() < SubClass.TemplateArgs.size()) + return Error(SubClass.RefRange.Start, + "More template args specified than expected"); + + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. MapResolver R(CurRec); - // Loop over all the subclass record's fields. Add template arguments - // to the resolver map. Add regular fields to the new record. - for (const RecordVal &Field : SC->getValues()) { - if (Field.isTemplateArg()) { - R.set(Field.getNameInit(), Field.getValue()); - } else { - if (AddValue(CurRec, SubClass.RefRange.Start, Field)) + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + if (i < SubClass.TemplateArgs.size()) { + // If a value is specified for this template arg, set it now. + if (SetValue(CurRec, SubClass.RefRange.Start, TArgs[i], + None, SubClass.TemplateArgs[i])) return true; - } - } - - ArrayRef TArgs = SC->getTemplateArgs(); - assert(SubClass.TemplateArgs.size() <= TArgs.size() && - "Too many template arguments allowed"); - - // Loop over the template argument names. If a value was specified, - // reset the map value. If not and there was no default, complain. - for (unsigned I = 0, E = TArgs.size(); I != E; ++I) { - if (I < SubClass.TemplateArgs.size()) - R.set(TArgs[I], SubClass.TemplateArgs[I]); - else if (!R.isComplete(TArgs[I])) + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { return Error(SubClass.RefRange.Start, "Value not specified for template argument #" + - Twine(I) + " (" + TArgs[I]->getAsUnquotedString() + - ") of parent class '" + SC->getNameInitAsString() + "'"); + Twine(i) + " (" + TArgs[i]->getAsUnquotedString() + + ") of subclass '" + SC->getNameInitAsString() + "'!"); + } + + R.set(TArgs[i], CurRec->getValue(TArgs[i])->getValue()); + + CurRec->removeValue(TArgs[i]); } Init *Name; @@ -2574,8 +2579,8 @@ void TGParser::ParseValueList(SmallVectorImpl &Result, Record *CurRec, } /// ParseDeclaration - Read a declaration, returning the name of field ID, or an -/// empty string on error. This can happen in a number of different contexts, -/// including within a def or in the template args for a class (in which case +/// empty string on error. This can happen in a number of different context's, +/// including within a def or in the template args for a def (which which case /// CurRec will be non-null) and within the template args for a multiclass (in /// which case CurRec will be null, but CurMultiClass will be set). This can /// also happen within a def that is within a multiclass, which will set both @@ -2606,30 +2611,23 @@ Init *TGParser::ParseDeclaration(Record *CurRec, Init *DeclName = StringInit::get(Str); Lex.Lex(); - bool BadField; - if (!ParsingTemplateArgs) { // def, possibly in a multiclass - BadField = AddValue(CurRec, IdLoc, - RecordVal(DeclName, IdLoc, Type, - HasField ? RecordVal::FK_NonconcreteOK - : RecordVal::FK_Normal)); - - } else if (CurRec) { // class template argument - DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":"); - BadField = AddValue(CurRec, IdLoc, - RecordVal(DeclName, IdLoc, Type, - RecordVal::FK_TemplateArg)); - - } else { // multiclass template argument - assert(CurMultiClass && "invalid context for template argument"); - DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::"); - BadField = AddValue(CurRec, IdLoc, - RecordVal(DeclName, IdLoc, Type, - RecordVal::FK_TemplateArg)); - } - if (BadField) + if (ParsingTemplateArgs) { + if (CurRec) + DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":"); + else + assert(CurMultiClass); + if (CurMultiClass) + DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, + "::"); + } + + // Add the field to the record. + if (AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type, + HasField ? RecordVal::FK_NonconcreteOK + : RecordVal::FK_Normal))) return nullptr; - // If a value is present, parse it and set new field's value. + // If a value is present, parse it. if (consume(tgtok::equal)) { SMLoc ValLoc = Lex.getLoc(); Init *Val = ParseValue(CurRec, Type); @@ -2730,7 +2728,7 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) { /// ParseTemplateArgList - Read a template argument list, which is a non-empty /// sequence of template-declarations in <>'s. If CurRec is non-null, these are -/// template args for a class, which may or may not be in a multiclass. If null, +/// template args for a def, which may or may not be in a multiclass. If null, /// these are the template args for a multiclass. /// /// TemplateArgList ::= '<' Declaration (',' Declaration)* '>' diff --git a/llvm/test/TableGen/self-reference-typeerror.td b/llvm/test/TableGen/self-reference-typeerror.td index 08070da68f6c7..35c6131fa2c98 100644 --- a/llvm/test/TableGen/self-reference-typeerror.td +++ b/llvm/test/TableGen/self-reference-typeerror.td @@ -9,5 +9,5 @@ class A { // This kind of self-reference is discourage, but if you *really* want it, you // can force it with !cast. // -// CHECK: nvalid value of type '{}' found when setting field 'a' of type 'A' +// CHECK: Field 'A:x' of type 'A' is incompatible with value def A0 : A;