diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index f4f79cb695..76863d4ae0 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -80,9 +80,15 @@ public: /// FIXME: Documenting error behavior. /// /// \param Res [out] - The resulting invocation. - /// \param Args - The input argument strings. + /// \param ArgBegin - The first element in the argument vector. + /// \param ArgEnd - The last element in the argument vector. + /// \param Argv0 - The program path (from argv[0]), for finding the builtin + /// compiler path. + /// \param MainAddr - The address of main (or some other function in the main + /// executable), for finding the builtin compiler path. static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, - const char **ArgEnd); + const char **ArgEnd, const char *Argv0, + void *MainAddr); /// toArgs - Convert the CompilerInvocation to a list of strings suitable for /// passing to CreateFromArgs. diff --git a/lib/Driver/CC1Options.cpp b/lib/Driver/CC1Options.cpp index b9c4277c56..6f0aa26af7 100644 --- a/lib/Driver/CC1Options.cpp +++ b/lib/Driver/CC1Options.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/CC1Options.h" +#include "clang/Basic/Version.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Arg.h" #include "clang/Driver/OptTable.h" @@ -19,6 +20,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Host.h" +#include "llvm/System/Path.h" using namespace clang::driver; using namespace clang::driver::options; @@ -373,14 +375,34 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args) { return DashX; } -static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { +static std::string GetBuiltinIncludePath(const char *Argv0, + void *MainAddr) { + llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr); + + if (!P.isEmpty()) { + P.eraseComponent(); // Remove /clang from foo/bin/clang + P.eraseComponent(); // Remove /bin from foo/bin + + // Get foo/lib/clang//include + P.appendComponent("lib"); + P.appendComponent("clang"); + P.appendComponent(CLANG_VERSION_STRING); + P.appendComponent("include"); + } + + return P.str(); +} + +static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, + const char *Argv0, void *MainAddr) { using namespace cc1options; Opts.Sysroot = getLastArgValue(Args, OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc); Opts.BuiltinIncludePath = ""; + // FIXME: Add an option for this, its a slow call. if (!Args.hasArg(OPT_nobuiltininc)) - Opts.BuiltinIncludePath = "FIXME"; // FIXME: Get builtin include path! + Opts.BuiltinIncludePath = GetBuiltinIncludePath(Argv0, MainAddr); // Add -I... and -F... options in order. for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F), @@ -638,7 +660,9 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, - const char **ArgEnd) { + const char **ArgEnd, + const char *Argv0, + void *MainAddr) { // Parse the arguments. llvm::OwningPtr Opts(createCC1OptTable()); unsigned MissingArgIndex, MissingArgCount; @@ -660,7 +684,8 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, ParseDiagnosticArgs(Res.getDiagnosticOpts(), *InputArgs); FrontendOptions::InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *InputArgs); - ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *InputArgs); + ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *InputArgs, + Argv0, MainAddr); if (DashX != FrontendOptions::IK_AST) ParseLangArgs(Res.getLangOpts(), *InputArgs, DashX); ParsePreprocessorArgs(Res.getPreprocessorOpts(), *InputArgs); diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 93adf579f9..5097c25832 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -25,7 +25,8 @@ using namespace clang; using namespace clang::driver; -int cc1_main(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { +int cc1_main(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd, + const char *Argv0, void *MainAddr) { llvm::errs() << "cc1 argv:"; for (const char **i = ArgBegin; i != ArgEnd; ++i) llvm::errs() << " \"" << *i << '"'; @@ -51,7 +52,8 @@ int cc1_main(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { // Create a compiler invocation. llvm::errs() << "cc1 creating invocation.\n"; CompilerInvocation Invocation; - CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd); + CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, + Argv0, MainAddr); // Convert the invocation back to argument strings. std::vector InvocationArgs; @@ -70,7 +72,7 @@ int cc1_main(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { // same thing. CompilerInvocation Invocation2; CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(), - Invocation2Args.end()); + Invocation2Args.end(), Argv0, MainAddr); // FIXME: Implement CompilerInvocation comparison. if (true) { diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index c69b29c1ed..d06ead0411 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -179,7 +179,8 @@ void ApplyQAOverride(std::vector &Args, const char *OverrideStr, } extern int cc1_main(Diagnostic &Diags, - const char **ArgBegin, const char **ArgEnd); + const char **ArgBegin, const char **ArgEnd, + const char *Argv0, void *MainAddr); int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); @@ -192,7 +193,8 @@ int main(int argc, const char **argv) { // Dispatch to cc1_main if appropriate. if (argc > 1 && llvm::StringRef(argv[1]) == "-cc1") - return cc1_main(Diags, argv+2, argv+argc); + return cc1_main(Diags, argv+2, argv+argc, argv[0], + (void*) (intptr_t) GetExecutablePath); #ifdef CLANG_IS_PRODUCTION bool IsProduction = true;