diff options
author | Chris Lattner <sabre@nondot.org> | 2009-03-09 04:49:14 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-03-09 04:49:14 +0000 |
commit | c3a8e1966c4eb27dc28ee5b550e50a3bf5da57ae (patch) | |
tree | d4dae89d38da9d4f6e47fc1583a44fbd4d9bec3e /lib | |
parent | a2d24e5b1055d27f421f0c9997c99622614cb9ed (diff) | |
download | external_llvm-c3a8e1966c4eb27dc28ee5b550e50a3bf5da57ae.zip external_llvm-c3a8e1966c4eb27dc28ee5b550e50a3bf5da57ae.tar.gz external_llvm-c3a8e1966c4eb27dc28ee5b550e50a3bf5da57ae.tar.bz2 |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 48 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.h | 6 |
2 files changed, 36 insertions, 18 deletions
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 90dd507..cb9eb6a 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -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)) diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index f013c63..3fc2fd2 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -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); |