Make Driver::link and LinkingContext::validate return true on success.

This patch inverts the return value of these functions, so that they return
"true" on success and "false" on failure. The meaning of boolean return value
was mixed in LLD; for example, InputGraph::validate() returns true on success.
With this patch they'll become consistent.

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1748

llvm-svn: 191341
This commit is contained in:
Rui Ueyama 2013-09-24 23:26:34 +00:00
parent 3ce27103d9
commit 8db1eddc07
15 changed files with 180 additions and 190 deletions

View File

@ -68,9 +68,8 @@ namespace lld {
bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) { bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
CoreLinkingContext info; CoreLinkingContext info;
if (parse(argc, argv, info)) if (!parse(argc, argv, info))
return true; return false;
return Driver::link(info); return Driver::link(info);
} }
@ -87,7 +86,7 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
diagnostics << "error: missing arg value for '" diagnostics << "error: missing arg value for '"
<< parsedArgs->getArgString(missingIndex) << "' expected " << parsedArgs->getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n"; << missingCount << " argument(s).\n";
return true; return false;
} }
std::unique_ptr<InputGraph> inputGraph(new InputGraph()); std::unique_ptr<InputGraph> inputGraph(new InputGraph());
@ -148,7 +147,7 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
if (!inputGraph->numFiles()) { if (!inputGraph->numFiles()) {
diagnostics << "No input files\n"; diagnostics << "No input files\n";
return true; return false;
} }
ctx.setInputGraph(std::move(inputGraph)); ctx.setInputGraph(std::move(inputGraph));

View File

@ -82,11 +82,10 @@ MachOFileNode::createLinkerInput(const LinkingContext &ctx) {
bool DarwinLdDriver::linkMachO(int argc, const char *argv[], bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
raw_ostream &diagnostics) { raw_ostream &diagnostics) {
MachOLinkingContext ctx; MachOLinkingContext ctx;
if (parse(argc, argv, ctx, diagnostics)) if (!parse(argc, argv, ctx, diagnostics))
return true;
if (ctx.doNothing())
return false; return false;
if (ctx.doNothing())
return true;
return link(ctx, diagnostics); return link(ctx, diagnostics);
} }
@ -104,7 +103,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
diagnostics << "error: missing arg value for '" diagnostics << "error: missing arg value for '"
<< parsedArgs->getArgString(missingIndex) << "' expected " << parsedArgs->getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n"; << missingCount << " argument(s).\n";
return true; return false;
} }
for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN), for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
@ -168,12 +167,12 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (ctx.outputFileType() != mach_o::MH_DYLIB) { if (ctx.outputFileType() != mach_o::MH_DYLIB) {
diagnostics diagnostics
<< "error: -compatibility_version can only be used with -dylib\n"; << "error: -compatibility_version can only be used with -dylib\n";
return true; return false;
} }
uint32_t parsedVers; uint32_t parsedVers;
if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
diagnostics << "error: -compatibility_version value is malformed\n"; diagnostics << "error: -compatibility_version value is malformed\n";
return true; return false;
} }
ctx.setCompatibilityVersion(parsedVers); ctx.setCompatibilityVersion(parsedVers);
} }
@ -181,12 +180,12 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_current_version)) { if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_current_version)) {
if (ctx.outputFileType() != mach_o::MH_DYLIB) { if (ctx.outputFileType() != mach_o::MH_DYLIB) {
diagnostics << "-current_version can only be used with -dylib\n"; diagnostics << "-current_version can only be used with -dylib\n";
return true; return false;
} }
uint32_t parsedVers; uint32_t parsedVers;
if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
diagnostics << "error: -current_version value is malformed\n"; diagnostics << "error: -current_version value is malformed\n";
return true; return false;
} }
ctx.setCurrentVersion(parsedVers); ctx.setCurrentVersion(parsedVers);
} }
@ -201,7 +200,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (ctx.arch() == MachOLinkingContext::arch_unknown) { if (ctx.arch() == MachOLinkingContext::arch_unknown) {
diagnostics << "error: unknown arch named '" << archStr->getValue() diagnostics << "error: unknown arch named '" << archStr->getValue()
<< "'\n"; << "'\n";
return true; return false;
} }
} }
@ -214,20 +213,20 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
case OPT_macosx_version_min: case OPT_macosx_version_min:
if (ctx.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) { if (ctx.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) {
diagnostics << "error: malformed macosx_version_min value\n"; diagnostics << "error: malformed macosx_version_min value\n";
return true; return false;
} }
break; break;
case OPT_ios_version_min: case OPT_ios_version_min:
if (ctx.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) { if (ctx.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) {
diagnostics << "error: malformed ios_version_min value\n"; diagnostics << "error: malformed ios_version_min value\n";
return true; return false;
} }
break; break;
case OPT_ios_simulator_version_min: case OPT_ios_simulator_version_min:
if (ctx.setOS(MachOLinkingContext::OS::iOS_simulator, if (ctx.setOS(MachOLinkingContext::OS::iOS_simulator,
minOS->getValue())) { minOS->getValue())) {
diagnostics << "error: malformed ios_simulator_version_min value\n"; diagnostics << "error: malformed ios_simulator_version_min value\n";
return true; return false;
} }
break; break;
} }
@ -242,7 +241,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// If only -help on command line, don't try to do any linking // If only -help on command line, don't try to do any linking
if (argc == 2) { if (argc == 2) {
ctx.setDoNothing(true); ctx.setDoNothing(true);
return false; return true;
} }
} }
@ -258,16 +257,13 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (!inputGraph->numFiles()) { if (!inputGraph->numFiles()) {
diagnostics << "No input files\n"; diagnostics << "No input files\n";
return true; return false;
} }
ctx.setInputGraph(std::move(inputGraph)); ctx.setInputGraph(std::move(inputGraph));
// Validate the combination of options used. // Validate the combination of options used.
if (ctx.validate(diagnostics)) return ctx.validate(diagnostics);
return true;
return false;
} }
} // namespace lld } // namespace lld

View File

@ -42,7 +42,7 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
} }
InputGraph &inputGraph = context.inputGraph(); InputGraph &inputGraph = context.inputGraph();
if (!inputGraph.numFiles()) if (!inputGraph.numFiles())
return true; return false;
// Read inputs // Read inputs
ScopedTask readTask(getDefaultDomain(), "Read Args"); ScopedTask readTask(getDefaultDomain(), "Read Args");
@ -58,7 +58,7 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
auto linkerInput = fileNode->createLinkerInput(context); auto linkerInput = fileNode->createLinkerInput(context);
if (!linkerInput) { if (!linkerInput) {
llvm::outs() << fileNode->errStr(error_code(linkerInput)) << "\n"; llvm::outs() << fileNode->errStr(error_code(linkerInput)) << "\n";
return true; return false;
} }
linkerInputs.push_back(std::move(*linkerInput)); linkerInputs.push_back(std::move(*linkerInput));
} }
@ -84,7 +84,7 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
readTask.end(); readTask.end();
if (fail) if (fail)
return true; return false;
InputFiles inputs; InputFiles inputs;
@ -105,7 +105,7 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
Resolver resolver(context, inputs); Resolver resolver(context, inputs);
if (resolver.resolve()) { if (resolver.resolve()) {
if (!context.allowRemainingUndefines()) if (!context.allowRemainingUndefines())
return true; return false;
} }
MutableFile &merged = resolver.resultFile(); MutableFile &merged = resolver.resultFile();
resolveTask.end(); resolveTask.end();
@ -122,10 +122,10 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
if (error_code ec = context.writeFile(merged)) { if (error_code ec = context.writeFile(merged)) {
diagnostics << "Failed to write file '" << context.outputPath() diagnostics << "Failed to write file '" << context.outputPath()
<< "': " << ec.message() << "\n"; << "': " << ec.message() << "\n";
return true; return false;
} }
return false; return true;
} }
} // namespace } // namespace

View File

@ -98,11 +98,10 @@ std::string ELFFileNode::errStr(llvm::error_code errc) {
bool GnuLdDriver::linkELF(int argc, const char *argv[], bool GnuLdDriver::linkELF(int argc, const char *argv[],
raw_ostream &diagnostics) { raw_ostream &diagnostics) {
std::unique_ptr<ELFLinkingContext> options; std::unique_ptr<ELFLinkingContext> options;
bool error = parse(argc, argv, options, diagnostics); if (!parse(argc, argv, options, diagnostics))
if (error)
return true;
if (!options)
return false; return false;
if (!options)
return true;
return link(*options, diagnostics); return link(*options, diagnostics);
} }
@ -122,13 +121,13 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
diagnostics << "error: missing arg value for '" diagnostics << "error: missing arg value for '"
<< parsedArgs->getArgString(missingIndex) << "' expected " << parsedArgs->getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n"; << missingCount << " argument(s).\n";
return true; return false;
} }
// Handle --help // Handle --help
if (parsedArgs->getLastArg(OPT_help)) { if (parsedArgs->getLastArg(OPT_help)) {
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false); table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
return false; return true;
} }
// Use -target or use default target triple to instantiate LinkingContext // Use -target or use default target triple to instantiate LinkingContext
@ -141,7 +140,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
if (!ctx) { if (!ctx) {
diagnostics << "unknown target triple\n"; diagnostics << "unknown target triple\n";
return true; return false;
} }
std::unique_ptr<InputGraph> inputGraph(new InputGraph()); std::unique_ptr<InputGraph> inputGraph(new InputGraph());
@ -276,7 +275,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
(llvm::dyn_cast<ControlNode>)(controlNodeStack.top()) (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
->processControlExit(); ->processControlExit();
controlNodeStack.pop(); controlNodeStack.pop();
return false; return true;
case OPT_INPUT: case OPT_INPUT:
case OPT_l: { case OPT_l: {
@ -323,7 +322,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
if (!inputGraph->numFiles()) { if (!inputGraph->numFiles()) {
diagnostics << "No input files\n"; diagnostics << "No input files\n";
return true; return false;
} }
inputGraph->addInternalFile(ctx->createInternalFiles()); inputGraph->addInternalFile(ctx->createInternalFiles());
@ -348,14 +347,14 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
inputGraph->dump(diagnostics); inputGraph->dump(diagnostics);
// Validate the combination of options used. // Validate the combination of options used.
if (ctx->validate(diagnostics)) if (!ctx->validate(diagnostics))
return true; return false;
ctx->setInputGraph(std::move(inputGraph)); ctx->setInputGraph(std::move(inputGraph));
context.swap(ctx); context.swap(ctx);
return false; return true;
} }
/// Get the default target triple based on either the program name /// Get the default target triple based on either the program name

View File

@ -129,7 +129,7 @@ bool UniversalDriver::link(int argc, const char *argv[],
case Flavor::core: case Flavor::core:
return CoreDriver::link(args.size(), args.data(), diagnostics); return CoreDriver::link(args.size(), args.data(), diagnostics);
case Flavor::invalid: case Flavor::invalid:
return true; return false;
} }
llvm_unreachable("Unrecognised flavor"); llvm_unreachable("Unrecognised flavor");
} }

View File

@ -257,8 +257,8 @@ bool WinLinkDriver::linkPECOFF(int argc, const char *argv[],
PECOFFLinkingContext context; PECOFFLinkingContext context;
std::vector<const char *> newargv = processLinkEnv(context, argc, argv); std::vector<const char *> newargv = processLinkEnv(context, argc, argv);
processLibEnv(context); processLibEnv(context);
if (parse(newargv.size() - 1, &newargv[0], context, diagnostics)) if (!parse(newargv.size() - 1, &newargv[0], context, diagnostics))
return true; return false;
return link(context, diagnostics); return link(context, diagnostics);
} }
@ -269,7 +269,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
std::unique_ptr<llvm::opt::InputArgList> parsedArgs = parseArgs( std::unique_ptr<llvm::opt::InputArgList> parsedArgs = parseArgs(
argc, argv, diagnostics, isDirective); argc, argv, diagnostics, isDirective);
if (!parsedArgs) if (!parsedArgs)
return true; return false;
if (!ctx.hasInputGraph()) if (!ctx.hasInputGraph())
ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph())); ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
@ -280,7 +280,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
if (parsedArgs->getLastArg(OPT_help)) { if (parsedArgs->getLastArg(OPT_help)) {
WinLinkOptTable table; WinLinkOptTable table;
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false); table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
return true; return false;
} }
// Handle /nodefaultlib:<lib>. The same option without argument is handled in // Handle /nodefaultlib:<lib>. The same option without argument is handled in
@ -316,7 +316,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
// it's smaller than the actual size, the linker should warn about that. // it's smaller than the actual size, the linker should warn about that.
// Currently we just ignore the value of size parameter. // Currently we just ignore the value of size parameter.
if (parseMemoryOption(inputArg->getValue(), addr, size)) if (parseMemoryOption(inputArg->getValue(), addr, size))
return true; return false;
ctx.setBaseAddress(addr); ctx.setBaseAddress(addr);
break; break;
@ -325,7 +325,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
uint64_t reserve; uint64_t reserve;
uint64_t commit = ctx.getStackCommit(); uint64_t commit = ctx.getStackCommit();
if (parseMemoryOption(inputArg->getValue(), reserve, commit)) if (parseMemoryOption(inputArg->getValue(), reserve, commit))
return true; return false;
ctx.setStackReserve(reserve); ctx.setStackReserve(reserve);
ctx.setStackCommit(commit); ctx.setStackCommit(commit);
break; break;
@ -336,7 +336,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
uint64_t reserve; uint64_t reserve;
uint64_t commit = ctx.getHeapCommit(); uint64_t commit = ctx.getHeapCommit();
if (parseMemoryOption(inputArg->getValue(), reserve, commit)) if (parseMemoryOption(inputArg->getValue(), reserve, commit))
return true; return false;
ctx.setHeapReserve(reserve); ctx.setHeapReserve(reserve);
ctx.setHeapCommit(commit); ctx.setHeapCommit(commit);
break; break;
@ -347,7 +347,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
StringRef arg = inputArg->getValue(); StringRef arg = inputArg->getValue();
if (arg.getAsInteger(10, align)) { if (arg.getAsInteger(10, align)) {
diagnostics << "error: invalid value for /align: " << arg << "\n"; diagnostics << "error: invalid value for /align: " << arg << "\n";
return true; return false;
} }
ctx.setSectionAlignment(align); ctx.setSectionAlignment(align);
break; break;
@ -358,7 +358,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
llvm::COFF::MachineTypes type = stringToMachineType(arg); llvm::COFF::MachineTypes type = stringToMachineType(arg);
if (type == llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN) { if (type == llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
diagnostics << "error: unknown machine type: " << arg << "\n"; diagnostics << "error: unknown machine type: " << arg << "\n";
return true; return false;
} }
ctx.setMachineType(type); ctx.setMachineType(type);
break; break;
@ -367,7 +367,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
case OPT_version: { case OPT_version: {
uint32_t major, minor; uint32_t major, minor;
if (parseVersion(inputArg->getValue(), major, minor)) if (parseVersion(inputArg->getValue(), major, minor))
return true; return false;
ctx.setImageVersion(PECOFFLinkingContext::Version(major, minor)); ctx.setImageVersion(PECOFFLinkingContext::Version(major, minor));
break; break;
} }
@ -381,7 +381,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
if (!osVersion.empty()) { if (!osVersion.empty()) {
uint32_t major, minor; uint32_t major, minor;
if (parseVersion(osVersion, major, minor)) if (parseVersion(osVersion, major, minor))
return true; return false;
ctx.setMinOSVersion(PECOFFLinkingContext::Version(major, minor)); ctx.setMinOSVersion(PECOFFLinkingContext::Version(major, minor));
} }
// Parse subsystem name. // Parse subsystem name.
@ -390,7 +390,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) { if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
diagnostics << "error: unknown subsystem name: " << subsystemStr diagnostics << "error: unknown subsystem name: " << subsystemStr
<< "\n"; << "\n";
return true; return false;
} }
ctx.setSubsystem(subsystem); ctx.setSubsystem(subsystem);
break; break;
@ -399,7 +399,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
case OPT_failifmismatch: case OPT_failifmismatch:
if (handleFailIfMismatchOption(inputArg->getValue(), failIfMismatchMap, if (handleFailIfMismatchOption(inputArg->getValue(), failIfMismatchMap,
diagnostics)) diagnostics))
return true; return false;
break; break;
case OPT_entry: case OPT_entry:
@ -427,7 +427,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
// /fixed is not compatible with /dynamicbase. Check for it. // /fixed is not compatible with /dynamicbase. Check for it.
if (parsedArgs->getLastArg(OPT_dynamicbase)) { if (parsedArgs->getLastArg(OPT_dynamicbase)) {
diagnostics << "/dynamicbase must not be specified with /fixed\n"; diagnostics << "/dynamicbase must not be specified with /fixed\n";
return true; return false;
} }
ctx.setBaseRelocationEnabled(false); ctx.setBaseRelocationEnabled(false);
ctx.setDynamicBaseEnabled(false); ctx.setDynamicBaseEnabled(false);
@ -493,7 +493,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
// Specifying both /opt:ref and /opt:noref is an error. // Specifying both /opt:ref and /opt:noref is an error.
if (parsedArgs->getLastArg(OPT_ref) && parsedArgs->getLastArg(OPT_ref_no)) { if (parsedArgs->getLastArg(OPT_ref) && parsedArgs->getLastArg(OPT_ref_no)) {
diagnostics << "/opt:ref must not be specified with /opt:noref\n"; diagnostics << "/opt:ref must not be specified with /opt:noref\n";
return true; return false;
} }
// If dead-stripping is enabled, we need to add the entry symbol and // If dead-stripping is enabled, we need to add the entry symbol and
@ -525,7 +525,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
if (!inputGraph.numFiles()) { if (!inputGraph.numFiles()) {
diagnostics << "No input files\n"; diagnostics << "No input files\n";
return true; return false;
} }
// A list of undefined symbols will be added to the input // A list of undefined symbols will be added to the input

