diff options
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 14 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.h | 4 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 3 | ||||
-rw-r--r-- | test/Assembler/declare-unnamed-addr.ll | 8 | ||||
-rw-r--r-- | test/Assembler/external-unnamed-addr.ll | 8 | ||||
-rw-r--r-- | unittests/VMCore/VerifierTest.cpp | 26 |
6 files changed, 60 insertions, 3 deletions
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 5c33d65..f0fb310 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -694,12 +694,14 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Visibility) { unsigned AddrSpace; bool ThreadLocal, IsConstant, UnnamedAddr; + LocTy UnnamedAddrLoc; LocTy TyLoc; PATypeHolder Ty(Type::getVoidTy(Context)); if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) || ParseOptionalAddrSpace(AddrSpace) || - ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr) || + ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, + &UnnamedAddrLoc) || ParseGlobalType(IsConstant) || ParseType(Ty, TyLoc)) return true; @@ -714,6 +716,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, return true; } + if (!Init && UnnamedAddr) + return Error(UnnamedAddrLoc, "only definitions can have unnamed_addr"); + if (Ty->isFunctionTy() || Ty->isLabelTy()) return Error(TyLoc, "invalid type for global variable"); @@ -2669,6 +2674,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { unsigned Visibility, RetAttrs; bool UnnamedAddr; + LocTy UnnamedAddrLoc; CallingConv::ID CC; PATypeHolder RetType(Type::getVoidTy(Context)); LocTy RetTypeLoc = Lex.getLoc(); @@ -2676,10 +2682,14 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { ParseOptionalVisibility(Visibility) || ParseOptionalCallingConv(CC) || ParseOptionalAttrs(RetAttrs, 1) || - ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr) || + ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, + &UnnamedAddrLoc) || ParseType(RetType, RetTypeLoc, true /*void allowed*/)) return true; + if (!isDefine && UnnamedAddr) + return Error(UnnamedAddrLoc, "only definitions can have unnamed_addr"); + // Verify that the linkage is ok. switch ((GlobalValue::LinkageTypes)Linkage) { case GlobalValue::ExternalLinkage: diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 1baa7d8..93e7f77 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -162,10 +162,12 @@ namespace llvm { Lex.Lex(); return true; } - bool ParseOptionalToken(lltok::Kind T, bool &Present) { + bool ParseOptionalToken(lltok::Kind T, bool &Present, LocTy *Loc = 0) { if (Lex.getKind() != T) { Present = false; } else { + if (Loc) + *Loc = Lex.getLoc(); Lex.Lex(); Present = true; } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 58ec6fe..ee62a29 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -469,6 +469,8 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { Assert1(GV.hasExternalLinkage() || GV.hasDLLImportLinkage() || GV.hasExternalWeakLinkage(), "invalid linkage type for global declaration", &GV); + Assert1(!GV.hasUnnamedAddr(), "only definitions can have unnamed_addr", + &GV); } visitGlobalValue(GV); @@ -725,6 +727,7 @@ void Verifier::visitFunction(Function &F) { Assert1(F.hasExternalLinkage() || F.hasDLLImportLinkage() || F.hasExternalWeakLinkage(), "invalid linkage type for function declaration", &F); + Assert1(!F.hasUnnamedAddr(), "only definitions can have unnamed_addr", &F); } else { // Verify that this function (which has a body) is not named "llvm.*". It // is not legal to define intrinsics. diff --git a/test/Assembler/declare-unnamed-addr.ll b/test/Assembler/declare-unnamed-addr.ll new file mode 100644 index 0000000..ac74299 --- /dev/null +++ b/test/Assembler/declare-unnamed-addr.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>%t +; RUN: FileCheck -input-file=%t %s + +declare unnamed_addr i32 @zed() + +// CHECK: error: only definitions can have unnamed_addr +// CHECK: declare unnamed_addr i32 @zed() +// CHECK: ^ diff --git a/test/Assembler/external-unnamed-addr.ll b/test/Assembler/external-unnamed-addr.ll new file mode 100644 index 0000000..856f592 --- /dev/null +++ b/test/Assembler/external-unnamed-addr.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>%t +; RUN: FileCheck -input-file=%t %s + +@foo = external unnamed_addr global i8* + +// CHECK: error: only definitions can have unnamed_addr +// CHECK: @foo = external unnamed_addr global i8* +// CHECK: ^ diff --git a/unittests/VMCore/VerifierTest.cpp b/unittests/VMCore/VerifierTest.cpp index 55ce144..d94dc22 100644 --- a/unittests/VMCore/VerifierTest.cpp +++ b/unittests/VMCore/VerifierTest.cpp @@ -61,5 +61,31 @@ TEST(VerifierTest, AliasUnnamedAddr) { EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr")); } +TEST(VerifierTest, ExternalUnnamedAddr) { + LLVMContext &C = getGlobalContext(); + Module M("M", C); + const Type *Ty = Type::getInt8Ty(C); + GlobalVariable *GV = new GlobalVariable(M, Ty, true, + GlobalValue::ExternalLinkage, + NULL, "foo"); + GV->setUnnamedAddr(true); + std::string Error; + EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); + EXPECT_TRUE(StringRef(Error) + .startswith("only definitions can have unnamed_addr")); +} + +TEST(VerifierTest, DeclarationUnnamedAddr) { + LLVMContext &C = getGlobalContext(); + Module M("M", C); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false); + Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, + "foo", &M); + F->setUnnamedAddr(true); + std::string Error; + EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); + EXPECT_TRUE(StringRef(Error) + .startswith("only definitions can have unnamed_addr")); +} } } |