Skip to content

Commit 208e9ed

Browse files
[lldb] Fix SwiftASTContext creatiion when swift caching is used
Followup to swiftlang#9088, handle the cc1 flag deserialization when swift caching is enabled. LLDB should ignore all the CAS related options from embedded flags since LLDB doesn't receive the correct CAS configuration and should just load the modules from disk directly. rdar://134090397 (cherry picked from commit 1162e50)
1 parent c650ca1 commit 208e9ed

File tree

10 files changed

+135
-22
lines changed

10 files changed

+135
-22
lines changed

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "clang/Basic/TargetOptions.h"
5858
#include "clang/Driver/Driver.h"
5959
#include "clang/Frontend/CompilerInstance.h"
60+
#include "clang/Frontend/TextDiagnosticPrinter.h"
6061
#include "clang/Lex/Preprocessor.h"
6162

6263
#include "clang/Lex/PreprocessorOptions.h"
@@ -1573,21 +1574,7 @@ bool ShouldUnique(StringRef arg) {
15731574

15741575
// static
15751576
void SwiftASTContext::AddExtraClangArgs(const std::vector<std::string> &source,
1576-
std::vector<std::string> &dest,
1577-
bool cc1) {
1578-
// FIXME: Support for cc1 flags isn't complete. The uniquing
1579-
// algortihm below does not work for cc1 flags. Since cc1 flags are
1580-
// not stable it's not feasible to keep a list of all multi-arg
1581-
// flags, for example. It also makes it difficult to correctly
1582-
// identify where workng directories and path remappings should
1583-
// applied. For all these reasons, using cc1 flags for anything but
1584-
// a local build with explicit modules and precise compiler
1585-
// invocations isn't supported yet.
1586-
if (cc1) {
1587-
dest.insert(dest.end(), source.begin(), source.end());
1588-
return;
1589-
}
1590-
1577+
std::vector<std::string> &dest) {
15911578
llvm::StringSet<> unique_flags;
15921579
for (auto &arg : dest)
15931580
unique_flags.insert(arg);
@@ -1779,8 +1766,14 @@ void SwiftASTContext::AddExtraClangArgs(
17791766
eSeverityWarning,
17801767
"Mixing and matching of driver and cc1 Clang options detected");
17811768

1782-
AddExtraClangArgs(ExtraArgs, importer_options.ExtraArgs,
1783-
importer_options.DirectClangCC1ModuleBuild);
1769+
// If using direct cc1 flags, compute the arguments and return.
1770+
// Since this is cc1 flags, no driver overwrite can be applied.
1771+
if (importer_options.DirectClangCC1ModuleBuild) {
1772+
AddExtraClangCC1Args(ExtraArgs, importer_options.ExtraArgs);
1773+
return;
1774+
}
1775+
1776+
AddExtraClangArgs(ExtraArgs, importer_options.ExtraArgs);
17841777
applyOverrideOptions(importer_options.ExtraArgs, overrideOpts);
17851778
if (HasNonexistentExplicitModule(importer_options.ExtraArgs))
17861779
RemoveExplicitModules(importer_options.ExtraArgs);
@@ -1792,6 +1785,69 @@ void SwiftASTContext::AddExtraClangArgs(
17921785
});
17931786
}
17941787

