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 ">, MetaVarName<"">; 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 @@ -1607,9 +1607,20 @@ bool MultipleArchs) const { llvm::PrettyStackTraceString CrashInfo("Computing output path"); // Output to a user requested destination? - if (AtTopLevel && !isa(JA) && - !isa(JA)) { - if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) + if (AtTopLevel && !isa(JA) && !isa(JA)) { + // Honor -o if it is the last output option for this job type. + types::ID Ty = JA.getType(); + options::ID MaybeFA = + Ty == types::TY_PP_Asm ? options::OPT__SLASH_FA : options::OPT_INVALID; + options::ID MaybeFa = + Ty == types::TY_PP_Asm ? options::OPT__SLASH_Fa : options::OPT_INVALID; + options::ID MaybeFo = + Ty == types::TY_Object ? options::OPT__SLASH_Fo : options::OPT_INVALID; + options::ID MaybeFe = + Ty == types::TY_Image ? options::OPT__SLASH_Fe : options::OPT_INVALID; + Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o, MaybeFA, MaybeFa, + MaybeFo, MaybeFe); + if (FinalOutput && FinalOutput->getOption().matches(options::OPT_o)) return C.addResultFile(FinalOutput->getValue(), &JA); } 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"