From 7668182e445b407ca7749b6d96744f880889b19f Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 21 Mar 2017 00:12:51 +0000 Subject: [PATCH] [COFF] Don't let /def override /out filename Summary: This also delays setting the output filename based on the first input argument until after processing /def. Fixes PR32354 Reviewers: ruiu, pcc Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D31152 llvm-svn: 298327 --- lld/COFF/Driver.cpp | 9 ++++++--- lld/COFF/ModuleDef.cpp | 22 +++++++++++++++------- lld/test/COFF/def-name.test | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 lld/test/COFF/def-name.test diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 8b5eb40ec36d..3bf9b7613500 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -137,9 +137,6 @@ void LinkerDriver::enqueuePath(StringRef Path) { fatal(MBOrErr.second, "could not open " + PathStr); Driver->addBuffer(std::move(MBOrErr.first)); }); - - if (Config->OutputFile == "") - Config->OutputFile = getOutputPath(Path); } void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, @@ -887,6 +884,12 @@ void LinkerDriver::link(ArrayRef ArgsArr) { } } + // Set default image name if neither /out or /def set it. + if (Config->OutputFile.empty()) { + Config->OutputFile = + getOutputPath((*Args.filtered_begin(OPT_INPUT))->getValue()); + } + // Set default image base if /base is not given. if (Config->ImageBase == uint64_t(-1)) Config->ImageBase = getDefaultImageBase(); diff --git a/lld/COFF/ModuleDef.cpp b/lld/COFF/ModuleDef.cpp index a273b6f535db..c9a40ac5ab8c 100644 --- a/lld/COFF/ModuleDef.cpp +++ b/lld/COFF/ModuleDef.cpp @@ -163,17 +163,25 @@ private: case KwHeapsize: parseNumbers(&Config->HeapReserve, &Config->HeapCommit); return; - case KwLibrary: - parseName(&Config->OutputFile, &Config->ImageBase); - if (!StringRef(Config->OutputFile).endswith_lower(".dll")) - Config->OutputFile += ".dll"; - return; case KwStacksize: parseNumbers(&Config->StackReserve, &Config->StackCommit); return; - case KwName: - parseName(&Config->OutputFile, &Config->ImageBase); + case KwLibrary: + case KwName: { + bool IsDll = Tok.K == KwLibrary; // Check before parseName. + std::string Name; + parseName(&Name, &Config->ImageBase); + + // Append the appropriate file extension if not already present. + StringRef Ext = IsDll ? ".dll" : ".exe"; + if (!StringRef(Name).endswith_lower(Ext)) + Name += Ext; + + // Set the output file, but don't override /out if it was already passed. + if (Config->OutputFile.empty()) + Config->OutputFile = Name; return; + } case KwVersion: parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion); return; diff --git a/lld/test/COFF/def-name.test b/lld/test/COFF/def-name.test new file mode 100644 index 000000000000..c48424a1bff0 --- /dev/null +++ b/lld/test/COFF/def-name.test @@ -0,0 +1,28 @@ +# REQUIRES: winres + +# RUN: rm -rf %t +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: yaml2obj < %p/Inputs/ret42.yaml > in.obj + +# RUN: lld-link /entry:main in.obj +# RUN: lld-link /entry:main /dll in.obj + +# RUN: echo -e "NAME foo\n" > fooexe.def +# RUN: echo -e "LIBRARY foo\n" > foodll.def +# RUN: lld-link /entry:main /def:fooexe.def in.obj +# RUN: lld-link /entry:main /def:foodll.def /dll in.obj + +# RUN: lld-link /entry:main /out:bar.exe /def:fooexe.def in.obj +# RUN: lld-link /entry:main /out:bar.dll /def:foodll.def /dll in.obj + +# RUN: llvm-readobj in.exe | FileCheck %s +# RUN: llvm-readobj in.dll | FileCheck %s + +# RUN: llvm-readobj foo.exe | FileCheck %s +# RUN: llvm-readobj foo.dll | FileCheck %s + +# RUN: llvm-readobj bar.exe | FileCheck %s +# RUN: llvm-readobj bar.dll | FileCheck %s + +CHECK: File: