5858#include " clang/Basic/Module.h"
5959#include " clang/Basic/TargetInfo.h"
6060#include " clang/Basic/Version.h"
61+ #include " clang/CAS/CASOptions.h"
6162#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
63+ #include " clang/Frontend/CompilerInvocation.h"
6264#include " clang/Frontend/FrontendActions.h"
6365#include " clang/Frontend/TextDiagnosticPrinter.h"
6466#include " clang/Frontend/Utils.h"
7375#include " clang/Sema/Sema.h"
7476#include " clang/Serialization/ASTReader.h"
7577#include " clang/Serialization/ASTWriter.h"
78+ #include " clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
7679#include " llvm/ADT/IntrusiveRefCntPtr.h"
7780#include " llvm/ADT/STLExtras.h"
81+ #include " llvm/ADT/SmallVector.h"
7882#include " llvm/ADT/StringExtras.h"
7983#include " llvm/Support/CrashRecoveryContext.h"
8084#include " llvm/Support/FileCollector.h"
@@ -1067,26 +1071,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
10671071 ClangImporter *importer, ASTContext &ctx,
10681072 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
10691073 bool ignoreClangTarget) {
1070- // If using direct cc1 module build, return extra args only.
1071- if (ctx.ClangImporterOpts .DirectClangCC1ModuleBuild )
1072- return ctx.ClangImporterOpts .ExtraArgs ;
1073-
1074- // Otherwise, create cc1 arguments from driver args.
1075- auto driverArgs = getClangDriverArguments (ctx, ignoreClangTarget);
1076-
1077- llvm::SmallVector<const char *> invocationArgs;
1078- invocationArgs.reserve (driverArgs.size ());
1079- llvm::for_each (driverArgs, [&](const std::string &Arg) {
1080- invocationArgs.push_back (Arg.c_str ());
1081- });
1082-
1083- if (ctx.ClangImporterOpts .DumpClangDiagnostics ) {
1084- llvm::errs () << " clang importer driver args: '" ;
1085- llvm::interleave (
1086- invocationArgs, [](StringRef arg) { llvm::errs () << arg; },
1087- [] { llvm::errs () << " ' '" ; });
1088- llvm::errs () << " '\n " ;
1089- }
1074+ std::unique_ptr<clang::CompilerInvocation> CI;
10901075
10911076 // Set up a temporary diagnostic client to report errors from parsing the
10921077 // command line, which may be important for Swift clients if, for example,
@@ -1098,24 +1083,64 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
10981083 // clang::CompilerInstance is created.
10991084 llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> tempDiagOpts{
11001085 new clang::DiagnosticOptions};
1101-
11021086 auto *tempDiagClient =
11031087 new ClangDiagnosticConsumer (importer->Impl , *tempDiagOpts,
11041088 ctx.ClangImporterOpts .DumpClangDiagnostics );
1105-
11061089 auto clangDiags = clang::CompilerInstance::createDiagnostics (
11071090 tempDiagOpts.get (), tempDiagClient,
11081091 /* owned*/ true );
11091092
1110- clang::CreateInvocationOptions CIOpts;
1111- CIOpts.VFS = VFS;
1112- CIOpts.Diags = clangDiags;
1113- CIOpts.RecoverOnError = false ;
1114- CIOpts.ProbePrecompiled = true ;
1115- auto CI = clang::createInvocation (invocationArgs, std::move (CIOpts));
1093+ // If using direct cc1 module build, use extra args to setup ClangImporter.
1094+ if (ctx.ClangImporterOpts .DirectClangCC1ModuleBuild ) {
1095+ llvm::SmallVector<const char *> clangArgs;
1096+ clangArgs.reserve (ctx.ClangImporterOpts .ExtraArgs .size ());
1097+ llvm::for_each (
1098+ ctx.ClangImporterOpts .ExtraArgs ,
1099+ [&](const std::string &Arg) { clangArgs.push_back (Arg.c_str ()); });
1100+
1101+ // Try parse extra args, if failed, return nullopt.
1102+ CI = std::make_unique<clang::CompilerInvocation>();
1103+ if (!clang::CompilerInvocation::CreateFromArgs (*CI, clangArgs,
1104+ *clangDiags))
1105+ return std::nullopt ;
11161106
1117- if (!CI)
1118- return std::nullopt ;
1107+ // Forwards some options from swift to clang even using direct mode. This is
1108+ // to reduce the number of argument passing on the command-line and swift
1109+ // compiler can be more efficient to compute swift cache key without having
1110+ // the knowledge about clang command-line options.
1111+ if (ctx.CASOpts .EnableCaching )
1112+ CI->getCASOpts () = ctx.CASOpts .CASOpts ;
1113+
1114+ // Forward the index store path. That information is not passed to scanner
1115+ // and it is cached invariant so we don't want to re-scan if that changed.
1116+ CI->getFrontendOpts ().IndexStorePath = ctx.ClangImporterOpts .IndexStorePath ;
1117+ } else {
1118+ // Otherwise, create cc1 arguments from driver args.
1119+ auto driverArgs = getClangDriverArguments (ctx, ignoreClangTarget);
1120+
1121+ llvm::SmallVector<const char *> invocationArgs;
1122+ invocationArgs.reserve (driverArgs.size ());
1123+ llvm::for_each (driverArgs, [&](const std::string &Arg) {
1124+ invocationArgs.push_back (Arg.c_str ());
1125+ });
1126+
1127+ if (ctx.ClangImporterOpts .DumpClangDiagnostics ) {
1128+ llvm::errs () << " clang importer driver args: '" ;
1129+ llvm::interleave (
1130+ invocationArgs, [](StringRef arg) { llvm::errs () << arg; },
1131+ [] { llvm::errs () << " ' '" ; });
1132+ llvm::errs () << " '\n " ;
1133+ }
1134+
1135+ clang::CreateInvocationOptions CIOpts;
1136+ CIOpts.VFS = VFS;
1137+ CIOpts.Diags = clangDiags;
1138+ CIOpts.RecoverOnError = false ;
1139+ CIOpts.ProbePrecompiled = true ;
1140+ CI = clang::createInvocation (invocationArgs, std::move (CIOpts));
1141+ if (!CI)
1142+ return std::nullopt ;
1143+ }
11191144
11201145 // FIXME: clang fails to generate a module if there is a `-fmodule-map-file`
11211146 // argument pointing to a missing file.
@@ -3919,6 +3944,66 @@ std::string ClangImporter::getClangModuleHash() const {
39193944 return Impl.Invocation ->getModuleHash (Impl.Instance ->getDiagnostics ());
39203945}
39213946
3947+ std::vector<std::string>
3948+ ClangImporter::getSwiftExplicitModuleDirectCC1Args () const {
3949+ llvm::SmallVector<const char *> clangArgs;
3950+ clangArgs.reserve (Impl.ClangArgs .size ());
3951+ llvm::for_each (Impl.ClangArgs , [&](const std::string &Arg) {
3952+ clangArgs.push_back (Arg.c_str ());
3953+ });
3954+
3955+ clang::CompilerInvocation instance;
3956+ clang::DiagnosticsEngine clangDiags (new clang::DiagnosticIDs (),
3957+ new clang::DiagnosticOptions (),
3958+ new clang::IgnoringDiagConsumer ());
3959+ bool success = clang::CompilerInvocation::CreateFromArgs (instance, clangArgs,
3960+ clangDiags);
3961+ (void )success;
3962+ assert (success && " clang options from clangImporter failed to parse" );
3963+
3964+ if (!Impl.SwiftContext .CASOpts .EnableCaching )
3965+ return instance.getCC1CommandLine ();
3966+
3967+ // Clear some options that are not needed.
3968+ instance.clearImplicitModuleBuildOptions ();
3969+
3970+ // CASOpts are forwarded from swift arguments.
3971+ instance.getCASOpts () = clang::CASOptions ();
3972+
3973+ // HeaderSearchOptions.
3974+ // Clang search options are only used by scanner and clang importer from main
3975+ // module should not using search paths to find modules.
3976+ auto &HSOpts = instance.getHeaderSearchOpts ();
3977+ HSOpts.VFSOverlayFiles .clear ();
3978+ HSOpts.UserEntries .clear ();
3979+ HSOpts.SystemHeaderPrefixes .clear ();
3980+
3981+ // FrontendOptions.
3982+ auto &FEOpts = instance.getFrontendOpts ();
3983+ FEOpts.IncludeTimestamps = false ;
3984+ FEOpts.ModuleMapFiles .clear ();
3985+
3986+ // IndexStorePath is forwarded from swift.
3987+ FEOpts.IndexStorePath .clear ();
3988+
3989+ // PreprocessorOptions.
3990+ // Cannot clear macros as the main module clang importer doesn't have clang
3991+ // include tree created and it has to be created from command-line. However,
3992+ // include files are no collected into CASFS so they will not be found so
3993+ // clear them to avoid problem.
3994+ auto &PPOpts = instance.getPreprocessorOpts ();
3995+ PPOpts.MacroIncludes .clear ();
3996+ PPOpts.Includes .clear ();
3997+
3998+ if (Impl.SwiftContext .ClangImporterOpts .UseClangIncludeTree ) {
3999+ // FileSystemOptions.
4000+ auto &FSOpts = instance.getFileSystemOpts ();
4001+ FSOpts.WorkingDir .clear ();
4002+ }
4003+
4004+ return instance.getCC1CommandLine ();
4005+ }
4006+
39224007std::optional<Decl *>
39234008ClangImporter::importDeclCached (const clang::NamedDecl *ClangDecl) {
39244009 return Impl.importDeclCached (ClangDecl, Impl.CurrentVersion );
0 commit comments