Skip to content

Commit

Permalink
Fix returning error message in LLVMLinkModules
Browse files Browse the repository at this point in the history
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 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239646 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
eliben committed Jun 12, 2015
1 parent 69fb65b commit 21a987d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/Linker/LinkModules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
40 changes: 40 additions & 0 deletions unittests/Linker/LinkModulesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -178,4 +195,27 @@ 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);
}

} // end anonymous namespace

0 comments on commit 21a987d

Please sign in to comment.