forked from OSchip/llvm-project
[lldb][import-std-module] Do some basic file checks before trying to import a module
Currently when LLDB has enough data in the debug information to import the `std` module, it will just try to import it. However when debugging libraries where the sources aren't available anymore, importing the module will generate a confusing diagnostic that the module couldn't be built. For the fallback mode (where we retry failed expressions with the loaded module), this will cause the second expression to fail with a module built error instead of the actual parsing issue in the user expression. This patch adds checks that ensures that we at least have any source files in the found include paths before we try to import the module. This prevents the module from being loaded in the situation described above which means we don't emit the bogus 'can't import module' diagnostic and also don't waste any time retrying the expression in the fallback mode. For the unit tests I did some refactoring as they now require a VFS with the files in it and not just the paths. The Python test just builds a binary with a fake C++ module, then deletes the module before debugging. Fixes rdar://73264458 Reviewed By: JDevlieghere Differential Revision: https://reviews.llvm.org/D95096
This commit is contained in:
parent
ff41ae8b36
commit
99b7b41edf
|
@ -57,9 +57,38 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Utility function for just appending two paths.
|
||||||
|
static std::string MakePath(llvm::StringRef lhs, llvm::StringRef rhs) {
|
||||||
|
llvm::SmallString<256> result(lhs);
|
||||||
|
llvm::sys::path::append(result, rhs);
|
||||||
|
return std::string(result);
|
||||||
|
}
|
||||||
|
|
||||||
bool CppModuleConfiguration::hasValidConfig() {
|
bool CppModuleConfiguration::hasValidConfig() {
|
||||||
// We all these include directories to have a valid usable configuration.
|
// We need to have a C and C++ include dir for a valid configuration.
|
||||||
return m_c_inc.Valid() && m_std_inc.Valid();
|
if (!m_c_inc.Valid() || !m_std_inc.Valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Do some basic sanity checks on the directories that we don't activate
|
||||||
|
// the module when it's clear that it's not usable.
|
||||||
|
const std::vector<std::string> files_to_check = {
|
||||||
|
// * Check that the C library contains at least one random C standard
|
||||||
|
// library header.
|
||||||
|
MakePath(m_c_inc.Get(), "stdio.h"),
|
||||||
|
// * Without a libc++ modulemap file we can't have a 'std' module that
|
||||||
|
// could be imported.
|
||||||
|
MakePath(m_std_inc.Get(), "module.modulemap"),
|
||||||
|
// * Check for a random libc++ header (vector in this case) that has to
|
||||||
|
// exist in a working libc++ setup.
|
||||||
|
MakePath(m_std_inc.Get(), "vector"),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (llvm::StringRef file_to_check : files_to_check) {
|
||||||
|
if (!FileSystem::Instance().Exists(file_to_check))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CppModuleConfiguration::CppModuleConfiguration(
|
CppModuleConfiguration::CppModuleConfiguration(
|
||||||
|
@ -78,7 +107,8 @@ CppModuleConfiguration::CppModuleConfiguration(
|
||||||
m_resource_inc = std::string(resource_dir.str());
|
m_resource_inc = std::string(resource_dir.str());
|
||||||
|
|
||||||
// This order matches the way Clang orders these directories.
|
// This order matches the way Clang orders these directories.
|
||||||
m_include_dirs = {m_std_inc.Get(), m_resource_inc, m_c_inc.Get()};
|
m_include_dirs = {m_std_inc.Get().str(), m_resource_inc,
|
||||||
|
m_c_inc.Get().str()};
|
||||||
m_imported_modules = {"std"};
|
m_imported_modules = {"std"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class CppModuleConfiguration {
|
||||||
/// the path was already set.
|
/// the path was already set.
|
||||||
LLVM_NODISCARD bool TrySet(llvm::StringRef path);
|
LLVM_NODISCARD bool TrySet(llvm::StringRef path);
|
||||||
/// Return the path if there is one.
|
/// Return the path if there is one.
|
||||||
std::string Get() const {
|
llvm::StringRef Get() const {
|
||||||
assert(m_valid && "Called Get() on an invalid SetOncePath?");
|
assert(m_valid && "Called Get() on an invalid SetOncePath?");
|
||||||
return m_path;
|
return m_path;
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,6 @@ class CppModuleConfiguration {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Creates a configuration by analyzing the given list of used source files.
|
/// Creates a configuration by analyzing the given list of used source files.
|
||||||
///
|
|
||||||
/// Currently only looks at the used paths and doesn't actually access the
|
|
||||||
/// files on the disk.
|
|
||||||
explicit CppModuleConfiguration(const FileSpecList &support_files);
|
explicit CppModuleConfiguration(const FileSpecList &support_files);
|
||||||
/// Creates an empty and invalid configuration.
|
/// Creates an empty and invalid configuration.
|
||||||
CppModuleConfiguration() {}
|
CppModuleConfiguration() {}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// library module so the actual contents of the module are missing.
|
// library module so the actual contents of the module are missing.
|
||||||
#ifdef ENABLE_STD_CONTENT
|
#ifdef ENABLE_STD_CONTENT
|
||||||
|
|
||||||
#include "libc_header.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
inline namespace __1 {
|
inline namespace __1 {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "libc_header.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
inline namespace __1 {
|
inline namespace __1 {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
# We don't have any standard include directories, so we can't
|
||||||
|
# parse the test_common.h header we usually inject as it includes
|
||||||
|
# system headers.
|
||||||
|
NO_TEST_COMMON_H := 1
|
||||||
|
|
||||||
|
# Take the libc++ from the build directory (which will be later deleted).
|
||||||
|
CXXFLAGS_EXTRAS = -I $(BUILDDIR)/root/usr/include/c++/v1/ -I $(BUILDDIR)/root/usr/include/ -nostdinc -nostdinc++
|
||||||
|
CXX_SOURCES := main.cpp
|
||||||
|
|
||||||
|
include Makefile.rules
|
|
@ -0,0 +1,60 @@
|
||||||
|
"""
|
||||||
|
Check that missing module source files are correctly handled by LLDB.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from lldbsuite.test.decorators import *
|
||||||
|
from lldbsuite.test.lldbtest import *
|
||||||
|
from lldbsuite.test import lldbutil
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
class TestCase(TestBase):
|
||||||
|
|
||||||
|
mydir = TestBase.compute_mydir(__file__)
|
||||||
|
|
||||||
|
# We only emulate a fake libc++ in this test and don't use the real libc++,
|
||||||
|
# but we still add the libc++ category so that this test is only run in
|
||||||
|
# test configurations where libc++ is actually supposed to be tested.
|
||||||
|
@add_test_categories(["libc++"])
|
||||||
|
@skipIf(compiler=no_match("clang"))
|
||||||
|
def test(self):
|
||||||
|
# The path to our temporary target root that contains the temporary
|
||||||
|
# module sources.
|
||||||
|
target_sysroot = self.getBuildArtifact("root")
|
||||||
|
|
||||||
|
# Copy the sources to the root.
|
||||||
|
shutil.copytree(self.getSourcePath("root"), target_sysroot)
|
||||||
|
# Build the binary with the copied sources.
|
||||||
|
self.build()
|
||||||
|
# Delete the copied sources so that they are now unavailable.
|
||||||
|
shutil.rmtree(target_sysroot)
|
||||||
|
|
||||||
|
# Set the sysroot where our dummy libc++ used to exist. Just to make
|
||||||
|
# sure we don't find some existing headers on the system that could
|
||||||
|
# XPASS this test.
|
||||||
|
self.runCmd("platform select --sysroot '" + target_sysroot + "' host")
|
||||||
|
|
||||||
|
lldbutil.run_to_source_breakpoint(self,
|
||||||
|
"// Set break point at this line.",
|
||||||
|
lldb.SBFileSpec("main.cpp"))
|
||||||
|
|
||||||
|
# Import the std C++ module and run an expression.
|
||||||
|
# As we deleted the sources, LLDB should refuse the load the module
|
||||||
|
# and just print the normal error we get from the expression.
|
||||||
|
self.runCmd("settings set target.import-std-module true")
|
||||||
|
self.expect("expr v.unknown_identifier", error=True,
|
||||||
|
substrs=["no member named 'unknown_identifier'"])
|
||||||
|
# Check that there is no confusing error about failing to build the
|
||||||
|
# module.
|
||||||
|
self.expect("expr v.unknown_identifier", error=True, matching=False,
|
||||||
|
substrs=["could not build module 'std'"])
|
||||||
|
|
||||||
|
# Test the fallback mode. It should also just print the normal
|
||||||
|
# error but not mention a failed module build.
|
||||||
|
self.runCmd("settings set target.import-std-module fallback")
|
||||||
|
|
||||||
|
self.expect("expr v.unknown_identifier", error=True,
|
||||||
|
substrs=["no member named 'unknown_identifier'"])
|
||||||
|
self.expect("expr v.unknown_identifier", error=True, matching=False,
|
||||||
|
substrs=["could not build module 'std'"])
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
// Makes sure we have the mock libc headers in the debug information.
|
||||||
|
libc_struct s;
|
||||||
|
std::vector<int> v;
|
||||||
|
return 0; // Set break point at this line.
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module std {
|
||||||
|
module "vector" { header "vector" export * }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
inline namespace __1 {
|
||||||
|
template<typename T>
|
||||||
|
struct vector {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
#include "libc_header.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
// Makes sure we get a support file for this header.
|
// Makes sure we get a support file for this header.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
struct libc_struct {};
|
|
@ -11,6 +11,7 @@
|
||||||
#include "TestingSupport/SubsystemRAII.h"
|
#include "TestingSupport/SubsystemRAII.h"
|
||||||
#include "lldb/Host/FileSystem.h"
|
#include "lldb/Host/FileSystem.h"
|
||||||
#include "lldb/Host/HostInfo.h"
|
#include "lldb/Host/HostInfo.h"
|
||||||
|
#include "llvm/Support/SmallVectorMemoryBuffer.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
@ -19,7 +20,33 @@ using namespace lldb_private;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct CppModuleConfigurationTest : public testing::Test {
|
struct CppModuleConfigurationTest : public testing::Test {
|
||||||
SubsystemRAII<FileSystem, HostInfo> subsystems;
|
llvm::MemoryBufferRef m_empty_buffer;
|
||||||
|
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> m_fs;
|
||||||
|
|
||||||
|
CppModuleConfigurationTest()
|
||||||
|
: m_empty_buffer("", "<empty buffer>"),
|
||||||
|
m_fs(new llvm::vfs::InMemoryFileSystem()) {}
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
FileSystem::Initialize(m_fs);
|
||||||
|
HostInfo::Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
HostInfo::Terminate();
|
||||||
|
FileSystem::Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Utility function turning a list of paths into a FileSpecList.
|
||||||
|
FileSpecList makeFiles(llvm::ArrayRef<std::string> paths) {
|
||||||
|
FileSpecList result;
|
||||||
|
for (const std::string &path : paths) {
|
||||||
|
result.Append(FileSpec(path, FileSpec::Style::posix));
|
||||||
|
if (!m_fs->addFileNoOwn(path, static_cast<time_t>(0), m_empty_buffer))
|
||||||
|
llvm_unreachable("Invalid test configuration?");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -31,20 +58,18 @@ static std::string ResourceInc() {
|
||||||
return std::string(resource_dir);
|
return std::string(resource_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility function turningn a list of paths into a FileSpecList.
|
|
||||||
static FileSpecList makeFiles(llvm::ArrayRef<std::string> paths) {
|
|
||||||
FileSpecList result;
|
|
||||||
for (const std::string &path : paths)
|
|
||||||
result.Append(FileSpec(path, FileSpec::Style::posix));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, Linux) {
|
TEST_F(CppModuleConfigurationTest, Linux) {
|
||||||
// Test the average Linux configuration.
|
// Test the average Linux configuration.
|
||||||
std::string libcpp = "/usr/include/c++/v1";
|
|
||||||
std::string usr = "/usr/include";
|
std::string usr = "/usr/include";
|
||||||
CppModuleConfiguration config(
|
std::string libcpp = "/usr/include/c++/v1";
|
||||||
makeFiles({usr + "/bits/types.h", libcpp + "/vector"}));
|
std::vector<std::string> files = {// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
||||||
|
@ -52,10 +77,15 @@ TEST_F(CppModuleConfigurationTest, Linux) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, Sysroot) {
|
TEST_F(CppModuleConfigurationTest, Sysroot) {
|
||||||
// Test that having a sysroot for the whole system works fine.
|
// Test that having a sysroot for the whole system works fine.
|
||||||
|
|
||||||
std::string libcpp = "/home/user/sysroot/usr/include/c++/v1";
|
std::string libcpp = "/home/user/sysroot/usr/include/c++/v1";
|
||||||
std::string usr = "/home/user/sysroot/usr/include";
|
std::string usr = "/home/user/sysroot/usr/include";
|
||||||
CppModuleConfiguration config(
|
std::vector<std::string> files = {// C library
|
||||||
makeFiles({usr + "/bits/types.h", libcpp + "/vector"}));
|
usr + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
||||||
|
@ -63,10 +93,15 @@ TEST_F(CppModuleConfigurationTest, Sysroot) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) {
|
TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) {
|
||||||
// Test that a locally build libc++ is detected.
|
// Test that a locally build libc++ is detected.
|
||||||
std::string libcpp = "/home/user/llvm-build/include/c++/v1";
|
|
||||||
std::string usr = "/usr/include";
|
std::string usr = "/usr/include";
|
||||||
CppModuleConfiguration config(
|
std::string libcpp = "/home/user/llvm-build/include/c++/v1";
|
||||||
makeFiles({usr + "/bits/types.h", libcpp + "/vector"}));
|
std::vector<std::string> files = {// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
||||||
|
@ -74,10 +109,17 @@ TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) {
|
TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) {
|
||||||
// Test that having an unrelated library in /usr/include doesn't break.
|
// Test that having an unrelated library in /usr/include doesn't break.
|
||||||
std::string libcpp = "/home/user/llvm-build/include/c++/v1";
|
|
||||||
std::string usr = "/usr/include";
|
std::string usr = "/usr/include";
|
||||||
CppModuleConfiguration config(makeFiles(
|
std::string libcpp = "/home/user/llvm-build/include/c++/v1";
|
||||||
{usr + "/bits/types.h", libcpp + "/vector", usr + "/boost/vector"}));
|
std::vector<std::string> files = {// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// unrelated library
|
||||||
|
usr + "/boost/vector",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
||||||
|
@ -85,12 +127,19 @@ TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, Xcode) {
|
TEST_F(CppModuleConfigurationTest, Xcode) {
|
||||||
// Test detection of libc++ coming from Xcode with generic platform names.
|
// Test detection of libc++ coming from Xcode with generic platform names.
|
||||||
|
|
||||||
std::string p = "/Applications/Xcode.app/Contents/Developer/";
|
std::string p = "/Applications/Xcode.app/Contents/Developer/";
|
||||||
std::string libcpp = p + "Toolchains/B.xctoolchain/usr/include/c++/v1";
|
std::string libcpp = p + "Toolchains/B.xctoolchain/usr/include/c++/v1";
|
||||||
std::string usr =
|
std::string usr =
|
||||||
p + "Platforms/A.platform/Developer/SDKs/OSVers.sdk/usr/include";
|
p + "Platforms/A.platform/Developer/SDKs/OSVers.sdk/usr/include";
|
||||||
CppModuleConfiguration config(
|
std::vector<std::string> files = {
|
||||||
makeFiles({libcpp + "/unordered_map", usr + "/stdio.h"}));
|
// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap",
|
||||||
|
};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
testing::ElementsAre(libcpp, ResourceInc(), usr));
|
||||||
|
@ -98,8 +147,14 @@ TEST_F(CppModuleConfigurationTest, Xcode) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, LibCppV2) {
|
TEST_F(CppModuleConfigurationTest, LibCppV2) {
|
||||||
// Test that a "v2" of libc++ is still correctly detected.
|
// Test that a "v2" of libc++ is still correctly detected.
|
||||||
CppModuleConfiguration config(
|
|
||||||
makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v2/vector"}));
|
std::string libcpp = "/usr/include/c++/v2";
|
||||||
|
std::vector<std::string> files = {// C library
|
||||||
|
"/usr/include/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre("/usr/include/c++/v2", ResourceInc(),
|
testing::ElementsAre("/usr/include/c++/v2", ResourceInc(),
|
||||||
|
@ -109,8 +164,15 @@ TEST_F(CppModuleConfigurationTest, LibCppV2) {
|
||||||
TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) {
|
TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) {
|
||||||
// Test that having some unknown file in the libc++ path doesn't break
|
// Test that having some unknown file in the libc++ path doesn't break
|
||||||
// anything.
|
// anything.
|
||||||
CppModuleConfiguration config(makeFiles(
|
|
||||||
{"/usr/include/bits/types.h", "/usr/include/c++/v1/non_existing_file"}));
|
std::string libcpp = "/usr/include/c++/v1";
|
||||||
|
std::vector<std::string> files = {// C library
|
||||||
|
"/usr/include/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/non_existing_file",
|
||||||
|
libcpp + "/module.modulemap",
|
||||||
|
libcpp + "/vector"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
|
||||||
EXPECT_THAT(config.GetIncludeDirs(),
|
EXPECT_THAT(config.GetIncludeDirs(),
|
||||||
testing::ElementsAre("/usr/include/c++/v1", ResourceInc(),
|
testing::ElementsAre("/usr/include/c++/v1", ResourceInc(),
|
||||||
|
@ -119,22 +181,40 @@ TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) {
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, MissingUsrInclude) {
|
TEST_F(CppModuleConfigurationTest, MissingUsrInclude) {
|
||||||
// Test that we don't load 'std' if we can't find the C standard library.
|
// Test that we don't load 'std' if we can't find the C standard library.
|
||||||
CppModuleConfiguration config(makeFiles({"/usr/include/c++/v1/vector"}));
|
|
||||||
|
std::string libcpp = "/usr/include/c++/v1";
|
||||||
|
std::vector<std::string> files = {// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap"};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
||||||
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, MissingLibCpp) {
|
TEST_F(CppModuleConfigurationTest, MissingLibCpp) {
|
||||||
// Test that we don't load 'std' if we don't have a libc++.
|
// Test that we don't load 'std' if we don't have a libc++.
|
||||||
CppModuleConfiguration config(makeFiles({"/usr/include/bits/types.h"}));
|
|
||||||
|
std::string usr = "/usr/include";
|
||||||
|
std::vector<std::string> files = {
|
||||||
|
// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
||||||
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) {
|
TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) {
|
||||||
// Test that we don't do anything bad when we encounter libstdc++ paths.
|
// Test that we don't do anything bad when we encounter libstdc++ paths.
|
||||||
CppModuleConfiguration config(makeFiles(
|
|
||||||
{"/usr/include/bits/types.h", "/usr/include/c++/8.0.1/vector"}));
|
std::string usr = "/usr/include";
|
||||||
|
std::vector<std::string> files = {
|
||||||
|
// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
usr + "/c++/8.0.1/vector",
|
||||||
|
};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
||||||
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
||||||
}
|
}
|
||||||
|
@ -142,9 +222,20 @@ TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) {
|
||||||
TEST_F(CppModuleConfigurationTest, AmbiguousCLib) {
|
TEST_F(CppModuleConfigurationTest, AmbiguousCLib) {
|
||||||
// Test that we don't do anything when we are not sure where the
|
// Test that we don't do anything when we are not sure where the
|
||||||
// right C standard library is.
|
// right C standard library is.
|
||||||
CppModuleConfiguration config(
|
|
||||||
makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v1/vector",
|
std::string usr1 = "/usr/include";
|
||||||
"/sysroot/usr/include/bits/types.h"}));
|
std::string usr2 = "/usr/include/other/path";
|
||||||
|
std::string libcpp = usr1 + "c++/v1";
|
||||||
|
std::vector<std::string> files = {
|
||||||
|
// First C library
|
||||||
|
usr1 + "/stdio.h",
|
||||||
|
// Second C library
|
||||||
|
usr2 + "/stdio.h",
|
||||||
|
// C++ library
|
||||||
|
libcpp + "/vector",
|
||||||
|
libcpp + "/module.modulemap",
|
||||||
|
};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
||||||
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
||||||
}
|
}
|
||||||
|
@ -152,9 +243,21 @@ TEST_F(CppModuleConfigurationTest, AmbiguousCLib) {
|
||||||
TEST_F(CppModuleConfigurationTest, AmbiguousLibCpp) {
|
TEST_F(CppModuleConfigurationTest, AmbiguousLibCpp) {
|
||||||
// Test that we don't do anything when we are not sure where the
|
// Test that we don't do anything when we are not sure where the
|
||||||
// right libc++ is.
|
// right libc++ is.
|
||||||
CppModuleConfiguration config(
|
|
||||||
makeFiles({"/usr/include/bits/types.h", "/usr/include/c++/v1/vector",
|
std::string usr = "/usr/include";
|
||||||
"/usr/include/c++/v2/vector"}));
|
std::string libcpp1 = usr + "c++/v1";
|
||||||
|
std::string libcpp2 = usr + "c++/v2";
|
||||||
|
std::vector<std::string> files = {
|
||||||
|
// C library
|
||||||
|
usr + "/stdio.h",
|
||||||
|
// First C++ library
|
||||||
|
libcpp1 + "/vector",
|
||||||
|
libcpp1 + "/module.modulemap",
|
||||||
|
// Second C++ library
|
||||||
|
libcpp2 + "/vector",
|
||||||
|
libcpp2 + "/module.modulemap",
|
||||||
|
};
|
||||||
|
CppModuleConfiguration config(makeFiles(files));
|
||||||
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
|
||||||
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue