Fix two classes of bugs. First:

validate an invariant so that the asmparser rejects a bad construct
instead of the verifier.  Before:

llvm-as: assembly parsed, but does not verify as correct!
Invalid struct return type!
i64 (%struct.Type*, %struct.Type*)* @foo

after:

llvm-as: t.ll:5:8: functions with 'sret' argument must return void
define i64 @foo(%struct.Type* noalias nocapture sret %agg.result, %struct.Type* nocapture byval %t) nounwind {
       ^


Second, check that void is only used where allowed (in function return types) not in
arbitrary places, fixing PR3747 - Crash in llvm-as with void field in struct.  We
now reject that example with:

$ llvm-as t.ll
llvm-as: t.ll:1:12: struct element can not have void type
%x = type {void}
           ^





git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66394 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-03-09 04:49:14 +00:00
parent c66996ab34
commit a9a9e07d1c
2 changed files with 36 additions and 18 deletions

View File

@ -235,10 +235,6 @@ bool LLParser::ParseUnnamedType() {
unsigned TypeID = NumberedTypes.size();
// We don't allow assigning names to void type
if (Ty == Type::VoidTy)
return Error(TypeLoc, "can't assign name to the void type");
// See if this type was previously referenced.
std::map<unsigned, std::pair<PATypeHolder, LocTy> >::iterator
FI = ForwardRefTypeIDs.find(TypeID);
@ -270,10 +266,6 @@ bool LLParser::ParseNamedType() {
ParseType(Ty))
return true;
// We don't allow assigning names to void type
if (Ty == Type::VoidTy)
return Error(NameLoc, "can't assign name '" + Name + "' to the void type");
// Set the type name, checking for conflicts as we do so.
bool AlreadyExists = M->addTypeName(Name, Ty);
if (!AlreadyExists) return false;
@ -473,7 +465,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
return true;
}
if (isa<FunctionType>(Ty) || Ty == Type::LabelTy || Ty == Type::VoidTy)
if (isa<FunctionType>(Ty) || Ty == Type::LabelTy)
return Error(TyLoc, "invalid type for global variable");
GlobalVariable *GV = 0;
@ -873,13 +865,17 @@ bool LLParser::ParseIndexList(SmallVectorImpl<unsigned> &Indices) {
//===----------------------------------------------------------------------===//
/// ParseType - Parse and resolve a full type.
bool LLParser::ParseType(PATypeHolder &Result) {
bool LLParser::ParseType(PATypeHolder &Result, bool AllowVoid) {
LocTy TypeLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
// Verify no unresolved uprefs.
if (!UpRefs.empty())
return Error(UpRefs.back().Loc, "invalid unresolved type up reference");
if (!AllowVoid && Result.get() == Type::VoidTy)
return Error(TypeLoc, "void type only allowed for function results");
return false;
}
@ -1140,6 +1136,9 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy == Type::VoidTy)
return Error(TypeLoc, "argument can not have void type");
if (Lex.getKind() == lltok::LocalVar ||
Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0
Name = Lex.getStrVal();
@ -1160,9 +1159,12 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
// Otherwise must be an argument type.
TypeLoc = Lex.getLoc();
if (ParseTypeRec(ArgTy) ||
if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy == Type::VoidTy)
return Error(TypeLoc, "argument can not have void type");
if (Lex.getKind() == lltok::LocalVar ||
Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0
Name = Lex.getStrVal();
@ -1233,11 +1235,20 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) {
}
std::vector<PATypeHolder> ParamsList;
LocTy EltTyLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
ParamsList.push_back(Result);
if (Result == Type::VoidTy)
return Error(EltTyLoc, "struct element can not have void type");
while (EatIfPresent(lltok::comma)) {
EltTyLoc = Lex.getLoc();
if (ParseTypeRec(Result)) return true;
if (Result == Type::VoidTy)
return Error(EltTyLoc, "struct element can not have void type");
ParamsList.push_back(Result);
}
@ -1272,6 +1283,9 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
PATypeHolder EltTy(Type::VoidTy);
if (ParseTypeRec(EltTy)) return true;
if (EltTy == Type::VoidTy)
return Error(TypeLoc, "array and vector element type cannot be void");
if (ParseToken(isVector ? lltok::greater : lltok::rsquare,
"expected end of sequential type"))
return true;
@ -2081,7 +2095,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
ParseOptionalVisibility(Visibility) ||
ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
ParseType(RetType, RetTypeLoc))
ParseType(RetType, RetTypeLoc, true /*void allowed*/))
return true;
// Verify that the linkage is ok.
@ -2183,6 +2197,10 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
if (PAL.paramHasAttr(1, Attribute::StructRet) &&
RetType != Type::VoidTy)
return Error(RetTypeLoc, "functions with 'sret' argument must return void");
const FunctionType *FT = FunctionType::get(RetType, ParamTypeList, isVarArg);
const PointerType *PFT = PointerType::getUnqual(FT);
@ -2472,7 +2490,7 @@ bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) {
bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
PerFunctionState &PFS) {
PATypeHolder Ty(Type::VoidTy);
if (ParseType(Ty)) return true;
if (ParseType(Ty, true /*void allowed*/)) return true;
if (Ty == Type::VoidTy) {
Inst = ReturnInst::Create();
@ -2602,7 +2620,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
Value *NormalBB, *UnwindBB;
if (ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
ParseType(RetType, RetTypeLoc) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
ParseValID(CalleeID) ||
ParseParameterList(ArgList, PFS) ||
ParseOptionalAttrs(FnAttrs, 2) ||
@ -2960,7 +2978,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
if ((isTail && ParseToken(lltok::kw_call, "expected 'tail call'")) ||
ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
ParseType(RetType, RetTypeLoc) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
ParseValID(CalleeID) ||
ParseParameterList(ArgList, PFS) ||
ParseOptionalAttrs(FnAttrs, 2))

View File

@ -139,10 +139,10 @@ namespace llvm {
bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility);
// Type Parsing.
bool ParseType(PATypeHolder &Result);
bool ParseType(PATypeHolder &Result, LocTy &Loc) {
bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
bool ParseType(PATypeHolder &Result, LocTy &Loc, bool AllowVoid = false) {
Loc = Lex.getLoc();
return ParseType(Result);
return ParseType(Result, AllowVoid);
}
bool ParseTypeRec(PATypeHolder &H);
bool ParseStructType(PATypeHolder &H, bool Packed);