1788+
void SwiftASTContext::AddExtraClangCC1Args(
1789+
const std::vector<std::string> &source, std::vector<std::string> &dest) {
1790+
clang::CompilerInvocation invocation;
1791+
llvm::SmallVector<const char *> clangArgs;
1792+
clangArgs.reserve(source.size());
1793+
llvm::for_each(source, [&](const std::string &Arg) {
1794+
clangArgs.push_back(Arg.c_str());
1795+
});
1796+
1797+
std::string diags;
1798+
llvm::raw_string_ostream os(diags);
1799+
auto diagOpts = llvm::makeIntrusiveRefCnt<clang::DiagnosticOptions>();
1800+
clang::DiagnosticsEngine clangDiags(
1801+
new clang::DiagnosticIDs(), diagOpts,
1802+
new clang::TextDiagnosticPrinter(os, diagOpts.get()));
1803+
1804+
if (!clang::CompilerInvocation::CreateFromArgs(invocation, clangArgs,
1805+
clangDiags)) {
1806+
// If cc1 arguments failed to parse, report diagnostics and return
1807+
// immediately.
1808+
AddDiagnostic(eSeverityError, diags);
1809+
// Disable direct-cc1 build as fallback.
1810+
GetClangImporterOptions().DirectClangCC1ModuleBuild = false;
1811+
return;
1812+
}
1813+
1814+
// Clear module cache key and other CAS options to load modules from disk
1815+
// directly.
1816+
invocation.getFrontendOpts().ModuleCacheKeys.clear();
1817+
invocation.getCASOpts() = clang::CASOptions();
1818+
1819+
// Remove non-existing modules in a systematic way.
1820+
bool module_missing = false;
1821+
auto CheckFileExists = [&](const char *file) {
1822+
if (!llvm::sys::fs::exists(file)) {
1823+
std::string m_description;
1824+
HEALTH_LOG_PRINTF("Nonexistent explicit module file %s", file);
1825+
module_missing = true;
1826+
}
1827+
};
1828+
llvm::for_each(invocation.getHeaderSearchOpts().PrebuiltModuleFiles,
1829+
[&](const auto &mod) { CheckFileExists(mod.second.c_str()); });
1830+
llvm::for_each(invocation.getFrontendOpts().ModuleFiles,
1831+
[&](const auto &mod) { CheckFileExists(mod.c_str()); });
1832+
1833+
// If missing, clear all the prebuilt module options and use implicit module
1834+
// build.
1835+
if (module_missing) {
1836+
invocation.getHeaderSearchOpts().PrebuiltModuleFiles.clear();
1837+
invocation.getFrontendOpts().ModuleFiles.clear();
1838+
invocation.getLangOpts().ImplicitModules = true;
1839+
invocation.getHeaderSearchOpts().ImplicitModuleMaps = true;
1840+
}
1841+
1842+
invocation.generateCC1CommandLine(
1843+
[&](const llvm::Twine &arg) { dest.push_back(arg.str()); });
1844+
1845+
// If cc1 arguments are parsed and generated correctly, set explicitly-built
1846+
// module since only explicit module build can use direct cc1 mode.
1847+
m_has_explicit_modules = true;
1848+
return;
1849+
}
1850+
17951851
void SwiftASTContext::AddUserClangArgs(TargetProperties &props) {
17961852
Args args(props.GetSwiftExtraClangFlags());
17971853
std::vector<std::string> user_clang_flags;

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,10 @@ class SwiftASTContext : public TypeSystemSwift {
283283
/// apply the working directory to any relative paths.
284284
void AddExtraClangArgs(const std::vector<std::string> &ExtraArgs,
285285
llvm::StringRef overrideOpts = "");
286+
void AddExtraClangCC1Args(const std::vector<std::string>& source,
287+
std::vector<std::string>& dest);
286288
static void AddExtraClangArgs(const std::vector<std::string>& source,
287-
std::vector<std::string>& dest, bool cc1);
289+
std::vector<std::string>& dest);
288290
static std::string GetPluginServer(llvm::StringRef plugin_library_path);
289291
/// Removes nonexisting VFS overlay options.
290292
static void FilterClangImporterOptions(std::vector<std::string> &extra_args,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFT_ENABLE_EXPLICIT_MODULES := YES
3+
SWIFTFLAGS_EXTRAS = -I$(SRCDIR) -cache-compile-job -cas-path $(BUILDDIR)/cas
4+
5+
include Makefile.rules
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
class TestSwiftClangImporterCaching(TestBase):
8+
9+
NO_DEBUG_INFO_TESTCASE = True
10+
11+
# Don't run ClangImporter tests if Clangimporter is disabled.
12+
@skipIf(setting=('symbols.use-swift-clangimporter', 'false'))
13+
@skipIf(setting=('symbols.swift-precise-compiler-invocation', 'false'))
14+
@skipIf(setting=('plugin.typesystem.clang.experimental-redecl-completion', 'true'), bugnumber='rdar://128094135')
15+
@skipUnlessDarwin
16+
@swiftTest
17+
def test(self):
18+
"""
19+
Test flipping on/off implicit modules.
20+
"""
21+
self.build()
22+
lldbutil.run_to_source_breakpoint(self, "break here",
23+
lldb.SBFileSpec('main.swift'))
24+
log = self.getBuildArtifact("types.log")
25+
self.expect('log enable lldb types -f "%s"' % log)
26+
self.expect("expression obj", DATA_TYPES_DISPLAYED_CORRECTLY,
27+
substrs=["b ="])
28+
self.filecheck('platform shell cat "%s"' % log, __file__)
29+
### -cc1 should be round-tripped so there is no more `-cc1` in the extra args. Look for `-triple` which is a cc1 flag.
30+
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift")::LogConfiguration() -- -triple
31+
# CHECK-NOT: -cc1
32+
# CHECK-NOT: -fmodule-file-cache-key
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "b.h"
2+
3+
struct A {
4+
struct B b;
5+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct B {};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import ClangA
2+
let obj = A()
3+
print("break here \(obj)")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module ClangA {
2+
header "a.h"
3+
}
4+
5+
module ClangB {
6+
header "b.h"
7+
}

lldb/test/API/lang/swift/clangimporter/explicit_cc1/TestSwiftClangImporterExplicitCC1.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ def test(self):
2626
self.expect("expression obj", DATA_TYPES_DISPLAYED_CORRECTLY,
2727
substrs=["b ="])
2828
self.filecheck('platform shell cat "%s"' % log, __file__)
29-
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift")::LogConfiguration() -- -cc1
29+
### -cc1 should be round-tripped so there is no more `-cc1` in the extra args. Look for `-triple` which is a cc1 flag.
30+
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift")::LogConfiguration() -- -triple
31+
# CHECK-NOT: -cc1

lldb/unittests/Symbol/TestSwiftASTContext.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,15 +234,15 @@ const std::vector<std::string> uniqued_flags = {
234234
TEST_F(ClangArgs, UniquingCollisionWithExistingFlags) {
235235
const std::vector<std::string> source = duplicated_flags;
236236
std::vector<std::string> dest = uniqued_flags;
237-
SwiftASTContext::AddExtraClangArgs(source, dest, false);
237+
SwiftASTContext::AddExtraClangArgs(source, dest);
238238

239239
EXPECT_EQ(dest, uniqued_flags);
240240
}
241241

242242
TEST_F(ClangArgs, UniquingCollisionWithAddedFlags) {
243243
const std::vector<std::string> source = duplicated_flags;
244244
std::vector<std::string> dest;
245-
SwiftASTContext::AddExtraClangArgs(source, dest, false);
245+
SwiftASTContext::AddExtraClangArgs(source, dest);
246246

247247
EXPECT_EQ(dest, uniqued_flags);
248248
}
@@ -251,7 +251,7 @@ TEST_F(ClangArgs, DoubleDash) {
251251
// -v with all currently ignored arguments following.
252252
const std::vector<std::string> source{"-v", "--", "-Werror", ""};
253253
std::vector<std::string> dest;
254-
SwiftASTContext::AddExtraClangArgs(source, dest, false);
254+
SwiftASTContext::AddExtraClangArgs(source, dest);
255255

256256
// Check that all ignored arguments got removed.
257257
EXPECT_EQ(dest, std::vector<std::string>({"-v"}));

0 commit comments

Comments
 (0)