- try to clean this up
http://reviews.llvm.org/D3771
Files:
include/clang/Driver/Options.td
lib/Driver/Driver.cpp
test/Driver/cl-outputs.c
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1237,7 +1237,8 @@
HelpText<"Disable standard #include directories for the C++ standard library">;
def nostdlib : Flag<["-"], "nostdlib">;
def object : Flag<["-"], "object">;
-def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option]>,
+def o : JoinedOrSeparate<["-"], "o">,
+ Flags<[DriverOption, RenderAsInput, CC1Option, CoreOption]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">;
def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>;
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -1606,17 +1606,41 @@
bool AtTopLevel,
bool MultipleArchs) const {
llvm::PrettyStackTraceString CrashInfo("Computing output path");
- // Output to a user requested destination?
- if (AtTopLevel && !isa<DsymutilJobAction>(JA) &&
- !isa<VerifyJobAction>(JA)) {
- if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
- return C.addResultFile(FinalOutput->getValue(), &JA);
+ StringRef BaseName = llvm::sys::path::filename(BaseInput);
+
+ if (!isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
+ // Only apply -o to the output of the top level action.
+ options::ID MaybeDashO = AtTopLevel ? options::OPT_o : options::OPT_INVALID;
+ // Find the last clang-cl output argument that is relevant to the current job.
+ options::ID MaybeCLOpt;
+ switch (JA.getType()) {
+ case types::TY_PP_Asm: MaybeCLOpt = options::OPT__SLASH_Fa; break;
+ case types::TY_Object: MaybeCLOpt = options::OPT__SLASH_Fo; break;
+ case types::TY_Image: MaybeCLOpt = options::OPT__SLASH_Fe; break;
+ default: MaybeCLOpt = options::OPT_INVALID; break;
+ }
+ Arg *OutputArg = C.getArgs().getLastArg(MaybeDashO, MaybeCLOpt);
+
+ // If we had an explicit output argument, honor it.
+ if (OutputArg) {
+ Option Op = OutputArg->getOption();
+ const char *NamedOutput;
+ if (Op.matches(options::OPT__SLASH_Fa) ||
+ Op.matches(options::OPT__SLASH_Fo) ||
+ Op.matches(options::OPT__SLASH_Fe)) {
+ NamedOutput = MakeCLOutputFilename(C.getArgs(), OutputArg->getValue(),
+ BaseName, JA.getType());
+ } else {
+ assert(Op.matches(options::OPT_o));
+ NamedOutput = OutputArg->getValue();
+ }
+ return C.addResultFile(NamedOutput, &JA);
+ }
}
// For /P, preprocess to file named after BaseInput.
if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
assert(AtTopLevel && isa<PreprocessJobAction>(JA));
- StringRef BaseName = llvm::sys::path::filename(BaseInput);
return C.addResultFile(MakeCLOutputFilename(C.getArgs(), "", BaseName,
types::TY_PP_C), &JA);
}
@@ -1627,19 +1651,13 @@
return "-";
// Is this the assembly listing for /FA?
- if (JA.getType() == types::TY_PP_Asm &&
- (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
- C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
- // Use /Fa and the input filename to determine the asm file name.
- StringRef BaseName = llvm::sys::path::filename(BaseInput);
- StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
- return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName,
- JA.getType()), &JA);
+ if (C.getArgs().hasArg(options::OPT__SLASH_FA)) {
+ return C.addResultFile(
+ MakeCLOutputFilename(C.getArgs(), "", BaseName, JA.getType()), &JA);
}
// Output to a temporary file?
- if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
- !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
+ if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) ||
CCGenDiagnostics) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
@@ -1649,31 +1667,14 @@
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
- SmallString<128> BasePath(BaseInput);
- StringRef BaseName;
-
// Dsymutil actions should use the full path.
if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))
- BaseName = BasePath;
- else
- BaseName = llvm::sys::path::filename(BasePath);
+ BaseName = BaseInput;
// Determine what the derived output name should be.
const char *NamedOutput;
- if (JA.getType() == types::TY_Object &&
- C.getArgs().hasArg(options::OPT__SLASH_Fo)) {
- // The /Fo flag decides the object filename.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue();
- NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
- types::TY_Object);
- } else if (JA.getType() == types::TY_Image &&
- C.getArgs().hasArg(options::OPT__SLASH_Fe)) {
- // The /Fe flag names the linked file.
- StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue();
- NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
- types::TY_Image);
- } else if (JA.getType() == types::TY_Image) {
+ if (JA.getType() == types::TY_Image) {
if (IsCLMode()) {
// clang-cl uses BaseName for the executable name.
NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
@@ -1725,6 +1726,7 @@
// As an annoying special case, PCH generation doesn't strip the pathname.
if (JA.getType() == types::TY_PCH) {
+ SmallString<128> BasePath(BaseInput);
llvm::sys::path::remove_filename(BasePath);
if (BasePath.empty())
BasePath = NamedOutput;
Index: test/Driver/cl-outputs.c
===================================================================
--- test/Driver/cl-outputs.c
+++ test/Driver/cl-outputs.c
@@ -109,3 +109,31 @@
// RUN: %clang_cl /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s
// P: "-E"
// P: "-o" "cl-outputs.i"
+
+// Last arg wins between -o and -Fo for simple compilation.
+// RUN: %clang_cl -c -o t1.obj -Fot2.obj -### -- %s 2>&1 | FileCheck %s -check-prefix o_Fo
+// o_Fo: "-cc1"
+// o_Fo: "-o" "t2.obj"
+// RUN: %clang_cl -c -Fot1.obj -o t2.obj -### -- %s 2>&1 | FileCheck %s -check-prefix Fo_o
+// Fo_o: "-cc1"
+// Fo_o: "-o" "t2.obj"
+
+// Last arg wins between -o and -Fe for linked images.
+// RUN: %clang_cl -o t1.exe -Fet2.exe -### -- %s 2>&1 | FileCheck %s -check-prefix o_Fe
+// o_Fe: "-cc1"
+// o_Fe: link.exe
+// o_Fe: "-out:t2.exe"
+// RUN: %clang_cl -Fet1.exe -o t2.exe -### -- %s 2>&1 | FileCheck %s -check-prefix Fe_o
+// Fe_o: "-cc1"
+// Fe_o: link.exe
+// Fe_o: "-out:t2.exe"
+
+// -Fo and -Fa work for intermediate outputs.
+// RUN: %clang_cl -Fat.s -Fot.obj -o t.exe -### -- %s 2>&1 | FileCheck %s -check-prefix Fa_Fo_o
+// Fa_Fo_o: "-cc1"
+// Fa_Fo_o: "-S"
+// Fa_Fo_o: "-o" "t.s"
+// Fa_Fo_o: "-cc1as"
+// Fa_Fo_o: "-o" "t.obj"
+// Fa_Fo_o: link.exe
+// Fa_Fo_o: "-out:t.exe"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits