aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-03-09 04:49:14 +0000
committerChris Lattner <sabre@nondot.org>2009-03-09 04:49:14 +0000
commitc3a8e1966c4eb27dc28ee5b550e50a3bf5da57ae (patch)
treed4dae89d38da9d4f6e47fc1583a44fbd4d9bec3e /lib
parenta2d24e5b1055d27f421f0c9997c99622614cb9ed (diff)
downloadexternal_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.cpp48
-rw-r--r--lib/AsmParser/LLParser.h6
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);