57
57
#include " clang/Basic/TargetOptions.h"
58
58
#include " clang/Driver/Driver.h"
59
59
#include " clang/Frontend/CompilerInstance.h"
60
+ #include " clang/Frontend/TextDiagnosticPrinter.h"
60
61
#include " clang/Lex/Preprocessor.h"
61
62
62
63
#include " clang/Lex/PreprocessorOptions.h"
@@ -1573,21 +1574,7 @@ bool ShouldUnique(StringRef arg) {
1573
1574
1574
1575
// static
1575
1576
void 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) {
1591
1578
llvm::StringSet<> unique_flags;
1592
1579
for (auto &arg : dest)
1593
1580
unique_flags.insert (arg);
@@ -1764,23 +1751,37 @@ static void applyOverrideOptions(std::vector<std::string> &args,
1764
1751
1765
1752
void SwiftASTContext::AddExtraClangArgs (
1766
1753
const std::vector<std::string> &ExtraArgs, StringRef overrideOpts) {
1754
+ if (ExtraArgs.empty ())
1755
+ return ;
1756
+
1767
1757
swift::ClangImporterOptions &importer_options = GetClangImporterOptions ();
1768
1758
1769
1759
// Detect cc1 flags. When DirectClangCC1ModuleBuild is on then the
1770
1760
// clang arguments in the serialized invocation are clang cc1 flags,
1771
1761
// which are very specific to one compiler version and cannot
1772
1762
// be merged with driver options.
1773
1763
bool fresh_invocation = importer_options.ExtraArgs .empty ();
1774
- if (fresh_invocation && !ExtraArgs.empty () && ExtraArgs.front () == " -cc1" )
1775
- importer_options.DirectClangCC1ModuleBuild = true ;
1776
- if (!importer_options.DirectClangCC1ModuleBuild && !ExtraArgs.empty () &&
1777
- ExtraArgs.front () == " -cc1" )
1764
+ bool invocation_direct_cc1 = ExtraArgs.front () == " -cc1" ;
1765
+
1766
+ // If it is not a fresh invocation, make sure the cc1 option matches.
1767
+ if (!fresh_invocation &&
1768
+ (importer_options.DirectClangCC1ModuleBuild != invocation_direct_cc1))
1778
1769
AddDiagnostic (
1779
1770
eSeverityWarning,
1780
1771
" Mixing and matching of driver and cc1 Clang options detected" );
1781
1772
1782
- AddExtraClangArgs (ExtraArgs, importer_options.ExtraArgs ,
1783
- importer_options.DirectClangCC1ModuleBuild );
1773
+ importer_options.DirectClangCC1ModuleBuild = invocation_direct_cc1;
1774
+
1775
+ // If using direct cc1 flags, compute the arguments and return.
1776
+ // Since this is cc1 flags, override options are driver flags and don't apply.
1777
+ if (importer_options.DirectClangCC1ModuleBuild ) {
1778
+ if (!fresh_invocation)
1779
+ importer_options.ExtraArgs .clear ();
1780
+ AddExtraClangCC1Args (ExtraArgs, importer_options.ExtraArgs );
1781
+ return ;
1782
+ }
1783
+
1784
+ AddExtraClangArgs (ExtraArgs, importer_options.ExtraArgs );
1784
1785
applyOverrideOptions (importer_options.ExtraArgs , overrideOpts);
1785
1786
if (HasNonexistentExplicitModule (importer_options.ExtraArgs ))
1786
1787
RemoveExplicitModules (importer_options.ExtraArgs );
@@ -1792,6 +1793,78 @@ void SwiftASTContext::AddExtraClangArgs(
1792
1793
});
1793
1794
}
1794
1795
1796
+ void SwiftASTContext::AddExtraClangCC1Args (
1797
+ const std::vector<std::string> &source, std::vector<std::string> &dest) {
1798
+ clang::CompilerInvocation invocation;
1799
+ llvm::SmallVector<const char *> clangArgs;
1800
+ clangArgs.reserve (source.size ());
1801
+ llvm::for_each (source, [&](const std::string &Arg) {
1802
+ // Workaround for the extra driver argument embedded in the swiftmodule by
1803
+ // some swift compiler version. It always starts with `--target=` and it is
1804
+ // not a valid cc1 option.
1805
+ if (!StringRef (Arg).starts_with (" --target=" ))
1806
+ clangArgs.push_back (Arg.c_str ());
1807
+ });
1808
+
1809
+ std::string diags;
1810
+ llvm::raw_string_ostream os (diags);
1811
+ auto diagOpts = llvm::makeIntrusiveRefCnt<clang::DiagnosticOptions>();
1812
+ clang::DiagnosticsEngine clangDiags (
1813
+ new clang::DiagnosticIDs (), diagOpts,
1814
+ new clang::TextDiagnosticPrinter (os, diagOpts.get ()));
1815
+
1816
+ if (!clang::CompilerInvocation::CreateFromArgs (invocation, clangArgs,
1817
+ clangDiags)) {
1818
+ // If cc1 arguments failed to parse, report diagnostics and return
1819
+ // immediately.
1820
+ AddDiagnostic (eSeverityError, diags);
1821
+ // Disable direct-cc1 build as fallback.
1822
+ GetClangImporterOptions ().DirectClangCC1ModuleBuild = false ;
1823
+ return ;
1824
+ }
1825
+
1826
+ // Clear module cache key and other CAS options to load modules from disk
1827
+ // directly.
1828
+ invocation.getFrontendOpts ().ModuleCacheKeys .clear ();
1829
+ invocation.getCASOpts () = clang::CASOptions ();
1830
+
1831
+ // Ignore CAS info inside modules when loading.
1832
+ invocation.getFrontendOpts ().ModuleLoadIgnoreCAS = true ;
1833
+
1834
+ // Remove non-existing modules in a systematic way.
1835
+ bool module_missing = false ;
1836
+ auto CheckFileExists = [&](const char *file) {
1837
+ if (!llvm::sys::fs::exists (file)) {
1838
+ std::string warn;
1839
+ llvm::raw_string_ostream (warn)
1840
+ << " Nonexistent explicit module file " << file;
1841
+ AddDiagnostic (eSeverityWarning, warn);
1842
+ module_missing = true ;
1843
+ }
1844
+ };
1845
+ llvm::for_each (invocation.getHeaderSearchOpts ().PrebuiltModuleFiles ,
1846
+ [&](const auto &mod) { CheckFileExists (mod.second .c_str ()); });
1847
+ llvm::for_each (invocation.getFrontendOpts ().ModuleFiles ,
1848
+ [&](const auto &mod) { CheckFileExists (mod.c_str ()); });
1849
+
1850
+ // If missing, clear all the prebuilt module options and switch to implicit
1851
+ // modules build.
1852
+ if (module_missing) {
1853
+ invocation.getHeaderSearchOpts ().PrebuiltModuleFiles .clear ();
1854
+ invocation.getFrontendOpts ().ModuleFiles .clear ();
1855
+ invocation.getLangOpts ().ImplicitModules = true ;
1856
+ invocation.getHeaderSearchOpts ().ImplicitModuleMaps = true ;
1857
+ }
1858
+
1859
+ invocation.generateCC1CommandLine (
1860
+ [&](const llvm::Twine &arg) { dest.push_back (arg.str ()); });
1861
+
1862
+ // If cc1 arguments are parsed and generated correctly, set explicitly-built
1863
+ // module since only explicit module build can use direct cc1 mode.
1864
+ m_has_explicit_modules = true ;
1865
+ return ;
1866
+ }
1867
+
1795
1868
void SwiftASTContext::AddUserClangArgs (TargetProperties &props) {
1796
1869
Args args (props.GetSwiftExtraClangFlags ());
1797
1870
std::vector<std::string> user_clang_flags;
@@ -1883,6 +1956,10 @@ void SwiftASTContext::RemapClangImporterOptions(
1883
1956
1884
1957
void SwiftASTContext::FilterClangImporterOptions (
1885
1958
std::vector<std::string> &extra_args, SwiftASTContext *ctx) {
1959
+ // The direct cc1 mode do not need any extra audit.
1960
+ if (ctx && ctx->GetClangImporterOptions ().DirectClangCC1ModuleBuild )
1961
+ return ;
1962
+
1886
1963
std::string ivfs_arg;
1887
1964
// Copy back a filtered version of ExtraArgs.
1888
1965
std::vector<std::string> orig_args (std::move (extra_args));
@@ -1893,11 +1970,6 @@ void SwiftASTContext::FilterClangImporterOptions(
1893
1970
arg_sr == " -fno-implicit-module-maps" )
1894
1971
continue ;
1895
1972
1896
- // This is not a cc1 option.
1897
- if (arg_sr.starts_with (" --target=" ) && ctx &&
1898
- ctx->GetClangImporterOptions ().DirectClangCC1ModuleBuild )
1899
- continue ;
1900
-
1901
1973
// The VFS options turn into fatal errors when the referenced file
1902
1974
// is not found. Since the Xcode build system tends to create a
1903
1975
// lot of VFS overlays by default, stat them and emit a warning if
@@ -2184,6 +2256,11 @@ ProcessModule(Module &module, std::string m_description,
2184
2256
for (auto path : opts.getFrameworkSearchPaths ())
2185
2257
framework_search_paths.push_back ({path.Path , path.IsSystem });
2186
2258
auto &clang_opts = invocation.getClangImporterOptions ().ExtraArgs ;
2259
+ // If the args embedded are cc1 args, they are not compatible with existing
2260
+ // setting. Clear the previous args.
2261
+ if (!clang_opts.empty () && clang_opts.front () == " -cc1" )
2262
+ extra_clang_args.clear ();
2263
+
2187
2264
for (const std::string &arg : clang_opts) {
2188
2265
extra_clang_args.push_back (arg);
2189
2266
LOG_VERBOSE_PRINTF (GetLog (LLDBLog::Types), " adding Clang argument \" %s\" ." ,
0 commit comments