diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 3ad3fb3ff4de3bdc8842fc953cf24ed39bbb1a18..0e5e81a7e2b3476b8da3fe37f1e055b22569706e 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -29,6 +29,7 @@ namespace llvm { namespace clang { namespace driver { class Action; + class Arg; class ArgList; class Compilation; class DerivedArgList; @@ -171,6 +172,11 @@ private: /// arguments, after applying the standard argument translations. DerivedArgList *TranslateInputArgs(const InputArgList &Args) const; + // getFinalPhase - Determine which compilation mode we are in and record + // which option we used to determine the final phase. + phases::ID getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg = 0) + const; + public: Driver(StringRef _ClangExecutable, StringRef _DefaultHostTriple, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 014b9152c47acc325e47951057182dd855e431e8..ac5cedf7719e77a65672bed7970279f5db355374 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -120,6 +120,43 @@ InputArgList *Driver::ParseArgStrings(ArrayRef ArgList) { return Args; } +// Determine which compilation mode we are in. We look for options which +// affect the phase, starting with the earliest phases, and record which +// option we used to determine the final phase. +phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg) +const { + Arg *PhaseArg = 0; + phases::ID FinalPhase; + + // -{E,M,MM} only run the preprocessor. + if (CCCIsCPP || + (PhaseArg = DAL.getLastArg(options::OPT_E)) || + (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) { + FinalPhase = phases::Preprocess; + + // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT__analyze, + options::OPT__analyze_auto)) || + (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || + (PhaseArg = DAL.getLastArg(options::OPT_S))) { + FinalPhase = phases::Compile; + + // -c only runs up to the assembler. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { + FinalPhase = phases::Assemble; + + // Otherwise do everything. + } else + FinalPhase = phases::Link; + + if (FinalPhaseArg) + *FinalPhaseArg = PhaseArg; + + return FinalPhase; +} + DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); @@ -198,6 +235,23 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { } #endif + // If -fapple-kext has been specified, add -kext to linker command if not + // already done so. Also check to make sure we're actually linking. + if (Args.hasArg(options::OPT_fapple_kext) && getFinalPhase(*DAL) == + phases::Link) { + bool add_kext = true; + std::vector LinkerArgs = + Args.getAllArgValues(options::OPT_Xlinker); + for (std::vector::iterator it = LinkerArgs.begin(), + ie = LinkerArgs.end(); it != ie; it++) + if (*it == "-kext") { + add_kext = false; + break; + } + if (add_kext) + DAL->AddSeparateArg(0, Opts->getOption(options::OPT_Xlinker), "-kext"); + } + return DAL; } @@ -818,34 +872,8 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, return; } - // Determine which compilation mode we are in. We look for options which - // affect the phase, starting with the earliest phases, and record which - // option we used to determine the final phase. - Arg *FinalPhaseArg = 0; - phases::ID FinalPhase; - - // -{E,M,MM} only run the preprocessor. - if (CCCIsCPP || - (FinalPhaseArg = Args.getLastArg(options::OPT_E)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { - FinalPhase = phases::Preprocess; - - // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_rewrite_objc)) || - (FinalPhaseArg = Args.getLastArg(options::OPT__analyze, - options::OPT__analyze_auto)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_S))) { - FinalPhase = phases::Compile; - - // -c only runs up to the assembler. - } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) { - FinalPhase = phases::Assemble; - - // Otherwise do everything. - } else - FinalPhase = phases::Link; + Arg *FinalPhaseArg; + phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); // Reject -Z* at the top level, these options should never have been exposed // by gcc.