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,73 @@ 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+ // Workaround for the extra driver argument embedded in the swiftmodule by
1795+ // some swift compiler version. It always starts with `--target=` and it is
1796+ // not a valid cc1 option.
1797+ if (!StringRef (Arg).starts_with (" --target=" ))
1798+ clangArgs.push_back (Arg.c_str ());
1799+ });
1800+
1801+ std::string diags;
1802+ llvm::raw_string_ostream os (diags);
1803+ auto diagOpts = llvm::makeIntrusiveRefCnt<clang::DiagnosticOptions>();
1804+ clang::DiagnosticsEngine clangDiags (
1805+ new clang::DiagnosticIDs (), diagOpts,
1806+ new clang::TextDiagnosticPrinter (os, diagOpts.get ()));
1807+
1808+ if (!clang::CompilerInvocation::CreateFromArgs (invocation, clangArgs,
1809+ clangDiags)) {
1810+ // If cc1 arguments failed to parse, report diagnostics and return
1811+ // immediately.
1812+ AddDiagnostic (eSeverityError, diags);
1813+ // Disable direct-cc1 build as fallback.
1814+ GetClangImporterOptions ().DirectClangCC1ModuleBuild = false ;
1815+ return ;
1816+ }
1817+
1818+ // Clear module cache key and other CAS options to load modules from disk
1819+ // directly.
1820+ invocation.getFrontendOpts ().ModuleCacheKeys .clear ();
1821+ invocation.getCASOpts () = clang::CASOptions ();
1822+
1823+ // Remove non-existing modules in a systematic way.
1824+ bool module_missing = false ;
1825+ auto CheckFileExists = [&](const char *file) {
1826+ if (!llvm::sys::fs::exists (file)) {
1827+ std::string m_description;
1828+ HEALTH_LOG_PRINTF (" Nonexistent explicit module file %s" , file);
1829+ module_missing = true ;
1830+ }
1831+ };
1832+ llvm::for_each (invocation.getHeaderSearchOpts ().PrebuiltModuleFiles ,
1833+ [&](const auto &mod) { CheckFileExists (mod.second .c_str ()); });
1834+ llvm::for_each (invocation.getFrontendOpts ().ModuleFiles ,
1835+ [&](const auto &mod) { CheckFileExists (mod.c_str ()); });
1836+
1837+ // If missing, clear all the prebuilt module options and use implicit module
1838+ // build.
1839+ if (module_missing) {
1840+ invocation.getHeaderSearchOpts ().PrebuiltModuleFiles .clear ();
1841+ invocation.getFrontendOpts ().ModuleFiles .clear ();
1842+ invocation.getLangOpts ().ImplicitModules = true ;
1843+ invocation.getHeaderSearchOpts ().ImplicitModuleMaps = true ;
1844+ }
1845+
1846+ invocation.generateCC1CommandLine (
1847+ [&](const llvm::Twine &arg) { dest.push_back (arg.str ()); });
1848+
1849+ // If cc1 arguments are parsed and generated correctly, set explicitly-built
1850+ // module since only explicit module build can use direct cc1 mode.
1851+ m_has_explicit_modules = true ;
1852+ return ;
1853+ }
1854+
17951855void SwiftASTContext::AddUserClangArgs (TargetProperties &props) {
17961856 Args args (props.GetSwiftExtraClangFlags ());
17971857 std::vector<std::string> user_clang_flags;
0 commit comments