58
58
#include " clang/Basic/Module.h"
59
59
#include " clang/Basic/TargetInfo.h"
60
60
#include " clang/Basic/Version.h"
61
+ #include " clang/CAS/CASOptions.h"
61
62
#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
63
+ #include " clang/Frontend/CompilerInvocation.h"
62
64
#include " clang/Frontend/FrontendActions.h"
63
65
#include " clang/Frontend/TextDiagnosticPrinter.h"
64
66
#include " clang/Frontend/Utils.h"
73
75
#include " clang/Sema/Sema.h"
74
76
#include " clang/Serialization/ASTReader.h"
75
77
#include " clang/Serialization/ASTWriter.h"
78
+ #include " clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
76
79
#include " llvm/ADT/IntrusiveRefCntPtr.h"
77
80
#include " llvm/ADT/STLExtras.h"
81
+ #include " llvm/ADT/SmallVector.h"
78
82
#include " llvm/ADT/StringExtras.h"
79
83
#include " llvm/Support/CrashRecoveryContext.h"
80
84
#include " llvm/Support/FileCollector.h"
@@ -1067,26 +1071,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
1067
1071
ClangImporter *importer, ASTContext &ctx,
1068
1072
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
1069
1073
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;
1090
1075
1091
1076
// Set up a temporary diagnostic client to report errors from parsing the
1092
1077
// command line, which may be important for Swift clients if, for example,
@@ -1098,24 +1083,64 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
1098
1083
// clang::CompilerInstance is created.
1099
1084
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> tempDiagOpts{
1100
1085
new clang::DiagnosticOptions};
1101
-
1102
1086
auto *tempDiagClient =
1103
1087
new ClangDiagnosticConsumer (importer->Impl , *tempDiagOpts,
1104
1088
ctx.ClangImporterOpts .DumpClangDiagnostics );
1105
-
1106
1089
auto clangDiags = clang::CompilerInstance::createDiagnostics (
1107
1090
tempDiagOpts.get (), tempDiagClient,
1108
1091
/* owned*/ true );
1109
1092
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;
1116
1106
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
+ }
1119
1144
1120
1145
// FIXME: clang fails to generate a module if there is a `-fmodule-map-file`
1121
1146
// argument pointing to a missing file.
@@ -3919,6 +3944,66 @@ std::string ClangImporter::getClangModuleHash() const {
3919
3944
return Impl.Invocation ->getModuleHash (Impl.Instance ->getDiagnostics ());
3920
3945
}
3921
3946
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
+
3922
4007
std::optional<Decl *>
3923
4008
ClangImporter::importDeclCached (const clang::NamedDecl *ClangDecl) {
3924
4009
return Impl.importDeclCached (ClangDecl, Impl.CurrentVersion );
0 commit comments