OSDN Git Service

Reject uses of unnamed_addr in declarations.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 13 Jan 2011 01:30:30 +0000 (01:30 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 13 Jan 2011 01:30:30 +0000 (01:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123358 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/VMCore/Verifier.cpp
test/Assembler/declare-unnamed-addr.ll [new file with mode: 0644]
test/Assembler/external-unnamed-addr.ll [new file with mode: 0644]
unittests/VMCore/VerifierTest.cpp

index 5c33d65..f0fb310 100644 (file)
@@ -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:
index 1baa7d8..93e7f77 100644 (file)
@@ -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;
       }
index 58ec6fe..ee62a29 100644 (file)
@@ -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 (file)
index 0000000..ac74299
--- /dev/null
@@ -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 (file)
index 0000000..856f592
--- /dev/null
@@ -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:                 ^
index 55ce144..d94dc22 100644 (file)
@@ -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"));
+}
 }
 }