a code imperfection in tablegen

Hello, all:

I found a bug in code of tablegen in file record.cpp, line 792, which still exists in latest version 3.4.

It looks like this:

740 Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {

switch (getOpcode()) {

case CAST: {

if (getType()->getAsString() == “string”) {

if (StringInit *LHSs = dyn_cast(LHS))

return LHSs;

if (DefInit *LHSd = dyn_cast(LHS))

return StringInit::get(LHSd->getDef()->getName());

if (IntInit *LHSi = dyn_cast(LHS))

return StringInit::get(LHSi->getAsString());

} else {

if (StringInit *LHSs = dyn_cast(LHS)) {

std::string Name = LHSs->getValue();

// From TGParser::ParseIDValue

757 if (CurRec) { ß we check CurRec here, but this check doesn’t cover line 792

if (const RecordVal *RV = CurRec->getValue(Name)) {

if (RV->getType() != getType())

PrintFatalError(“type mismatch in cast”);

return VarInit::get(Name, RV->getType());

}

Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name,

“:”);

if (CurRec->isTemplateArg(TemplateArgName)) {

const RecordVal *RV = CurRec->getValue(TemplateArgName);

assert(RV && “Template arg doesn’t exist??”);

if (RV->getType() != getType())

PrintFatalError(“type mismatch in cast”);

return VarInit::get(TemplateArgName, RV->getType());

}

}

if (CurMultiClass) {

Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, “::”);

if (CurMultiClass->Rec.isTemplateArg(MCName)) {

const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);

assert(RV && “Template arg doesn’t exist??”);

if (RV->getType() != getType())

PrintFatalError(“type mismatch in cast”);

return VarInit::get(MCName, RV->getType());

}

}

792 if (Record *D = (CurRec->getRecords()).getDef(Name)) ß if CurRec is NULL, it will be in trouble

return DefInit::get(D);

PrintFatalError(CurRec->getLoc(),

“Undefined reference:'” + Name + “'\n”);

}

}

break;

}

case HEAD: {

if (ListInit *LHSl = dyn_cast(LHS)) {

if (LHSl->getSize() == 0) {

assert(0 && “Empty list in car”);

return 0;

}

return LHSl->getElement(0);

}

break;

}

case TAIL: {

if (ListInit *LHSl = dyn_cast(LHS)) {

if (LHSl->getSize() == 0) {

assert(0 && “Empty list in cdr”);

return 0;

}

// Note the +1. We can’t just pass the result of getValues()

// directly.

ArrayRef<Init *>::iterator begin = LHSl->getValues().begin()+1;

ArrayRef<Init *>::iterator end = LHSl->getValues().end();

ListInit *Result =

ListInit::get(ArrayRef<Init *>(begin, end - begin),

LHSl->getType());

return Result;

}

break;

}

case EMPTY: {

if (ListInit *LHSl = dyn_cast(LHS)) {

if (LHSl->getSize() == 0) {

return IntInit::get(1);

} else {

return IntInit::get(0);

}

}

if (StringInit *LHSs = dyn_cast(LHS)) {

if (LHSs->getValue().empty()) {

return IntInit::get(1);

} else {

return IntInit::get(0);

}

}

break;

}

}

return const_cast<UnOpInit *>(this);

}