Skip to content

Commit c056f82

Browse files
author
Paul C. Anagnostopoulos
committed
[TableGen] Improve algorithm for inheriting class template args and fields
Differential Revision: https://reviews.llvm.org/D94822
1 parent 21bfd06 commit c056f82

File tree

4 files changed

+55
-47
lines changed

4 files changed

+55
-47
lines changed

llvm/include/llvm/TableGen/Record.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,6 +1996,12 @@ class MapResolver final : public Resolver {
19961996

19971997
void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; }
19981998

1999+
bool isComplete(Init *VarName) const {
2000+
auto It = Map.find(VarName);
2001+
assert(It != Map.end() && "key must be present in map");
2002+
return It->second.V->isComplete();
2003+
}
2004+
19992005
Init *resolve(Init *VarName) override;
20002006
};
20012007

llvm/lib/TableGen/Record.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2316,7 +2316,7 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
23162316
Type =
23172317
(Twine("of type '") + VRT->getType()->getAsString() + "' ").str();
23182318
PrintFatalError(getLoc(), Twine("Invalid value ") + Type +
2319-
"is found when setting '" +
2319+
"found when setting field '" +
23202320
Value.getNameInitAsString() +
23212321
"' of type '" +
23222322
Value.getType()->getAsString() +

llvm/lib/TableGen/TGParser.cpp

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -229,38 +229,33 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
229229
/// args as SubClass's template arguments.
230230
bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
231231
Record *SC = SubClass.Rec;
232-
// Add all of the values in the subclass into the current class.
233-
for (const RecordVal &Val : SC->getValues())
234-
if (AddValue(CurRec, SubClass.RefRange.Start, Val))
235-
return true;
236-
237-
ArrayRef<Init *> TArgs = SC->getTemplateArgs();
238-
239-
// Ensure that an appropriate number of template arguments are specified.
240-
if (TArgs.size() < SubClass.TemplateArgs.size())
241-
return Error(SubClass.RefRange.Start,
242-
"More template args specified than expected");
243-
244-
// Loop over all of the template arguments, setting them to the specified
245-
// value or leaving them as the default if necessary.
246232
MapResolver R(CurRec);
247233

248-
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
249-
if (i < SubClass.TemplateArgs.size()) {
250-
// If a value is specified for this template arg, set it now.
251-
if (SetValue(CurRec, SubClass.RefRange.Start, TArgs[i],
252-
None, SubClass.TemplateArgs[i]))
234+
// Loop over all the subclass record's fields. Add template arguments
235+
// to the resolver map. Add regular fields to the new record.
236+
for (const RecordVal &Field : SC->getValues()) {
237+
if (Field.isTemplateArg()) {
238+
R.set(Field.getNameInit(), Field.getValue());
239+
} else {
240+
if (AddValue(CurRec, SubClass.RefRange.Start, Field))
253241
return true;
254-
} else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
255-
return Error(SubClass.RefRange.Start,
256-
"Value not specified for template argument #" +
257-
Twine(i) + " (" + TArgs[i]->getAsUnquotedString() +
258-
") of subclass '" + SC->getNameInitAsString() + "'!");
259242
}
243+
}
260244

261-
R.set(TArgs[i], CurRec->getValue(TArgs[i])->getValue());
262-
263-
CurRec->removeValue(TArgs[i]);
245+
ArrayRef<Init *> TArgs = SC->getTemplateArgs();
246+
assert(SubClass.TemplateArgs.size() <= TArgs.size() &&
247+
"Too many template arguments allowed");
248+
249+
// Loop over the template argument names. If a value was specified,
250+
// reset the map value. If not and there was no default, complain.
251+
for (unsigned I = 0, E = TArgs.size(); I != E; ++I) {
252+
if (I < SubClass.TemplateArgs.size())
253+
R.set(TArgs[I], SubClass.TemplateArgs[I]);
254+
else if (!R.isComplete(TArgs[I]))
255+
return Error(SubClass.RefRange.Start,
256+
"Value not specified for template argument #" +
257+
Twine(I) + " (" + TArgs[I]->getAsUnquotedString() +
258+
") of parent class '" + SC->getNameInitAsString() + "'");
264259
}
265260

266261
Init *Name;
@@ -2579,8 +2574,8 @@ void TGParser::ParseValueList(SmallVectorImpl<Init*> &Result, Record *CurRec,
25792574
}
25802575

25812576
/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
2582-
/// empty string on error. This can happen in a number of different context's,
2583-
/// including within a def or in the template args for a def (which which case
2577+
/// empty string on error. This can happen in a number of different contexts,
2578+
/// including within a def or in the template args for a class (in which case
25842579
/// CurRec will be non-null) and within the template args for a multiclass (in
25852580
/// which case CurRec will be null, but CurMultiClass will be set). This can
25862581
/// also happen within a def that is within a multiclass, which will set both
@@ -2611,23 +2606,30 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
26112606
Init *DeclName = StringInit::get(Str);
26122607
Lex.Lex();
26132608

2614-
if (ParsingTemplateArgs) {
2615-
if (CurRec)
2616-
DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
2617-
else
2618-
assert(CurMultiClass);
2619-
if (CurMultiClass)
2620-
DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName,
2621-
"::");
2622-
}
2623-
2624-
// Add the field to the record.
2625-
if (AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
2626-
HasField ? RecordVal::FK_NonconcreteOK
2627-
: RecordVal::FK_Normal)))
2609+
bool BadField;
2610+
if (!ParsingTemplateArgs) { // def, possibly in a multiclass
2611+
BadField = AddValue(CurRec, IdLoc,
2612+
RecordVal(DeclName, IdLoc, Type,
2613+
HasField ? RecordVal::FK_NonconcreteOK
2614+
: RecordVal::FK_Normal));
2615+
2616+
} else if (CurRec) { // class template argument
2617+
DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
2618+
BadField = AddValue(CurRec, IdLoc,
2619+
RecordVal(DeclName, IdLoc, Type,
2620+
RecordVal::FK_TemplateArg));
2621+
2622+
} else { // multiclass template argument
2623+
assert(CurMultiClass && "invalid context for template argument");
2624+
DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::");
2625+
BadField = AddValue(CurRec, IdLoc,
2626+
RecordVal(DeclName, IdLoc, Type,
2627+
RecordVal::FK_TemplateArg));
2628+
}
2629+
if (BadField)
26282630
return nullptr;
26292631

2630-
// If a value is present, parse it.
2632+
// If a value is present, parse it and set new field's value.
26312633
if (consume(tgtok::equal)) {
26322634
SMLoc ValLoc = Lex.getLoc();
26332635
Init *Val = ParseValue(CurRec, Type);
@@ -2728,7 +2730,7 @@ VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
27282730

27292731
/// ParseTemplateArgList - Read a template argument list, which is a non-empty
27302732
/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
2731-
/// template args for a def, which may or may not be in a multiclass. If null,
2733+
/// template args for a class, which may or may not be in a multiclass. If null,
27322734
/// these are the template args for a multiclass.
27332735
///
27342736
/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'

llvm/test/TableGen/self-reference-typeerror.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ class A<A x> {
99
// This kind of self-reference is discourage, but if you *really* want it, you
1010
// can force it with !cast.
1111
//
12-
// CHECK: Field 'A:x' of type 'A' is incompatible with value
12+
// CHECK: nvalid value of type '{}' found when setting field 'a' of type 'A'
1313
def A0 : A<A0>;

0 commit comments

Comments
 (0)