Skip to content

Commit 59063e9

Browse files
committed
[lldb][ClangExpressionParser] Set BuiltinHeadersInSystemModules depending on SDK version
This patch changes the way we initialize `BuiltinHeadersInSystemModules` which is one of the flags controlling Clang's behaviour when the Darwin module is split into more fine-grained modules. The ClangExpressionParser currently unconditionally sets `-fbuiltin-headers-in-system-modules` when evaluating expressions with the `target.import-std-module` setting. This flag should, however, be set depending on the SDK version (which is what the Clang Darwin toolchain does). Unfortunately, the compiler instance that we create with `ClangExpressionParser` never consults the Clang driver, and thus doesn't correctly infer `BuiltinHeadersInSystemModules`. Note, this isn't an issue with the `CompilerInstance` that the `ClangModulesDeclVendor` creates because it uses the `createInovcation` API, which calls into `Darwin::addClangTargetOptions`. This patch mimicks how `sdkSupportsBuiltinModules` is used in `Darwin::addClangTargetOptions`. This ensures that the `import-std-module` API tests run cleanly regardless of SDK version. The plan is to eventually make the `CompilerInstance` construction in `ClangExpressionParser` go through the driver, so we can avoid duplicating the logic in LLDB. But we aren't there yet. **Implementation** * We look for the `SDKSettings.json` in the sysroot directory that we found in DWARF (via `DW_AT_LLVM_sysroot`) * Then parse this file and extract the SDK version number out of it * Then mimick `sdkSupportsBuiltinModules` from `Toolchains/Darwin.cpp` and set `BuiltinHeadersInSystemModules` based on it rdar://116490281
1 parent c848250 commit 59063e9

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "clang/AST/ExternalASTSource.h"
1212
#include "clang/AST/PrettyPrinter.h"
1313
#include "clang/Basic/Builtins.h"
14+
#include "clang/Basic/DarwinSDKInfo.h"
1415
#include "clang/Basic/DiagnosticIDs.h"
1516
#include "clang/Basic/SourceLocation.h"
1617
#include "clang/Basic/TargetInfo.h"
@@ -352,6 +353,73 @@ static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
352353
}
353354
}
354355

356+
// NOTE: should be kept in sync with sdkSupportsBuiltinModules in
357+
// Toolchains/Darwin.cpp
358+
static bool
359+
sdkSupportsBuiltinModulesImpl(const llvm::Triple &triple,
360+
const std::optional<DarwinSDKInfo> &SDKInfo) {
361+
if (!SDKInfo)
362+
return false;
363+
364+
VersionTuple SDKVersion = SDKInfo->getVersion();
365+
switch (triple.getOS()) {
366+
case Triple::OSType::MacOSX:
367+
return SDKVersion >= VersionTuple(15U);
368+
case Triple::OSType::IOS:
369+
return SDKVersion >= VersionTuple(18U);
370+
case Triple::OSType::TvOS:
371+
return SDKVersion >= VersionTuple(18U);
372+
case Triple::OSType::WatchOS:
373+
return SDKVersion >= VersionTuple(11U);
374+
case Triple::OSType::XROS:
375+
return SDKVersion >= VersionTuple(2U);
376+
default:
377+
// New SDKs support builtin modules from the start.
378+
return true;
379+
}
380+
}
381+
382+
/// Returns true if the SDK for the specified triple supports
383+
/// builtin modules in system headers. This is used to decide
384+
/// whether to pass -fbuiltin-headers-in-system-modules to
385+
/// the compiler instance when compiling the `std` module.
386+
///
387+
/// This function assumes one of the directories in \ref include_dirs
388+
/// is an SDK path that exists on the host. The SDK version is
389+
/// read from the SDKSettings.json in that directory.
390+
///
391+
/// \param[in] triple The target triple.
392+
/// \param[in] include_dirs The include directories the compiler will use
393+
/// during header search.
394+
///
395+
static bool
396+
sdkSupportsBuiltinModules(llvm::Triple const &triple,
397+
std::vector<std::string> const &include_dirs) {
398+
// Find an SDK directory.
399+
static constexpr std::string_view s_sdk_suffix = ".sdk";
400+
auto it = llvm::find_if(include_dirs, [](std::string const &path) {
401+
return path.find(s_sdk_suffix) != std::string::npos;
402+
});
403+
if (it == include_dirs.end())
404+
return false;
405+
406+
auto VFS = FileSystem::Instance().GetVirtualFileSystem();
407+
if (!VFS)
408+
return false;
409+
410+
// Extract: /path/to/some.sdk
411+
size_t suffix = it->find(s_sdk_suffix);
412+
assert(suffix != std::string::npos);
413+
std::string sdk_path = it->substr(0, suffix + s_sdk_suffix.size());
414+
415+
// Extract SDK version from the /path/to/some.sdk/SDKSettings.json
416+
auto parsed = clang::parseDarwinSDKInfo(*VFS, sdk_path);
417+
if (!parsed)
418+
return false;
419+
420+
return sdkSupportsBuiltinModulesImpl(triple, *parsed);
421+
}
422+
355423
//===----------------------------------------------------------------------===//
356424
// Implementation of ClangExpressionParser
357425
//===----------------------------------------------------------------------===//
@@ -576,7 +644,8 @@ ClangExpressionParser::ClangExpressionParser(
576644
lang_opts.GNUMode = true;
577645
lang_opts.GNUKeywords = true;
578646
lang_opts.CPlusPlus11 = true;
579-
lang_opts.BuiltinHeadersInSystemModules = true;
647+
lang_opts.BuiltinHeadersInSystemModules = !sdkSupportsBuiltinModules(
648+
target_sp->GetArchitecture().GetTriple(), m_include_directories);
580649

581650
// The Darwin libc expects this macro to be set.
582651
lang_opts.GNUCVersion = 40201;

0 commit comments

Comments
 (0)