From ff715e2d5ec91e971daa70fdcfc153903030cd15 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 12 Jun 2015 23:26:42 +0000 Subject: [PATCH] Fix returning error message in LLVMLinkModules On error, the temporary output stream wouldn't be flushed and therefore the caller would see an empty error message. Patch by Antoine Pitrou Differential Revision: http://reviews.llvm.org/D10241 llvm-svn: 239646 --- llvm/lib/Linker/LinkModules.cpp | 4 +++- llvm/unittests/Linker/LinkModulesTest.cpp | 40 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index 1b7a331..b47d268 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -1802,7 +1802,9 @@ LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, LLVMBool Result = Linker::LinkModules( D, unwrap(Src), [&](const DiagnosticInfo &DI) { DI.print(DP); }); - if (OutMessages && Result) + if (OutMessages && Result) { + Stream.flush(); *OutMessages = strdup(Message.c_str()); + } return Result; } diff --git a/llvm/unittests/Linker/LinkModulesTest.cpp b/llvm/unittests/Linker/LinkModulesTest.cpp index b4689cb..58a3e72 100644 --- a/llvm/unittests/Linker/LinkModulesTest.cpp +++ b/llvm/unittests/Linker/LinkModulesTest.cpp @@ -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; @@ -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,27 @@ TEST_F(LinkModuleTest, TypeMerge) { M1->getNamedGlobal("t2")->getType()); } +TEST_F(LinkModuleTest, CAPISuccess) { + std::unique_ptr DestM(getExternal(Ctx, "foo")); + std::unique_ptr 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 DestM(getExternal(Ctx, "foo")); + std::unique_ptr 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); +} + } // end anonymous namespace -- 2.7.4