[WinEH] Add additional verification
[oota-llvm.git] / unittests / Linker / LinkModulesTest.cpp
index 4eba718e2663c47c239dfe0be141d070b5a71911..322a44f8aafe5d03fd6d3d0fdd51a72465e783a4 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Linker/Linker.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm-c/Core.h"
 #include "llvm-c/Linker.h"
 #include "gtest/gtest.h"
 
@@ -71,6 +72,10 @@ protected:
   BasicBlock *ExitBB;
 };
 
+static void expectNoDiags(const DiagnosticInfo &DI, void *C) {
+  EXPECT_TRUE(false);
+}
+
 TEST_F(LinkModuleTest, BlockAddress) {
   IRBuilder<> Builder(EntryBB);
 
@@ -93,10 +98,8 @@ TEST_F(LinkModuleTest, BlockAddress) {
   Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));
 
   Module *LinkedModule = new Module("MyModuleLinked", Ctx);
-  Linker::linkModules(*LinkedModule, *M);
-
-  // Delete the original module.
-  M.reset();
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*LinkedModule, std::move(M));
 
   // Check that the global "@switch.bas" is well-formed.
   const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas");
@@ -169,13 +172,15 @@ static Module *getInternal(LLVMContext &Ctx) {
 TEST_F(LinkModuleTest, EmptyModule) {
   std::unique_ptr<Module> InternalM(getInternal(Ctx));
   std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
-  Linker::linkModules(*EmptyM, *InternalM);
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*EmptyM, std::move(InternalM));
 }
 
 TEST_F(LinkModuleTest, EmptyModule2) {
   std::unique_ptr<Module> InternalM(getInternal(Ctx));
   std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
-  Linker::linkModules(*InternalM, *EmptyM);
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*InternalM, std::move(EmptyM));
 }
 
 TEST_F(LinkModuleTest, TypeMerge) {
@@ -190,7 +195,8 @@ TEST_F(LinkModuleTest, TypeMerge) {
                       "@t2 = weak global %t zeroinitializer\n";
   std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, C);
 
-  Linker::linkModules(*M1, *M2, [](const llvm::DiagnosticInfo &) {});
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*M1, std::move(M2));
 
   EXPECT_EQ(M1->getNamedGlobal("t1")->getType(),
             M1->getNamedGlobal("t2")->getType());
@@ -220,6 +226,37 @@ TEST_F(LinkModuleTest, CAPIFailure) {
   LLVMDisposeMessage(errout);
 }
 
+TEST_F(LinkModuleTest, NewCAPISuccess) {
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
+  LLVMBool Result =
+      LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release()));
+  EXPECT_EQ(0, Result);
+  // "bar" is present in destination module
+  EXPECT_NE(nullptr, DestM->getFunction("bar"));
+}
+
+static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) {
+  auto *Err = reinterpret_cast<std::string *>(C);
+  char *CErr = LLVMGetDiagInfoDescription(DI);
+  *Err = CErr;
+  LLVMDisposeMessage(CErr);
+}
+
+TEST_F(LinkModuleTest, NewCAPIFailure) {
+  // Symbol clash between two modules
+  LLVMContext Ctx;
+  std::string Err;
+  LLVMContextSetDiagnosticHandler(wrap(&Ctx), diagnosticHandler, &Err);
+
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
+  LLVMBool Result =
+      LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release()));
+  EXPECT_EQ(1, Result);
+  EXPECT_EQ("Linking globals named 'foo': symbol multiply defined!", Err);
+}
+
 TEST_F(LinkModuleTest, MoveDistinctMDs) {
   LLVMContext C;
   SMDiagnostic Err;
@@ -267,7 +304,8 @@ TEST_F(LinkModuleTest, MoveDistinctMDs) {
   // Link into destination module.
   auto Dst = llvm::make_unique<Module>("Linked", C);
   ASSERT_TRUE(Dst.get());
-  Linker::linkModules(*Dst, *Src, [](const llvm::DiagnosticInfo &) {});
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*Dst, std::move(Src));
 
   // Check that distinct metadata was moved, not cloned.  Even !4, the uniqued
   // node, should effectively be moved, since its only operand hasn't changed.