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"
75
77
#include " clang/Serialization/ASTWriter.h"
76
78
#include " llvm/ADT/IntrusiveRefCntPtr.h"
77
79
#include " llvm/ADT/STLExtras.h"
80
+ #include " llvm/ADT/SmallVector.h"
78
81
#include " llvm/ADT/StringExtras.h"
79
82
#include " llvm/Support/CrashRecoveryContext.h"
80
83
#include " llvm/Support/FileCollector.h"
@@ -1067,26 +1070,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
1067
1070
ClangImporter *importer, ASTContext &ctx,
1068
1071
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
1069
1072
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
- }
1073
+ std::unique_ptr<clang::CompilerInvocation> CI;
1090
1074
1091
1075
// Set up a temporary diagnostic client to report errors from parsing the
1092
1076
// command line, which may be important for Swift clients if, for example,
@@ -1098,24 +1082,62 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
1098
1082
// clang::CompilerInstance is created.
1099
1083
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> tempDiagOpts{
1100
1084
new clang::DiagnosticOptions};
1101
-
1102
1085
auto *tempDiagClient =
1103
1086
new ClangDiagnosticConsumer (importer->Impl , *tempDiagOpts,
1104
1087
ctx.ClangImporterOpts .DumpClangDiagnostics );
1105
-
1106
1088
auto clangDiags = clang::CompilerInstance::createDiagnostics (
1107
1089
tempDiagOpts.get (), tempDiagClient,
1108
1090
/* owned*/ true );
1109
1091
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));
1092
+ // If using direct cc1 module build, use extra args to setup ClangImporter.
1093
+ if (ctx.ClangImporterOpts .DirectClangCC1ModuleBuild ) {
1094
+ llvm::SmallVector<const char *> clangArgs;
1095
+ clangArgs.reserve (ctx.ClangImporterOpts .ExtraArgs .size ());
1096
+ llvm::for_each (
1097
+ ctx.ClangImporterOpts .ExtraArgs ,
1098
+ [&](const std::string &Arg) { clangArgs.push_back (Arg.c_str ()); });
1099
+
1100
+ // Try parse extra args, if failed, return nullopt.
1101
+ CI = std::make_unique<clang::CompilerInvocation>();
1102
+ if (!clang::CompilerInvocation::CreateFromArgs (*CI, clangArgs,
1103
+ *clangDiags))
1104
+ return std::nullopt;
1116
1105
1117
- if (!CI)
1118
- return std::nullopt;
1106
+ // Forwards some options from swift to clang even using direct mode. This is
1107
+ // to reduce the number of argument passing on the command-line and swift
1108
+ // compiler can be more efficient to compute swift cache key without having
1109
+ // the knowledge about clang command-line options.
1110
+ if (ctx.CASOpts .EnableCaching ) {
1111
+ CI->getFrontendOpts ().IncludeTimestamps = false ;
1112
+ CI->getCASOpts () = ctx.CASOpts .CASOpts ;
1113
+ }
1114
+ } else {
1115
+ // Otherwise, create cc1 arguments from driver args.
1116
+ auto driverArgs = getClangDriverArguments (ctx, ignoreClangTarget);
1117
+
1118
+ llvm::SmallVector<const char *> invocationArgs;
1119
+ invocationArgs.reserve (driverArgs.size ());
1120
+ llvm::for_each (driverArgs, [&](const std::string &Arg) {
1121
+ invocationArgs.push_back (Arg.c_str ());
1122
+ });
1123
+
1124
+ if (ctx.ClangImporterOpts .DumpClangDiagnostics ) {
1125
+ llvm::errs () << " clang importer driver args: '" ;
1126
+ llvm::interleave (
1127
+ invocationArgs, [](StringRef arg) { llvm::errs () << arg; },
1128
+ [] { llvm::errs () << " ' '" ; });
1129
+ llvm::errs () << " '\n " ;
1130
+ }
1131
+
1132
+ clang::CreateInvocationOptions CIOpts;
1133
+ CIOpts.VFS = VFS;
1134
+ CIOpts.Diags = clangDiags;
1135
+ CIOpts.RecoverOnError = false ;
1136
+ CIOpts.ProbePrecompiled = true ;
1137
+ CI = clang::createInvocation (invocationArgs, std::move (CIOpts));
1138
+ if (!CI)
1139
+ return std::nullopt;
1140
+ }
1119
1141
1120
1142
// FIXME: clang fails to generate a module if there is a `-fmodule-map-file`
1121
1143
// argument pointing to a missing file.
@@ -3919,6 +3941,67 @@ std::string ClangImporter::getClangModuleHash() const {
3919
3941
return Impl.Invocation ->getModuleHash (Impl.Instance ->getDiagnostics ());
3920
3942
}
3921
3943
3944
+ std::vector<std::string>
3945
+ ClangImporter::getSwiftExplicitModuleDirectCC1Args () const {
3946
+ llvm::SmallVector<const char *> clangArgs;
3947
+ clangArgs.reserve (Impl.ClangArgs .size ());
3948
+ llvm::for_each (Impl.ClangArgs , [&](const std::string &Arg) {
3949
+ clangArgs.push_back (Arg.c_str ());
3950
+ });
3951
+
3952
+ clang::CompilerInvocation instance;
3953
+ clang::DiagnosticsEngine clangDiags (new clang::DiagnosticIDs (),
3954
+ new clang::DiagnosticOptions (),
3955
+ new clang::IgnoringDiagConsumer ());
3956
+ bool success = clang::CompilerInvocation::CreateFromArgs (instance, clangArgs,
3957
+ clangDiags);
3958
+ (void )success;
3959
+ assert (success && " clang options from clangImporter failed to parse" );
3960
+
3961
+ if (!Impl.SwiftContext .CASOpts .EnableCaching )
3962
+ return instance.getCC1CommandLine ();
3963
+
3964
+ // Clear some options that are not needed.
3965
+ // CASOpts are forwarded from swift arguments.
3966
+ instance.getCASOpts () = clang::CASOptions ();
3967
+
3968
+ // HeaderSearchOptions.
3969
+ // Clang search options are only used by scanner and clang importer from main
3970
+ // module should not using search paths to find modules.
3971
+ auto &HSOpts = instance.getHeaderSearchOpts ();
3972
+ HSOpts.BuildSessionTimestamp = 0 ;
3973
+ HSOpts.ImplicitModuleMaps = 0 ;
3974
+ HSOpts.VFSOverlayFiles .clear ();
3975
+ HSOpts.UserEntries .clear ();
3976
+ HSOpts.SystemHeaderPrefixes .clear ();
3977
+
3978
+ // LanguageOptions.
3979
+ auto &LangOpts = instance.getLangOpts ();
3980
+ LangOpts.ImplicitModules = false ;
3981
+
3982
+ // FrontendOptions.
3983
+ auto &FEOpts = instance.getFrontendOpts ();
3984
+ FEOpts.IncludeTimestamps = false ;
3985
+ FEOpts.ModuleMapFiles .clear ();
3986
+
3987
+ // PreprocessorOptions.
3988
+ // Cannot clear macros as the main module clang importer doesn't have clang
3989
+ // include tree created and it has to be created from command-line. However,
3990
+ // include files are no collected into CASFS so they will not be found so
3991
+ // clear them to avoid problem.
3992
+ auto &PPOpts = instance.getPreprocessorOpts ();
3993
+ PPOpts.MacroIncludes .clear ();
3994
+ PPOpts.Includes .clear ();
3995
+
3996
+ if (Impl.SwiftContext .ClangImporterOpts .UseClangIncludeTree ) {
3997
+ // FileSystemOptions.
3998
+ auto &FSOpts = instance.getFileSystemOpts ();
3999
+ FSOpts.WorkingDir .clear ();
4000
+ }
4001
+
4002
+ return instance.getCC1CommandLine ();
4003
+ }
4004
+
3922
4005
std::optional<Decl *>
3923
4006
ClangImporter::importDeclCached (const clang::NamedDecl *ClangDecl) {
3924
4007
return Impl.importDeclCached (ClangDecl, Impl.CurrentVersion );
0 commit comments