View File

@ -272,7 +272,7 @@ private:
CoreLinkingContext::CoreLinkingContext() {} CoreLinkingContext::CoreLinkingContext() {}
bool CoreLinkingContext::validateImpl(raw_ostream &diagnostics) { bool CoreLinkingContext::validateImpl(raw_ostream &diagnostics) {
return false; return true;
} }
void CoreLinkingContext::addPasses(PassManager &pm) const { void CoreLinkingContext::addPasses(PassManager &pm) const {

View File

@ -91,7 +91,7 @@ bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
_writer = createWriterELF(*this); _writer = createWriterELF(*this);
break; break;
} }
return false; return true;
} }
bool ELFLinkingContext::isDynamic() const { bool ELFLinkingContext::isDynamic() const {

View File

@ -207,28 +207,28 @@ bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
if (_currentVersion && _outputFileType != mach_o::MH_DYLIB) { if (_currentVersion && _outputFileType != mach_o::MH_DYLIB) {
diagnostics << "error: -current_version can only be used with dylibs\n"; diagnostics << "error: -current_version can only be used with dylibs\n";
return true; return false;
} }
if (_compatibilityVersion && _outputFileType != mach_o::MH_DYLIB) { if (_compatibilityVersion && _outputFileType != mach_o::MH_DYLIB) {
diagnostics diagnostics
<< "error: -compatibility_version can only be used with dylibs\n"; << "error: -compatibility_version can only be used with dylibs\n";
return true; return false;
} }
if (_deadStrippableDylib && _outputFileType != mach_o::MH_DYLIB) { if (_deadStrippableDylib && _outputFileType != mach_o::MH_DYLIB) {
diagnostics diagnostics
<< "error: -mark_dead_strippable_dylib can only be used with dylibs.\n"; << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
return true; return false;
} }
if (!_bundleLoader.empty() && outputFileType() != mach_o::MH_BUNDLE) { if (!_bundleLoader.empty() && outputFileType() != mach_o::MH_BUNDLE) {
diagnostics diagnostics
<< "error: -bundle_loader can only be used with Mach-O bundles\n"; << "error: -bundle_loader can only be used with Mach-O bundles\n";
return true; return false;
} }
return false; return true;
} }
bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) { bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {

View File

@ -40,39 +40,39 @@ bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
diagnostics << "Invalid stack size: reserve size must be equal to or " diagnostics << "Invalid stack size: reserve size must be equal to or "
<< "greater than commit size, but got " << _stackCommit << "greater than commit size, but got " << _stackCommit
<< " and " << _stackReserve << ".\n"; << " and " << _stackReserve << ".\n";
return true; return false;
} }
if (_heapReserve < _heapCommit) { if (_heapReserve < _heapCommit) {
diagnostics << "Invalid heap size: reserve size must be equal to or " diagnostics << "Invalid heap size: reserve size must be equal to or "
<< "greater than commit size, but got " << _heapCommit << "greater than commit size, but got " << _heapCommit
<< " and " << _heapReserve << ".\n"; << " and " << _heapReserve << ".\n";
return true; return false;
} }
// It's an error if the base address is not multiple of 64K. // It's an error if the base address is not multiple of 64K.
if (_baseAddress & 0xffff) { if (_baseAddress & 0xffff) {
diagnostics << "Base address have to be multiple of 64K, but got " diagnostics << "Base address have to be multiple of 64K, but got "
<< _baseAddress << "\n"; << _baseAddress << "\n";
return true; return false;
} }
std::bitset<64> alignment(_sectionAlignment); std::bitset<64> alignment(_sectionAlignment);
if (alignment.count() != 1) { if (alignment.count() != 1) {
diagnostics << "Section alignment must be a power of 2, but got " diagnostics << "Section alignment must be a power of 2, but got "
<< _sectionAlignment << "\n"; << _sectionAlignment << "\n";
return true; return false;
} }
// Architectures other than i386 is not supported yet. // Architectures other than i386 is not supported yet.
if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386) { if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386) {
diagnostics << "Machine type other than x86 is not supported.\n"; diagnostics << "Machine type other than x86 is not supported.\n";
return true; return false;
} }
_reader = createReaderPECOFF(*this); _reader = createReaderPECOFF(*this);
_writer = createWriterPECOFF(*this); _writer = createWriterPECOFF(*this);
return false; return true;
} }
std::unique_ptr<File> PECOFFLinkingContext::createEntrySymbolFile() { std::unique_ptr<File> PECOFFLinkingContext::createEntrySymbolFile() {

View File

@ -762,8 +762,8 @@ private:
const char **argv = &tokens[0]; const char **argv = &tokens[0];
std::string errorMessage; std::string errorMessage;
llvm::raw_string_ostream stream(errorMessage); llvm::raw_string_ostream stream(errorMessage);
bool parseFailed = WinLinkDriver::parse(argc, argv, _PECOFFLinkingContext, bool parseFailed = !WinLinkDriver::parse(argc, argv, _PECOFFLinkingContext,
stream, /*isDirective*/ true); stream, /*isDirective*/ true);
stream.flush(); stream.flush();
// Print error message if error. // Print error message if error.

View File

@ -33,8 +33,5 @@ int main(int argc, const char *argv[]) {
llvm::PrettyStackTraceProgram stackPrinter(argc, argv); llvm::PrettyStackTraceProgram stackPrinter(argc, argv);
llvm::llvm_shutdown_obj shutdown; llvm::llvm_shutdown_obj shutdown;
if (UniversalDriver::link(argc, argv)) return UniversalDriver::link(argc, argv) ? 0 : 1;
return 1;
else
return 0;
} }

View File

@ -29,7 +29,7 @@ protected:
}; };
TEST_F(DarwinLdParserTest, Basic) { TEST_F(DarwinLdParserTest, Basic) {
EXPECT_FALSE(parse("ld", "foo.o", "bar.o", nullptr)); EXPECT_TRUE(parse("ld", "foo.o", "bar.o", nullptr));
EXPECT_FALSE(_context.allowRemainingUndefines()); EXPECT_FALSE(_context.allowRemainingUndefines());
EXPECT_FALSE(_context.deadStrip()); EXPECT_FALSE(_context.deadStrip());
EXPECT_EQ(2, inputFileCount()); EXPECT_EQ(2, inputFileCount());
@ -38,187 +38,187 @@ TEST_F(DarwinLdParserTest, Basic) {
} }
TEST_F(DarwinLdParserTest, Output) { TEST_F(DarwinLdParserTest, Output) {
EXPECT_FALSE(parse("ld", "-o", "my.out", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-o", "my.out", "foo.o", nullptr));
EXPECT_EQ("my.out", _context.outputPath()); EXPECT_EQ("my.out", _context.outputPath());
} }
TEST_F(DarwinLdParserTest, Dylib) { TEST_F(DarwinLdParserTest, Dylib) {
EXPECT_FALSE(parse("ld", "-dylib", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-dylib", "foo.o", nullptr));
EXPECT_EQ(mach_o::MH_DYLIB, _context.outputFileType()); EXPECT_EQ(mach_o::MH_DYLIB, _context.outputFileType());
} }
TEST_F(DarwinLdParserTest, Relocatable) { TEST_F(DarwinLdParserTest, Relocatable) {
EXPECT_FALSE(parse("ld", "-r", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-r", "foo.o", nullptr));
EXPECT_EQ(mach_o::MH_OBJECT, _context.outputFileType()); EXPECT_EQ(mach_o::MH_OBJECT, _context.outputFileType());
} }
TEST_F(DarwinLdParserTest, Bundle) { TEST_F(DarwinLdParserTest, Bundle) {
EXPECT_FALSE(parse("ld", "-bundle", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-bundle", "foo.o", nullptr));
EXPECT_EQ(mach_o::MH_BUNDLE, _context.outputFileType()); EXPECT_EQ(mach_o::MH_BUNDLE, _context.outputFileType());
} }
TEST_F(DarwinLdParserTest, Preload) { TEST_F(DarwinLdParserTest, Preload) {
EXPECT_FALSE(parse("ld", "-preload", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-preload", "foo.o", nullptr));
EXPECT_EQ(mach_o::MH_PRELOAD, _context.outputFileType()); EXPECT_EQ(mach_o::MH_PRELOAD, _context.outputFileType());
} }
TEST_F(DarwinLdParserTest, Static) { TEST_F(DarwinLdParserTest, Static) {
EXPECT_FALSE(parse("ld", "-static", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-static", "foo.o", nullptr));
EXPECT_EQ(mach_o::MH_EXECUTE, _context.outputFileType()); EXPECT_EQ(mach_o::MH_EXECUTE, _context.outputFileType());
} }
TEST_F(DarwinLdParserTest, Entry) { TEST_F(DarwinLdParserTest, Entry) {
EXPECT_FALSE(parse("ld", "-e", "entryFunc", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-e", "entryFunc", "foo.o", nullptr));
EXPECT_EQ("entryFunc", _context.entrySymbolName()); EXPECT_EQ("entryFunc", _context.entrySymbolName());
} }
TEST_F(DarwinLdParserTest, OutputPath) { TEST_F(DarwinLdParserTest, OutputPath) {
EXPECT_FALSE(parse("ld", "-o", "foo", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-o", "foo", "foo.o", nullptr));
EXPECT_EQ("foo", _context.outputPath()); EXPECT_EQ("foo", _context.outputPath());
} }
TEST_F(DarwinLdParserTest, DeadStrip) { TEST_F(DarwinLdParserTest, DeadStrip) {
EXPECT_FALSE(parse("ld", "-dead_strip", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-dead_strip", "foo.o", nullptr));
EXPECT_TRUE(_context.deadStrip()); EXPECT_TRUE(_context.deadStrip());
} }
TEST_F(DarwinLdParserTest, DeadStripRootsExe) { TEST_F(DarwinLdParserTest, DeadStripRootsExe) {
EXPECT_FALSE(parse("ld", "-dead_strip", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-dead_strip", "foo.o", nullptr));
EXPECT_FALSE(_context.globalsAreDeadStripRoots()); EXPECT_FALSE(_context.globalsAreDeadStripRoots());
} }
TEST_F(DarwinLdParserTest, DeadStripRootsDylib) { TEST_F(DarwinLdParserTest, DeadStripRootsDylib) {
EXPECT_FALSE(parse("ld", "-dylib", "-dead_strip", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-dylib", "-dead_strip", "foo.o", nullptr));
EXPECT_TRUE(_context.globalsAreDeadStripRoots()); EXPECT_TRUE(_context.globalsAreDeadStripRoots());
} }
TEST_F(DarwinLdParserTest, Arch) { TEST_F(DarwinLdParserTest, Arch) {
EXPECT_FALSE(parse("ld", "-arch", "x86_64", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-arch", "x86_64", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_x86_64, _context.arch()); EXPECT_EQ(MachOLinkingContext::arch_x86_64, _context.arch());
EXPECT_EQ(mach_o::CPU_TYPE_X86_64, _context.getCPUType()); EXPECT_EQ(mach_o::CPU_TYPE_X86_64, _context.getCPUType());
EXPECT_EQ(mach_o::CPU_SUBTYPE_X86_64_ALL, _context.getCPUSubType()); EXPECT_EQ(mach_o::CPU_SUBTYPE_X86_64_ALL, _context.getCPUSubType());
} }
TEST_F(DarwinLdParserTest, Arch_x86) { TEST_F(DarwinLdParserTest, Arch_x86) {
EXPECT_FALSE(parse("ld", "-arch", "i386", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-arch", "i386", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_x86, _context.arch()); EXPECT_EQ(MachOLinkingContext::arch_x86, _context.arch());
EXPECT_EQ(mach_o::CPU_TYPE_I386, _context.getCPUType()); EXPECT_EQ(mach_o::CPU_TYPE_I386, _context.getCPUType());
EXPECT_EQ(mach_o::CPU_SUBTYPE_X86_ALL, _context.getCPUSubType()); EXPECT_EQ(mach_o::CPU_SUBTYPE_X86_ALL, _context.getCPUSubType());
} }
TEST_F(DarwinLdParserTest, Arch_armv6) { TEST_F(DarwinLdParserTest, Arch_armv6) {
EXPECT_FALSE(parse("ld", "-arch", "armv6", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-arch", "armv6", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_armv6, _context.arch()); EXPECT_EQ(MachOLinkingContext::arch_armv6, _context.arch());
EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType()); EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType());
EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V6, _context.getCPUSubType()); EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V6, _context.getCPUSubType());
} }
TEST_F(DarwinLdParserTest, Arch_armv7) { TEST_F(DarwinLdParserTest, Arch_armv7) {
EXPECT_FALSE(parse("ld", "-arch", "armv7", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-arch", "armv7", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_armv7, _context.arch()); EXPECT_EQ(MachOLinkingContext::arch_armv7, _context.arch());
EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType()); EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType());
EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V7, _context.getCPUSubType()); EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V7, _context.getCPUSubType());
} }
TEST_F(DarwinLdParserTest, Arch_armv7s) { TEST_F(DarwinLdParserTest, Arch_armv7s) {
EXPECT_FALSE(parse("ld", "-arch", "armv7s", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-arch", "armv7s", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_armv7s, _context.arch()); EXPECT_EQ(MachOLinkingContext::arch_armv7s, _context.arch());
EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType()); EXPECT_EQ(mach_o::CPU_TYPE_ARM, _context.getCPUType());
EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V7S, _context.getCPUSubType()); EXPECT_EQ(mach_o::CPU_SUBTYPE_ARM_V7S, _context.getCPUSubType());
} }
TEST_F(DarwinLdParserTest, MinMacOSX10_7) { TEST_F(DarwinLdParserTest, MinMacOSX10_7) {
EXPECT_FALSE(parse("ld", "-macosx_version_min", "10.7", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-macosx_version_min", "10.7", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::macOSX, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::macOSX, _context.os());
EXPECT_TRUE(_context.minOS("10.7", "")); EXPECT_TRUE(_context.minOS("10.7", ""));
EXPECT_FALSE(_context.minOS("10.8", "")); EXPECT_FALSE(_context.minOS("10.8", ""));
} }
TEST_F(DarwinLdParserTest, MinMacOSX10_8) { TEST_F(DarwinLdParserTest, MinMacOSX10_8) {
EXPECT_FALSE(parse("ld", "-macosx_version_min", "10.8.3", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-macosx_version_min", "10.8.3", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::macOSX, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::macOSX, _context.os());
EXPECT_TRUE(_context.minOS("10.7", "")); EXPECT_TRUE(_context.minOS("10.7", ""));
EXPECT_TRUE(_context.minOS("10.8", "")); EXPECT_TRUE(_context.minOS("10.8", ""));
} }
TEST_F(DarwinLdParserTest, iOS5) { TEST_F(DarwinLdParserTest, iOS5) {
EXPECT_FALSE(parse("ld", "-ios_version_min", "5.0", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-ios_version_min", "5.0", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::iOS, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::iOS, _context.os());
EXPECT_TRUE(_context.minOS("", "5.0")); EXPECT_TRUE(_context.minOS("", "5.0"));
EXPECT_FALSE(_context.minOS("", "6.0")); EXPECT_FALSE(_context.minOS("", "6.0"));
} }
TEST_F(DarwinLdParserTest, iOS6) { TEST_F(DarwinLdParserTest, iOS6) {
EXPECT_FALSE(parse("ld", "-ios_version_min", "6.0", "foo.o", nullptr)); EXPECT_TRUE(parse("ld", "-ios_version_min", "6.0", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::iOS, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::iOS, _context.os());
EXPECT_TRUE(_context.minOS("", "5.0")); EXPECT_TRUE(_context.minOS("", "5.0"));
EXPECT_TRUE(_context.minOS("", "6.0")); EXPECT_TRUE(_context.minOS("", "6.0"));
} }
TEST_F(DarwinLdParserTest, iOS_Simulator5) { TEST_F(DarwinLdParserTest, iOS_Simulator5) {
EXPECT_FALSE(parse("ld", "-ios_simulator_version_min", "5.0", "a.o", nullptr)); EXPECT_TRUE(parse("ld", "-ios_simulator_version_min", "5.0", "a.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _context.os());
EXPECT_TRUE(_context.minOS("", "5.0")); EXPECT_TRUE(_context.minOS("", "5.0"));
EXPECT_FALSE(_context.minOS("", "6.0")); EXPECT_FALSE(_context.minOS("", "6.0"));
} }
TEST_F(DarwinLdParserTest, iOS_Simulator6) { TEST_F(DarwinLdParserTest, iOS_Simulator6) {
EXPECT_FALSE(parse("ld", "-ios_simulator_version_min", "6.0", "a.o", nullptr)); EXPECT_TRUE(parse("ld", "-ios_simulator_version_min", "6.0", "a.o", nullptr));
EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _context.os()); EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _context.os());
EXPECT_TRUE(_context.minOS("", "5.0")); EXPECT_TRUE(_context.minOS("", "5.0"));
EXPECT_TRUE(_context.minOS("", "6.0")); EXPECT_TRUE(_context.minOS("", "6.0"));
} }
TEST_F(DarwinLdParserTest, compatibilityVersion) { TEST_F(DarwinLdParserTest, compatibilityVersion) {
EXPECT_FALSE( EXPECT_TRUE(
parse("ld", "-dylib", "-compatibility_version", "1.2.3", "a.o", nullptr)); parse("ld", "-dylib", "-compatibility_version", "1.2.3", "a.o", nullptr));
EXPECT_EQ(_context.compatibilityVersion(), 0x10203U); EXPECT_EQ(_context.compatibilityVersion(), 0x10203U);
} }
TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) { TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) {
EXPECT_TRUE(parse("ld", "-bundle", "-compatibility_version", "1.2.3", "a.o", EXPECT_FALSE(parse("ld", "-bundle", "-compatibility_version", "1.2.3", "a.o",
nullptr)); nullptr));
} }
TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) { TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) {
EXPECT_TRUE(parse("ld", "-bundle", "-compatibility_version", "1,2,3", "a.o", EXPECT_FALSE(parse("ld", "-bundle", "-compatibility_version", "1,2,3", "a.o",
nullptr)); nullptr));
} }
TEST_F(DarwinLdParserTest, currentVersion) { TEST_F(DarwinLdParserTest, currentVersion) {
EXPECT_FALSE( EXPECT_TRUE(
parse("ld", "-dylib", "-current_version", "1.2.3", "a.o", nullptr)); parse("ld", "-dylib", "-current_version", "1.2.3", "a.o", nullptr));
EXPECT_EQ(_context.currentVersion(), 0x10203U); EXPECT_EQ(_context.currentVersion(), 0x10203U);
} }
TEST_F(DarwinLdParserTest, currentVersionInvalidType) { TEST_F(DarwinLdParserTest, currentVersionInvalidType) {
EXPECT_TRUE( EXPECT_FALSE(
parse("ld", "-bundle", "-current_version", "1.2.3", "a.o", nullptr)); parse("ld", "-bundle", "-current_version", "1.2.3", "a.o", nullptr));
} }
TEST_F(DarwinLdParserTest, currentVersionInvalidValue) { TEST_F(DarwinLdParserTest, currentVersionInvalidValue) {
EXPECT_TRUE( EXPECT_FALSE(
parse("ld", "-bundle", "-current_version", "1,2,3", "a.o", nullptr)); parse("ld", "-bundle", "-current_version", "1,2,3", "a.o", nullptr));
} }
TEST_F(DarwinLdParserTest, bundleLoader) { TEST_F(DarwinLdParserTest, bundleLoader) {
EXPECT_FALSE( EXPECT_TRUE(
parse("ld", "-bundle", "-bundle_loader", "/bin/ls", "a.o", nullptr)); parse("ld", "-bundle", "-bundle_loader", "/bin/ls", "a.o", nullptr));
EXPECT_EQ(_context.bundleLoader(), "/bin/ls"); EXPECT_EQ(_context.bundleLoader(), "/bin/ls");
} }
TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) { TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) {
EXPECT_TRUE(parse("ld", "-bundle_loader", "/bin/ls", "a.o", nullptr)); EXPECT_FALSE(parse("ld", "-bundle_loader", "/bin/ls", "a.o", nullptr));
} }
TEST_F(DarwinLdParserTest, deadStrippableDylib) { TEST_F(DarwinLdParserTest, deadStrippableDylib) {
EXPECT_FALSE( EXPECT_TRUE(
parse("ld", "-dylib", "-mark_dead_strippable_dylib", "a.o", nullptr)); parse("ld", "-dylib", "-mark_dead_strippable_dylib", "a.o", nullptr));
EXPECT_EQ(true, _context.deadStrippableDylib()); EXPECT_EQ(true, _context.deadStrippableDylib());
} }
TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) { TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
EXPECT_TRUE(parse("ld", "-mark_dead_strippable_dylib", "a.o", nullptr)); EXPECT_FALSE(parse("ld", "-mark_dead_strippable_dylib", "a.o", nullptr));
} }
} // end anonymous namespace } // end anonymous namespace

View File

@ -28,13 +28,13 @@ protected:
}; };
TEST_F(GnuLdParserTest, Empty) { TEST_F(GnuLdParserTest, Empty) {
EXPECT_TRUE(parse("ld", nullptr)); EXPECT_FALSE(parse("ld", nullptr));
EXPECT_EQ(linkingContext(), nullptr); EXPECT_EQ(linkingContext(), nullptr);
EXPECT_EQ("No input files\n", errorMessage()); EXPECT_EQ("No input files\n", errorMessage());
} }
TEST_F(GnuLdParserTest, Basic) { TEST_F(GnuLdParserTest, Basic) {
EXPECT_FALSE(parse("ld", "infile.o", nullptr)); EXPECT_TRUE(parse("ld", "infile.o", nullptr));
EXPECT_NE(linkingContext(), nullptr); EXPECT_NE(linkingContext(), nullptr);
EXPECT_EQ("a.out", linkingContext()->outputPath()); EXPECT_EQ("a.out", linkingContext()->outputPath());
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
@ -44,8 +44,8 @@ TEST_F(GnuLdParserTest, Basic) {
} }
TEST_F(GnuLdParserTest, ManyOptions) { TEST_F(GnuLdParserTest, ManyOptions) {
EXPECT_FALSE(parse("ld", "-entry", "_start", "-o", "outfile", EXPECT_TRUE(parse("ld", "-entry", "_start", "-o", "outfile",
"--output-filetype=yaml", "infile.o", nullptr)); "--output-filetype=yaml", "infile.o", nullptr));
EXPECT_NE(linkingContext(), nullptr); EXPECT_NE(linkingContext(), nullptr);
EXPECT_EQ("outfile", linkingContext()->outputPath()); EXPECT_EQ("outfile", linkingContext()->outputPath());
EXPECT_EQ("_start", linkingContext()->entrySymbolName()); EXPECT_EQ("_start", linkingContext()->entrySymbolName());

View File

@ -31,8 +31,8 @@ protected:
}; };
TEST_F(WinLinkParserTest, Basic) { TEST_F(WinLinkParserTest, Basic) {
EXPECT_FALSE(parse("link.exe", "/subsystem:console", "/out:a.exe", EXPECT_TRUE(parse("link.exe", "/subsystem:console", "/out:a.exe",
"-entry:start", "a.obj", "b.obj", "c.obj", nullptr)); "-entry:start", "a.obj", "b.obj", "c.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem());
EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _context.getMachineType()); EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _context.getMachineType());
EXPECT_EQ("a.exe", _context.outputPath()); EXPECT_EQ("a.exe", _context.outputPath());
@ -64,8 +64,8 @@ TEST_F(WinLinkParserTest, Basic) {
} }
TEST_F(WinLinkParserTest, StartsWithHyphen) { TEST_F(WinLinkParserTest, StartsWithHyphen) {
EXPECT_FALSE(parse("link.exe", "-subsystem:console", "-out:a.exe", EXPECT_TRUE(
"a.obj", nullptr)); parse("link.exe", "-subsystem:console", "-out:a.exe", "a.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem());
EXPECT_EQ("a.exe", _context.outputPath()); EXPECT_EQ("a.exe", _context.outputPath());
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
@ -73,8 +73,8 @@ TEST_F(WinLinkParserTest, StartsWithHyphen) {
} }
TEST_F(WinLinkParserTest, UppercaseOption) { TEST_F(WinLinkParserTest, UppercaseOption) {
EXPECT_FALSE(parse("link.exe", "/SUBSYSTEM:CONSOLE", "/OUT:a.exe", "a.obj", EXPECT_TRUE(
nullptr)); parse("link.exe", "/SUBSYSTEM:CONSOLE", "/OUT:a.exe", "a.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem());
EXPECT_EQ("a.exe", _context.outputPath()); EXPECT_EQ("a.exe", _context.outputPath());
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
@ -82,14 +82,14 @@ TEST_F(WinLinkParserTest, UppercaseOption) {
} }
TEST_F(WinLinkParserTest, Mllvm) { TEST_F(WinLinkParserTest, Mllvm) {
EXPECT_FALSE(parse("link.exe", "/mllvm:-debug", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/mllvm:-debug", "a.obj", nullptr));
const std::vector<const char *> &options = _context.llvmOptions(); const std::vector<const char *> &options = _context.llvmOptions();
EXPECT_EQ(1U, options.size()); EXPECT_EQ(1U, options.size());
EXPECT_STREQ("-debug", options[0]); EXPECT_STREQ("-debug", options[0]);
} }
TEST_F(WinLinkParserTest, NoInputFiles) { TEST_F(WinLinkParserTest, NoInputFiles) {
EXPECT_TRUE(parse("link.exe", nullptr)); EXPECT_FALSE(parse("link.exe", nullptr));
EXPECT_EQ("No input files\n", errorMessage()); EXPECT_EQ("No input files\n", errorMessage());
} }
@ -98,7 +98,7 @@ TEST_F(WinLinkParserTest, NoInputFiles) {
// //
TEST_F(WinLinkParserTest, NoFileExtension) { TEST_F(WinLinkParserTest, NoFileExtension) {
EXPECT_FALSE(parse("link.exe", "foo", "bar", nullptr)); EXPECT_TRUE(parse("link.exe", "foo", "bar", nullptr));
EXPECT_EQ("foo.exe", _context.outputPath()); EXPECT_EQ("foo.exe", _context.outputPath());
EXPECT_EQ(2, inputFileCount()); EXPECT_EQ(2, inputFileCount());
EXPECT_EQ("foo.obj", inputFile(0)); EXPECT_EQ("foo.obj", inputFile(0));
@ -106,15 +106,15 @@ TEST_F(WinLinkParserTest, NoFileExtension) {
} }
TEST_F(WinLinkParserTest, NonStandardFileExtension) { TEST_F(WinLinkParserTest, NonStandardFileExtension) {
EXPECT_FALSE(parse("link.exe", "foo.o", nullptr)); EXPECT_TRUE(parse("link.exe", "foo.o", nullptr));
EXPECT_EQ("foo.exe", _context.outputPath()); EXPECT_EQ("foo.exe", _context.outputPath());
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
EXPECT_EQ("foo.o", inputFile(0)); EXPECT_EQ("foo.o", inputFile(0));
} }
TEST_F(WinLinkParserTest, Libpath) { TEST_F(WinLinkParserTest, Libpath) {
EXPECT_FALSE(parse("link.exe", "/libpath:dir1", "/libpath:dir2", EXPECT_TRUE(
"a.obj", nullptr)); parse("link.exe", "/libpath:dir1", "/libpath:dir2", "a.obj", nullptr));
const std::vector<StringRef> &paths = _context.getInputSearchPaths(); const std::vector<StringRef> &paths = _context.getInputSearchPaths();
EXPECT_EQ(2U, paths.size()); EXPECT_EQ(2U, paths.size());
EXPECT_EQ("dir1", paths[0]); EXPECT_EQ("dir1", paths[0]);
@ -126,100 +126,100 @@ TEST_F(WinLinkParserTest, Libpath) {
// //
TEST_F(WinLinkParserTest, MachineX86) { TEST_F(WinLinkParserTest, MachineX86) {
EXPECT_FALSE(parse("link.exe", "/machine:x86", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/machine:x86", "a.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _context.getMachineType()); EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _context.getMachineType());
} }
TEST_F(WinLinkParserTest, MachineX64) { TEST_F(WinLinkParserTest, MachineX64) {
EXPECT_TRUE(parse("link.exe", "/machine:x64", "a.obj", nullptr)); EXPECT_FALSE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
EXPECT_TRUE(StringRef(errorMessage()).startswith( EXPECT_TRUE(StringRef(errorMessage())
"Machine type other than x86 is not supported")); .startswith("Machine type other than x86 is not supported"));
} }
TEST_F(WinLinkParserTest, MajorImageVersion) { TEST_F(WinLinkParserTest, MajorImageVersion) {
EXPECT_FALSE(parse("link.exe", "/version:7", "foo.o", nullptr)); EXPECT_TRUE(parse("link.exe", "/version:7", "foo.o", nullptr));
EXPECT_EQ(7, _context.getImageVersion().majorVersion); EXPECT_EQ(7, _context.getImageVersion().majorVersion);
EXPECT_EQ(0, _context.getImageVersion().minorVersion); EXPECT_EQ(0, _context.getImageVersion().minorVersion);
} }
TEST_F(WinLinkParserTest, MajorMinorImageVersion) { TEST_F(WinLinkParserTest, MajorMinorImageVersion) {
EXPECT_FALSE(parse("link.exe", "/version:72.35", "foo.o", nullptr)); EXPECT_TRUE(parse("link.exe", "/version:72.35", "foo.o", nullptr));
EXPECT_EQ(72, _context.getImageVersion().majorVersion); EXPECT_EQ(72, _context.getImageVersion().majorVersion);
EXPECT_EQ(35, _context.getImageVersion().minorVersion); EXPECT_EQ(35, _context.getImageVersion().minorVersion);
} }
TEST_F(WinLinkParserTest, MinMajorOSVersion) { TEST_F(WinLinkParserTest, MinMajorOSVersion) {
EXPECT_FALSE(parse("link.exe", "/subsystem:windows,3", "foo.o", nullptr)); EXPECT_TRUE(parse("link.exe", "/subsystem:windows,3", "foo.o", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem());
EXPECT_EQ(3, _context.getMinOSVersion().majorVersion); EXPECT_EQ(3, _context.getMinOSVersion().majorVersion);
EXPECT_EQ(0, _context.getMinOSVersion().minorVersion); EXPECT_EQ(0, _context.getMinOSVersion().minorVersion);
} }
TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) { TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) {
EXPECT_FALSE(parse("link.exe", "/subsystem:windows,3.1", "foo.o", nullptr)); EXPECT_TRUE(parse("link.exe", "/subsystem:windows,3.1", "foo.o", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem());
EXPECT_EQ(3, _context.getMinOSVersion().majorVersion); EXPECT_EQ(3, _context.getMinOSVersion().majorVersion);
EXPECT_EQ(1, _context.getMinOSVersion().minorVersion); EXPECT_EQ(1, _context.getMinOSVersion().minorVersion);
} }
TEST_F(WinLinkParserTest, Base) { TEST_F(WinLinkParserTest, Base) {
EXPECT_FALSE(parse("link.exe", "/base:8388608", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/base:8388608", "a.obj", nullptr));
EXPECT_EQ(0x800000U, _context.getBaseAddress()); EXPECT_EQ(0x800000U, _context.getBaseAddress());
} }
TEST_F(WinLinkParserTest, InvalidBase) { TEST_F(WinLinkParserTest, InvalidBase) {
EXPECT_TRUE(parse("link.exe", "/base:1234", "a.obj", nullptr)); EXPECT_FALSE(parse("link.exe", "/base:1234", "a.obj", nullptr));
EXPECT_TRUE(StringRef(errorMessage()).startswith( EXPECT_TRUE(StringRef(errorMessage())
"Base address have to be multiple of 64K")); .startswith("Base address have to be multiple of 64K"));
} }
TEST_F(WinLinkParserTest, StackReserve) { TEST_F(WinLinkParserTest, StackReserve) {
EXPECT_FALSE(parse("link.exe", "/stack:8192", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/stack:8192", "a.obj", nullptr));
EXPECT_EQ(8192U, _context.getStackReserve()); EXPECT_EQ(8192U, _context.getStackReserve());
EXPECT_EQ(4096U, _context.getStackCommit()); EXPECT_EQ(4096U, _context.getStackCommit());
} }
TEST_F(WinLinkParserTest, StackReserveAndCommit) { TEST_F(WinLinkParserTest, StackReserveAndCommit) {
EXPECT_FALSE(parse("link.exe", "/stack:16384,8192", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/stack:16384,8192", "a.obj", nullptr));
EXPECT_EQ(16384U, _context.getStackReserve()); EXPECT_EQ(16384U, _context.getStackReserve());
EXPECT_EQ(8192U, _context.getStackCommit()); EXPECT_EQ(8192U, _context.getStackCommit());
} }
TEST_F(WinLinkParserTest, InvalidStackSize) { TEST_F(WinLinkParserTest, InvalidStackSize) {
EXPECT_TRUE(parse("link.exe", "/stack:8192,16384", "a.obj", nullptr)); EXPECT_FALSE(parse("link.exe", "/stack:8192,16384", "a.obj", nullptr));
EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid stack size")); EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid stack size"));
} }
TEST_F(WinLinkParserTest, HeapReserve) { TEST_F(WinLinkParserTest, HeapReserve) {
EXPECT_FALSE(parse("link.exe", "/heap:8192", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/heap:8192", "a.obj", nullptr));
EXPECT_EQ(8192U, _context.getHeapReserve()); EXPECT_EQ(8192U, _context.getHeapReserve());
EXPECT_EQ(4096U, _context.getHeapCommit()); EXPECT_EQ(4096U, _context.getHeapCommit());
} }
TEST_F(WinLinkParserTest, HeapReserveAndCommit) { TEST_F(WinLinkParserTest, HeapReserveAndCommit) {
EXPECT_FALSE(parse("link.exe", "/heap:16384,8192", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/heap:16384,8192", "a.obj", nullptr));
EXPECT_EQ(16384U, _context.getHeapReserve()); EXPECT_EQ(16384U, _context.getHeapReserve());
EXPECT_EQ(8192U, _context.getHeapCommit()); EXPECT_EQ(8192U, _context.getHeapCommit());
} }
TEST_F(WinLinkParserTest, InvalidHeapSize) { TEST_F(WinLinkParserTest, InvalidHeapSize) {
EXPECT_TRUE(parse("link.exe", "/heap:8192,16384", "a.obj", nullptr)); EXPECT_FALSE(parse("link.exe", "/heap:8192,16384", "a.obj", nullptr));
EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid heap size")); EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid heap size"));
} }
TEST_F(WinLinkParserTest, SectionAlignment) { TEST_F(WinLinkParserTest, SectionAlignment) {
EXPECT_FALSE(parse("link.exe", "/align:8192", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/align:8192", "a.obj", nullptr));
EXPECT_EQ(8192U, _context.getSectionAlignment()); EXPECT_EQ(8192U, _context.getSectionAlignment());
} }
TEST_F(WinLinkParserTest, InvalidAlignment) { TEST_F(WinLinkParserTest, InvalidAlignment) {
EXPECT_TRUE(parse("link.exe", "/align:1000", "a.obj", nullptr)); EXPECT_FALSE(parse("link.exe", "/align:1000", "a.obj", nullptr));
EXPECT_EQ("Section alignment must be a power of 2, but got 1000\n", EXPECT_EQ("Section alignment must be a power of 2, but got 1000\n",
errorMessage()); errorMessage());
} }
TEST_F(WinLinkParserTest, Include) { TEST_F(WinLinkParserTest, Include) {
EXPECT_FALSE(parse("link.exe", "/include:foo", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/include:foo", "a.out", nullptr));
auto symbols = _context.initialUndefinedSymbols(); auto symbols = _context.initialUndefinedSymbols();
EXPECT_FALSE(symbols.empty()); EXPECT_FALSE(symbols.empty());
EXPECT_EQ("foo", symbols[0]); EXPECT_EQ("foo", symbols[0]);
@ -232,8 +232,8 @@ TEST_F(WinLinkParserTest, Include) {
// //
TEST_F(WinLinkParserTest, DefaultLib) { TEST_F(WinLinkParserTest, DefaultLib) {
EXPECT_FALSE(parse("link.exe", "/defaultlib:user32.lib", EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "a.obj", nullptr)); "/defaultlib:kernel32", "a.obj", nullptr));
EXPECT_EQ(3, inputFileCount()); EXPECT_EQ(3, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0)); EXPECT_EQ("a.obj", inputFile(0));
EXPECT_EQ("user32.lib", inputFile(1)); EXPECT_EQ("user32.lib", inputFile(1));
@ -241,18 +241,17 @@ TEST_F(WinLinkParserTest, DefaultLib) {
} }
TEST_F(WinLinkParserTest, NoDefaultLib) { TEST_F(WinLinkParserTest, NoDefaultLib) {
EXPECT_FALSE(parse("link.exe", "/defaultlib:user32.lib", EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "/nodefaultlib:user32.lib", "/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",
"a.obj", nullptr)); nullptr));
EXPECT_EQ(2, inputFileCount()); EXPECT_EQ(2, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0)); EXPECT_EQ("a.obj", inputFile(0));
EXPECT_EQ("kernel32.lib", inputFile(1)); EXPECT_EQ("kernel32.lib", inputFile(1));
} }
TEST_F(WinLinkParserTest, NoDefaultLibAll) { TEST_F(WinLinkParserTest, NoDefaultLibAll) {
EXPECT_FALSE(parse("link.exe", "/defaultlib:user32.lib", EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "/nodefaultlib", "a.obj", "/defaultlib:kernel32", "/nodefaultlib", "a.obj", nullptr));
nullptr));
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0)); EXPECT_EQ("a.obj", inputFile(0));
} }
@ -262,93 +261,93 @@ TEST_F(WinLinkParserTest, NoDefaultLibAll) {
// //
TEST_F(WinLinkParserTest, Force) { TEST_F(WinLinkParserTest, Force) {
EXPECT_FALSE(parse("link.exe", "/force", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/force", "a.obj", nullptr));
EXPECT_TRUE(_context.allowRemainingUndefines()); EXPECT_TRUE(_context.allowRemainingUndefines());
} }
TEST_F(WinLinkParserTest, ForceUnresolved) { TEST_F(WinLinkParserTest, ForceUnresolved) {
EXPECT_FALSE(parse("link.exe", "/force:unresolved", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/force:unresolved", "a.obj", nullptr));
EXPECT_TRUE(_context.allowRemainingUndefines()); EXPECT_TRUE(_context.allowRemainingUndefines());
} }
TEST_F(WinLinkParserTest, NoNxCompat) { TEST_F(WinLinkParserTest, NoNxCompat) {
EXPECT_FALSE(parse("link.exe", "/nxcompat:no", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/nxcompat:no", "a.obj", nullptr));
EXPECT_FALSE(_context.isNxCompat()); EXPECT_FALSE(_context.isNxCompat());
} }
TEST_F(WinLinkParserTest, LargeAddressAware) { TEST_F(WinLinkParserTest, LargeAddressAware) {
EXPECT_FALSE(parse("link.exe", "/largeaddressaware", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/largeaddressaware", "a.obj", nullptr));
EXPECT_TRUE(_context.getLargeAddressAware()); EXPECT_TRUE(_context.getLargeAddressAware());
} }
TEST_F(WinLinkParserTest, NoLargeAddressAware) { TEST_F(WinLinkParserTest, NoLargeAddressAware) {
EXPECT_FALSE(parse("link.exe", "/largeaddressaware:no", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/largeaddressaware:no", "a.obj", nullptr));
EXPECT_FALSE(_context.getLargeAddressAware()); EXPECT_FALSE(_context.getLargeAddressAware());
} }
TEST_F(WinLinkParserTest, AllowBind) { TEST_F(WinLinkParserTest, AllowBind) {
EXPECT_FALSE(parse("link.exe", "/allowbind", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/allowbind", "a.obj", nullptr));
EXPECT_TRUE(_context.getAllowBind()); EXPECT_TRUE(_context.getAllowBind());
} }
TEST_F(WinLinkParserTest, NoAllowBind) { TEST_F(WinLinkParserTest, NoAllowBind) {
EXPECT_FALSE(parse("link.exe", "/allowbind:no", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/allowbind:no", "a.obj", nullptr));
EXPECT_FALSE(_context.getAllowBind()); EXPECT_FALSE(_context.getAllowBind());
} }
TEST_F(WinLinkParserTest, AllowIsolation) { TEST_F(WinLinkParserTest, AllowIsolation) {
EXPECT_FALSE(parse("link.exe", "/allowisolation", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/allowisolation", "a.obj", nullptr));
EXPECT_TRUE(_context.getAllowIsolation()); EXPECT_TRUE(_context.getAllowIsolation());
} }
TEST_F(WinLinkParserTest, NoAllowIsolation) { TEST_F(WinLinkParserTest, NoAllowIsolation) {
EXPECT_FALSE(parse("link.exe", "/allowisolation:no", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/allowisolation:no", "a.obj", nullptr));
EXPECT_FALSE(_context.getAllowIsolation()); EXPECT_FALSE(_context.getAllowIsolation());
} }
TEST_F(WinLinkParserTest, SwapRunFromCD) { TEST_F(WinLinkParserTest, SwapRunFromCD) {
EXPECT_FALSE(parse("link.exe", "/swaprun:cd", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/swaprun:cd", "a.obj", nullptr));
EXPECT_TRUE(_context.getSwapRunFromCD()); EXPECT_TRUE(_context.getSwapRunFromCD());
} }
TEST_F(WinLinkParserTest, SwapRunFromNet) { TEST_F(WinLinkParserTest, SwapRunFromNet) {
EXPECT_FALSE(parse("link.exe", "/swaprun:net", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/swaprun:net", "a.obj", nullptr));
EXPECT_TRUE(_context.getSwapRunFromNet()); EXPECT_TRUE(_context.getSwapRunFromNet());
} }
TEST_F(WinLinkParserTest, Debug) { TEST_F(WinLinkParserTest, Debug) {
EXPECT_FALSE(parse("link.exe", "/debug", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/debug", "a.out", nullptr));
EXPECT_FALSE(_context.deadStrip()); EXPECT_FALSE(_context.deadStrip());
} }
TEST_F(WinLinkParserTest, Fixed) { TEST_F(WinLinkParserTest, Fixed) {
EXPECT_FALSE(parse("link.exe", "/fixed", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/fixed", "a.out", nullptr));
EXPECT_FALSE(_context.getBaseRelocationEnabled()); EXPECT_FALSE(_context.getBaseRelocationEnabled());
EXPECT_FALSE(_context.getDynamicBaseEnabled()); EXPECT_FALSE(_context.getDynamicBaseEnabled());
} }
TEST_F(WinLinkParserTest, NoFixed) { TEST_F(WinLinkParserTest, NoFixed) {
EXPECT_FALSE(parse("link.exe", "/fixed:no", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/fixed:no", "a.out", nullptr));
EXPECT_TRUE(_context.getBaseRelocationEnabled()); EXPECT_TRUE(_context.getBaseRelocationEnabled());
} }
TEST_F(WinLinkParserTest, TerminalServerAware) { TEST_F(WinLinkParserTest, TerminalServerAware) {
EXPECT_FALSE(parse("link.exe", "/tsaware", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/tsaware", "a.out", nullptr));
EXPECT_TRUE(_context.isTerminalServerAware()); EXPECT_TRUE(_context.isTerminalServerAware());
} }
TEST_F(WinLinkParserTest, NoTerminalServerAware) { TEST_F(WinLinkParserTest, NoTerminalServerAware) {
EXPECT_FALSE(parse("link.exe", "/tsaware:no", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/tsaware:no", "a.out", nullptr));
EXPECT_FALSE(_context.isTerminalServerAware()); EXPECT_FALSE(_context.isTerminalServerAware());
} }
TEST_F(WinLinkParserTest, DynamicBase) { TEST_F(WinLinkParserTest, DynamicBase) {
EXPECT_FALSE(parse("link.exe", "/dynamicbase", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/dynamicbase", "a.out", nullptr));
EXPECT_TRUE(_context.getDynamicBaseEnabled()); EXPECT_TRUE(_context.getDynamicBaseEnabled());
} }
TEST_F(WinLinkParserTest, NoDynamicBase) { TEST_F(WinLinkParserTest, NoDynamicBase) {
EXPECT_FALSE(parse("link.exe", "/dynamicbase:no", "a.out", nullptr)); EXPECT_TRUE(parse("link.exe", "/dynamicbase:no", "a.out", nullptr));
EXPECT_FALSE(_context.getDynamicBaseEnabled()); EXPECT_FALSE(_context.getDynamicBaseEnabled());
} }
@ -357,14 +356,14 @@ TEST_F(WinLinkParserTest, NoDynamicBase) {
// //
TEST_F(WinLinkParserTest, FailIfMismatch_Match) { TEST_F(WinLinkParserTest, FailIfMismatch_Match) {
EXPECT_FALSE(parse("link.exe", "/failifmismatch:foo=bar", EXPECT_TRUE(parse("link.exe", "/failifmismatch:foo=bar",
"/failifmismatch:foo=bar", "/failifmismatch:abc=def", "/failifmismatch:foo=bar", "/failifmismatch:abc=def",
"a.out", nullptr)); "a.out", nullptr));
} }
TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) { TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) {
EXPECT_TRUE(parse("link.exe", "/failifmismatch:foo=bar", EXPECT_FALSE(parse("link.exe", "/failifmismatch:foo=bar",
"/failifmismatch:foo=baz", "a.out", nullptr)); "/failifmismatch:foo=baz", "a.out", nullptr));
} }
// //
@ -374,11 +373,11 @@ TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) {
TEST_F(WinLinkParserTest, Ignore) { TEST_F(WinLinkParserTest, Ignore) {
// There are some no-op command line options that are recognized for // There are some no-op command line options that are recognized for
// compatibility with link.exe. // compatibility with link.exe.
EXPECT_FALSE(parse("link.exe", "/nologo", "/errorreport:prompt", EXPECT_TRUE(parse("link.exe", "/nologo", "/errorreport:prompt",
"/incremental", "/incremental:no", "/delay:unload", "/incremental", "/incremental:no", "/delay:unload",
"/delayload:user32", "/pdb:foo", "/pdbaltpath:bar", "/delayload:user32", "/pdb:foo", "/pdbaltpath:bar",
"/verbose", "/verbose:icf", "/wx", "/wx:no", "a.obj", "/verbose", "/verbose:icf", "/wx", "/wx:no", "a.obj",
nullptr)); nullptr));
EXPECT_EQ("", errorMessage()); EXPECT_EQ("", errorMessage());
EXPECT_EQ(1, inputFileCount()); EXPECT_EQ(1, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0)); EXPECT_EQ("a.obj", inputFile(0));
@ -389,8 +388,8 @@ TEST_F(WinLinkParserTest, Ignore) {
// //
TEST_F(WinLinkParserTest, DashDash) { TEST_F(WinLinkParserTest, DashDash) {
EXPECT_FALSE(parse("link.exe", "/subsystem:console", "/out:a.exe", EXPECT_TRUE(parse("link.exe", "/subsystem:console", "/out:a.exe", "a.obj",
"a.obj", "--", "b.obj", "-c.obj", nullptr)); "--", "b.obj", "-c.obj", nullptr));
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem()); EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _context.getSubsystem());
EXPECT_EQ("a.exe", _context.outputPath()); EXPECT_EQ("a.exe", _context.outputPath());
EXPECT_EQ(3, inputFileCount()); EXPECT_EQ(3, inputFileCount());
@ -404,12 +403,12 @@ TEST_F(WinLinkParserTest, DashDash) {
// //
TEST_F(WinLinkParserTest, DefEntryNameConsole) { TEST_F(WinLinkParserTest, DefEntryNameConsole) {
EXPECT_FALSE(parse("link.exe", "/subsystem:console", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/subsystem:console", "a.obj", nullptr));
EXPECT_EQ("_mainCRTStartup", _context.entrySymbolName()); EXPECT_EQ("_mainCRTStartup", _context.entrySymbolName());
} }
TEST_F(WinLinkParserTest, DefEntryNameWindows) { TEST_F(WinLinkParserTest, DefEntryNameWindows) {
EXPECT_FALSE(parse("link.exe", "/subsystem:windows", "a.obj", nullptr)); EXPECT_TRUE(parse("link.exe", "/subsystem:windows", "a.obj", nullptr));
EXPECT_EQ("_WinMainCRTStartup", _context.entrySymbolName()); EXPECT_EQ("_WinMainCRTStartup", _context.entrySymbolName());
} }