[LinkerTest] Don't leak error string.
[oota-llvm.git] / unittests / Linker / LinkModulesTest.cpp
index fbd03639fa704bf1e7d8ce20a5dd2b1326643ffe..2a0a7bfa84772f55640f18723659d3c90f17773c 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Linker/Linker.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm-c/Linker.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -23,7 +24,7 @@ namespace {
 
 class LinkModuleTest : public testing::Test {
 protected:
-  virtual void SetUp() {
+  void SetUp() override {
     M.reset(new Module("MyModule", Ctx));
     FunctionType *FTy = FunctionType::get(
         Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/);
@@ -56,7 +57,7 @@ protected:
     GV->setInitializer(ConstantArray::get(AT, Init));
   }
 
-  virtual void TearDown() { M.reset(); }
+  void TearDown() override { M.reset(); }
 
   LLVMContext Ctx;
   std::unique_ptr<Module> M;
@@ -125,6 +126,22 @@ TEST_F(LinkModuleTest, BlockAddress) {
   delete LinkedModule;
 }
 
+static Module *getExternal(LLVMContext &Ctx, StringRef FuncName) {
+  // Create a module with an empty externally-linked function
+  Module *M = new Module("ExternalModule", Ctx);
+  FunctionType *FTy = FunctionType::get(
+      Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
+
+  Function *F =
+      Function::Create(FTy, Function::ExternalLinkage, FuncName, M);
+  F->setCallingConv(CallingConv::C);
+
+  BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
+  IRBuilder<> Builder(BB);
+  Builder.CreateRetVoid();
+  return M;
+}
+
 static Module *getInternal(LLVMContext &Ctx) {
   Module *InternalM = new Module("InternalModule", Ctx);
   FunctionType *FTy = FunctionType::get(
@@ -178,4 +195,28 @@ TEST_F(LinkModuleTest, TypeMerge) {
             M1->getNamedGlobal("t2")->getType());
 }
 
+TEST_F(LinkModuleTest, CAPISuccess) {
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
+  char *errout = nullptr;
+  LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+                                    LLVMLinkerDestroySource, &errout);
+  EXPECT_EQ(0, result);
+  EXPECT_EQ(nullptr, errout);
+  // "bar" is present in destination module
+  EXPECT_NE(nullptr, DestM->getFunction("bar"));
+}
+
+TEST_F(LinkModuleTest, CAPIFailure) {
+  // Symbol clash between two modules
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
+  char *errout = nullptr;
+  LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+                                    LLVMLinkerDestroySource, &errout);
+  EXPECT_EQ(1, result);
+  EXPECT_STREQ("Linking globals named 'foo': symbol multiply defined!", errout);
+  std::free(errout);
+}
+
 } // end anonymous namespace