5757#include " clang/Basic/TargetOptions.h"
5858#include " clang/Driver/Driver.h"
5959#include " clang/Frontend/CompilerInstance.h"
60+ #include " clang/Frontend/TextDiagnosticPrinter.h"
6061#include " clang/Lex/Preprocessor.h"
6162
6263#include " clang/Lex/PreprocessorOptions.h"
@@ -1573,21 +1574,7 @@ bool ShouldUnique(StringRef arg) {
15731574
15741575// static
15751576void SwiftASTContext::AddExtraClangArgs (const std::vector<std::string> &source,
1576- std::vector<std::string> &dest,
1577- bool cc1) {
1578- // FIXME: Support for cc1 flags isn't complete. The uniquing
1579- // algortihm below does not work for cc1 flags. Since cc1 flags are
1580- // not stable it's not feasible to keep a list of all multi-arg
1581- // flags, for example. It also makes it difficult to correctly
1582- // identify where workng directories and path remappings should
1583- // applied. For all these reasons, using cc1 flags for anything but
1584- // a local build with explicit modules and precise compiler
1585- // invocations isn't supported yet.
1586- if (cc1) {
1587- dest.insert (dest.end (), source.begin (), source.end ());
1588- return ;
1589- }
1590-
1577+ std::vector<std::string> &dest) {
15911578 llvm::StringSet<> unique_flags;
15921579 for (auto &arg : dest)
15931580 unique_flags.insert (arg);
@@ -1779,8 +1766,14 @@ void SwiftASTContext::AddExtraClangArgs(
17791766 eSeverityWarning,
17801767 " Mixing and matching of driver and cc1 Clang options detected" );
17811768
1782- AddExtraClangArgs (ExtraArgs, importer_options.ExtraArgs ,
1783- importer_options.DirectClangCC1ModuleBuild );
1769+ // If using direct cc1 flags, compute the arguments and return.
1770+ // Since this is cc1 flags, no driver overwrite can be applied.
1771+ if (importer_options.DirectClangCC1ModuleBuild ) {
1772+ AddExtraClangCC1Args (ExtraArgs, importer_options.ExtraArgs );
1773+ return ;
1774+ }
1775+
1776+ AddExtraClangArgs (ExtraArgs, importer_options.ExtraArgs );
17841777 applyOverrideOptions (importer_options.ExtraArgs , overrideOpts);
17851778 if (HasNonexistentExplicitModule (importer_options.ExtraArgs ))
17861779 RemoveExplicitModules (importer_options.ExtraArgs );
@@ -1792,6 +1785,69 @@ void SwiftASTContext::AddExtraClangArgs(
17921785 });
17931786}
17941787
1788+ void SwiftASTContext::AddExtraClangCC1Args (
1789+ const std::vector<std::string> &source, std::vector<std::string> &dest) {
1790+ clang::CompilerInvocation invocation;
1791+ llvm::SmallVector<const char *> clangArgs;
1792+ clangArgs.reserve (source.size ());
1793+ llvm::for_each (source, [&](const std::string &Arg) {
1794+ clangArgs.push_back (Arg.c_str ());
1795+ });
1796+
1797+ std::string diags;
1798+ llvm::raw_string_ostream os (diags);
1799+ auto diagOpts = llvm::makeIntrusiveRefCnt<clang::DiagnosticOptions>();
1800+ clang::DiagnosticsEngine clangDiags (
1801+ new clang::DiagnosticIDs (), diagOpts,
1802+ new clang::TextDiagnosticPrinter (os, diagOpts.get ()));
1803+
1804+ if (!clang::CompilerInvocation::CreateFromArgs (invocation, clangArgs,
1805+ clangDiags)) {
1806+ // If cc1 arguments failed to parse, report diagnostics and return
1807+ // immediately.
1808+ AddDiagnostic (eSeverityError, diags);
1809+ // Disable direct-cc1 build as fallback.
1810+ GetClangImporterOptions ().DirectClangCC1ModuleBuild = false ;
1811+ return ;
1812+ }
1813+
1814+ // Clear module cache key and other CAS options to load modules from disk
1815+ // directly.
1816+ invocation.getFrontendOpts ().ModuleCacheKeys .clear ();
1817+ invocation.getCASOpts () = clang::CASOptions ();
1818+
1819+ // Remove non-existing modules in a systematic way.
1820+ bool module_missing = false ;
1821+ auto CheckFileExists = [&](const char *file) {
1822+ if (!llvm::sys::fs::exists (file)) {
1823+ std::string m_description;
1824+ HEALTH_LOG_PRINTF (" Nonexistent explicit module file %s" , file);
1825+ module_missing = true ;
1826+ }
1827+ };
1828+ llvm::for_each (invocation.getHeaderSearchOpts ().PrebuiltModuleFiles ,
1829+ [&](const auto &mod) { CheckFileExists (mod.second .c_str ()); });
1830+ llvm::for_each (invocation.getFrontendOpts ().ModuleFiles ,
1831+ [&](const auto &mod) { CheckFileExists (mod.c_str ()); });
1832+
1833+ // If missing, clear all the prebuilt module options and use implicit module
1834+ // build.
1835+ if (module_missing) {
1836+ invocation.getHeaderSearchOpts ().PrebuiltModuleFiles .clear ();
1837+ invocation.getFrontendOpts ().ModuleFiles .clear ();
1838+ invocation.getLangOpts ().ImplicitModules = true ;
1839+ invocation.getHeaderSearchOpts ().ImplicitModuleMaps = true ;
1840+ }
1841+
1842+ invocation.generateCC1CommandLine (
1843+ [&](const llvm::Twine &arg) { dest.push_back (arg.str ()); });
1844+
1845+ // If cc1 arguments are parsed and generated correctly, set explicitly-built
1846+ // module since only explicit module build can use direct cc1 mode.
1847+ m_has_explicit_modules = true ;
1848+ return ;
1849+ }
1850+
17951851void SwiftASTContext::AddUserClangArgs (TargetProperties &props) {
17961852 Args args (props.GetSwiftExtraClangFlags ());
17971853 std::vector<std::string> user_clang_flags;
0 commit comments