Skip to content

Commit 28b8155

Browse files
committed
[cxx-interop] Extract the C++ stdlib kind from Clang Driver
rdar://118357548 / #69825
1 parent ca0add4 commit 28b8155

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ namespace llvm {
2626
class Triple;
2727
class FileCollectorBase;
2828
template<typename Fn> class function_ref;
29+
namespace opt {
30+
class InputArgList;
31+
}
2932
namespace vfs {
3033
class FileSystem;
3134
class OutputBackend;
@@ -51,6 +54,9 @@ namespace clang {
5154
class DeclarationName;
5255
class CompilerInvocation;
5356
class TargetOptions;
57+
namespace driver {
58+
class Driver;
59+
}
5460
namespace tooling {
5561
namespace dependencies {
5662
struct ModuleDeps;
@@ -74,9 +80,11 @@ class EnumDecl;
7480
class FuncDecl;
7581
class ImportDecl;
7682
class IRGenOptions;
83+
class LangOptions;
7784
class ModuleDecl;
7885
struct ModuleDependencyID;
7986
class NominalTypeDecl;
87+
class SearchPathOptions;
8088
class StructDecl;
8189
class SwiftLookupTable;
8290
class TypeDecl;
@@ -196,6 +204,22 @@ class ClangImporter final : public ClangModuleLoader {
196204
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
197205
const std::vector<std::string> &CC1Args);
198206

207+
/// Creates a Clang Driver based on the Swift compiler options.
208+
///
209+
/// \return a pair of the Clang Driver and the diagnostic engine, which needs
210+
/// to be alive during the use of the Driver.
211+
static std::pair<clang::driver::Driver,
212+
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>>
213+
createClangDriver(
214+
const LangOptions &LangOpts,
215+
const ClangImporterOptions &ClangImporterOpts,
216+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs = nullptr);
217+
218+
static llvm::opt::InputArgList
219+
createClangArgs(const ClangImporterOptions &ClangImporterOpts,
220+
const SearchPathOptions &SearchPathOpts,
221+
clang::driver::Driver &clangDriver);
222+
199223
ClangImporter(const ClangImporter &) = delete;
200224
ClangImporter(ClangImporter &&) = delete;
201225
ClangImporter &operator=(const ClangImporter &) = delete;

lib/ClangImporter/ClangIncludePaths.cpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,18 @@ parseClangDriverArgs(const clang::driver::Driver &clangDriver,
112112
return clangDriver.getOpts().ParseArgs(args, unused1, unused2);
113113
}
114114

115-
static clang::driver::Driver
116-
createClangDriver(const ASTContext &ctx,
117-
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &vfs) {
115+
std::pair<clang::driver::Driver,
116+
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>>
117+
ClangImporter::createClangDriver(
118+
const LangOptions &LangOpts, const ClangImporterOptions &ClangImporterOpts,
119+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs) {
120+
auto *silentDiagConsumer = new clang::DiagnosticConsumer();
118121
auto clangDiags = clang::CompilerInstance::createDiagnostics(
119-
new clang::DiagnosticOptions());
120-
clang::driver::Driver clangDriver(ctx.ClangImporterOpts.clangPath,
121-
ctx.LangOpts.Target.str(), *clangDiags,
122+
new clang::DiagnosticOptions(), silentDiagConsumer);
123+
clang::driver::Driver clangDriver(ClangImporterOpts.clangPath,
124+
LangOpts.Target.str(), *clangDiags,
122125
"clang LLVM compiler", vfs);
123-
return clangDriver;
126+
return {std::move(clangDriver), clangDiags};
124127
}
125128

126129
/// Given a list of include paths and a list of file names, finds the first
@@ -162,21 +165,23 @@ static std::optional<Path> findFirstIncludeDir(
162165
return std::nullopt;
163166
}
164167

165-
static llvm::opt::InputArgList
166-
createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) {
168+
llvm::opt::InputArgList
169+
ClangImporter::createClangArgs(const ClangImporterOptions &ClangImporterOpts,
170+
const SearchPathOptions &SearchPathOpts,
171+
clang::driver::Driver &clangDriver) {
167172
// Flags passed to Swift with `-Xcc` might affect include paths.
168173
std::vector<const char *> clangArgs;
169-
for (const auto &each : ctx.ClangImporterOpts.ExtraArgs) {
174+
for (const auto &each : ClangImporterOpts.ExtraArgs) {
170175
clangArgs.push_back(each.c_str());
171176
}
172177
llvm::opt::InputArgList clangDriverArgs =
173178
parseClangDriverArgs(clangDriver, clangArgs);
174179
// If an SDK path was explicitly passed to Swift, make sure to pass it to
175180
// Clang driver as well. It affects the resulting include paths.
176-
auto sdkPath = ctx.SearchPathOpts.getSDKPath();
181+
auto sdkPath = SearchPathOpts.getSDKPath();
177182
if (!sdkPath.empty())
178183
clangDriver.SysRoot = sdkPath.str();
179-
if (auto sysroot = ctx.SearchPathOpts.getSysRoot())
184+
if (auto sysroot = SearchPathOpts.getSysRoot())
180185
clangDriver.SysRoot = sysroot->str();
181186
return clangDriverArgs;
182187
}
@@ -188,8 +193,10 @@ getLibcFileMapping(ASTContext &ctx, StringRef modulemapFileName,
188193
const llvm::Triple &triple = ctx.LangOpts.Target;
189194

190195
// Extract the libc path from Clang driver.
191-
auto clangDriver = createClangDriver(ctx, vfs);
192-
auto clangDriverArgs = createClangArgs(ctx, clangDriver);
196+
auto [clangDriver, clangDiagEngine] = ClangImporter::createClangDriver(
197+
ctx.LangOpts, ctx.ClangImporterOpts, vfs);
198+
auto clangDriverArgs = ClangImporter::createClangArgs(
199+
ctx.ClangImporterOpts, ctx.SearchPathOpts, clangDriver);
193200

194201
llvm::opt::ArgStringList includeArgStrings;
195202
const auto &clangToolchain =
@@ -262,8 +269,10 @@ static void getLibStdCxxFileMapping(
262269
return;
263270

264271
// Extract the libstdc++ installation path from Clang driver.
265-
auto clangDriver = createClangDriver(ctx, vfs);
266-
auto clangDriverArgs = createClangArgs(ctx, clangDriver);
272+
auto [clangDriver, clangDiagEngine] = ClangImporter::createClangDriver(
273+
ctx.LangOpts, ctx.ClangImporterOpts, vfs);
274+
auto clangDriverArgs = ClangImporter::createClangArgs(
275+
ctx.ClangImporterOpts, ctx.SearchPathOpts, clangDriver);
267276

268277
llvm::opt::ArgStringList stdlibArgStrings;
269278
const auto &clangToolchain =
@@ -457,8 +466,10 @@ SmallVector<std::pair<std::string, std::string>, 2> GetWindowsFileMappings(
457466
if (!Triple.isWindowsMSVCEnvironment())
458467
return Mappings;
459468

460-
clang::driver::Driver Driver = createClangDriver(Context, driverVFS);
461-
const llvm::opt::InputArgList Args = createClangArgs(Context, Driver);
469+
auto [Driver, clangDiagEngine] = ClangImporter::createClangDriver(
470+
Context.LangOpts, Context.ClangImporterOpts, driverVFS);
471+
const llvm::opt::InputArgList Args = ClangImporter::createClangArgs(
472+
Context.ClangImporterOpts, Context.SearchPathOpts, Driver);
462473
const clang::driver::ToolChain &ToolChain = Driver.getToolChain(Args, Triple);
463474
llvm::vfs::FileSystem &VFS = ToolChain.getVFS();
464475

lib/Frontend/CompilerInvocation.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "clang/Driver/Driver.h"
1314
#include "swift/AST/SILOptions.h"
1415
#include "swift/Basic/DiagnosticOptions.h"
1516
#include "swift/Frontend/Frontend.h"
@@ -335,6 +336,22 @@ setBridgingHeaderFromFrontendOptions(ClangImporterOptions &ImporterOpts,
335336
FrontendOpts.InputsAndOutputs.getFilenameOfFirstInput();
336337
}
337338

339+
static void setCXXStdlibOpts(LangOptions &LangOpts,
340+
const ClangImporterOptions &ClangImporterOpts,
341+
const SearchPathOptions &SearchPathOpts) {
342+
auto [clangDriver, clangDiagEngine] =
343+
ClangImporter::createClangDriver(LangOpts, ClangImporterOpts);
344+
auto clangDriverArgs = ClangImporter::createClangArgs(
345+
ClangImporterOpts, SearchPathOpts, clangDriver);
346+
auto &clangToolchain =
347+
clangDriver.getToolChain(clangDriverArgs, LangOpts.Target);
348+
auto cxxStdlibKind = clangToolchain.GetCXXStdlibType(clangDriverArgs);
349+
if (LangOpts.Target.isOSLinux() &&
350+
cxxStdlibKind == clang::driver::ToolChain::CST_Libcxx) {
351+
LangOpts.CXXStdlib = CXXStdlibKind::OverrideLibcxx;
352+
}
353+
}
354+
338355
void CompilerInvocation::setRuntimeResourcePath(StringRef Path) {
339356
SearchPathOpts.RuntimeResourcePath = Path.str();
340357
updateRuntimeLibraryPaths(SearchPathOpts, FrontendOpts, LangOpts);
@@ -627,16 +644,6 @@ void LangOptions::setCxxInteropFromArgs(ArgList &Args,
627644
cxxInteropCompatVersion =
628645
validateCxxInteropCompatibilityMode("swift-5.9").second;
629646
}
630-
631-
for (const Arg *A : Args.filtered(options::OPT_Xcc)) {
632-
StringRef clangArg = A->getValue();
633-
if (clangArg.consume_front("-stdlib")) {
634-
clangArg.consume_front("=");
635-
if (clangArg.equals("libc++") && Target.isOSLinux())
636-
CXXStdlib = CXXStdlibKind::OverrideLibcxx;
637-
// If the stdlib argument is invalid, Clang will emit an error.
638-
}
639-
}
640647
}
641648

642649
static std::optional<swift::StrictConcurrency>
@@ -3602,6 +3609,7 @@ bool CompilerInvocation::parseArgs(
36023609
// Now that we've parsed everything, setup some inter-option-dependent state.
36033610
setIRGenOutputOptsFromFrontendOptions(IRGenOpts, FrontendOpts);
36043611
setBridgingHeaderFromFrontendOptions(ClangImporterOpts, FrontendOpts);
3612+
setCXXStdlibOpts(LangOpts, ClangImporterOpts, SearchPathOpts);
36053613
if (LangOpts.hasFeature(Feature::Embedded)) {
36063614
IRGenOpts.InternalizeAtLink = true;
36073615
IRGenOpts.DisableLegacyTypeInfo = true;

0 commit comments

Comments
 (0)