Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / unittests / Expression / CppModuleConfigurationTest.cpp
blob017a0748c2243c8a46eff9915e9297964345bbe6
1 //===-- CppModuleConfigurationTest.cpp ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Plugins/ExpressionParser/Clang/CppModuleConfiguration.h"
10 #include "Plugins/ExpressionParser/Clang/ClangHost.h"
11 #include "TestingSupport/SubsystemRAII.h"
12 #include "lldb/Host/FileSystem.h"
13 #include "lldb/Host/HostInfo.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
18 using namespace lldb_private;
20 namespace {
21 struct CppModuleConfigurationTest : public testing::Test {
22 llvm::MemoryBufferRef m_empty_buffer;
23 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> m_fs;
25 CppModuleConfigurationTest()
26 : m_empty_buffer("", "<empty buffer>"),
27 m_fs(new llvm::vfs::InMemoryFileSystem()) {}
29 void SetUp() override {
30 FileSystem::Initialize(m_fs);
31 HostInfo::Initialize();
34 void TearDown() override {
35 HostInfo::Terminate();
36 FileSystem::Terminate();
39 /// Utility function turning a list of paths into a FileSpecList.
40 FileSpecList makeFiles(llvm::ArrayRef<std::string> paths) {
41 FileSpecList result;
42 for (const std::string &path : paths) {
43 result.Append(FileSpec(path, FileSpec::Style::posix));
44 if (!m_fs->addFileNoOwn(path, static_cast<time_t>(0), m_empty_buffer))
45 llvm_unreachable("Invalid test configuration?");
47 return result;
50 } // namespace
52 /// Returns the Clang resource include directory.
53 static std::string ResourceInc() {
54 llvm::SmallString<256> resource_dir;
55 llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(),
56 "include");
57 return std::string(resource_dir);
60 TEST_F(CppModuleConfigurationTest, Linux) {
61 // Test the average Linux configuration.
63 std::string usr = "/usr/include";
64 std::string libcpp = "/usr/include/c++/v1";
65 std::vector<std::string> files = {// C library
66 usr + "/stdio.h",
67 // C++ library
68 libcpp + "/vector",
69 libcpp + "/module.modulemap"};
70 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
71 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
72 EXPECT_THAT(config.GetIncludeDirs(),
73 testing::ElementsAre(libcpp, ResourceInc(), usr));
76 TEST_F(CppModuleConfigurationTest, LinuxTargetSpecificInclude) {
77 // Test the average Linux configuration.
79 std::string usr = "/usr/include";
80 std::string usr_target = "/usr/include/x86_64-linux-gnu";
81 std::string libcpp = "/usr/include/c++/v1";
82 std::string libcpp_target = "/usr/include/x86_64-unknown-linux-gnu/c++/v1";
83 std::vector<std::string> files = {
84 // C library
85 usr + "/stdio.h", usr_target + "/sys/cdefs.h",
86 // C++ library
87 libcpp + "/vector", libcpp + "/module.modulemap"};
88 CppModuleConfiguration config(makeFiles(files),
89 llvm::Triple("x86_64-unknown-linux-gnu"));
90 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
91 EXPECT_THAT(config.GetIncludeDirs(),
92 testing::ElementsAre(libcpp, ResourceInc(), usr, usr_target,
93 libcpp_target));
96 TEST_F(CppModuleConfigurationTest, Sysroot) {
97 // Test that having a sysroot for the whole system works fine.
99 std::string libcpp = "/home/user/sysroot/usr/include/c++/v1";
100 std::string usr = "/home/user/sysroot/usr/include";
101 std::vector<std::string> files = {// C library
102 usr + "/stdio.h",
103 // C++ library
104 libcpp + "/vector",
105 libcpp + "/module.modulemap"};
106 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
107 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
108 EXPECT_THAT(config.GetIncludeDirs(),
109 testing::ElementsAre(libcpp, ResourceInc(), usr));
112 TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) {
113 // Test that a locally build libc++ is detected.
115 std::string usr = "/usr/include";
116 std::string libcpp = "/home/user/llvm-build/include/c++/v1";
117 std::vector<std::string> files = {// C library
118 usr + "/stdio.h",
119 // C++ library
120 libcpp + "/vector",
121 libcpp + "/module.modulemap"};
122 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
123 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
124 EXPECT_THAT(config.GetIncludeDirs(),
125 testing::ElementsAre(libcpp, ResourceInc(), usr));
128 TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) {
129 // Test that having an unrelated library in /usr/include doesn't break.
131 std::string usr = "/usr/include";
132 std::string libcpp = "/home/user/llvm-build/include/c++/v1";
133 std::vector<std::string> files = {// C library
134 usr + "/stdio.h",
135 // unrelated library
136 usr + "/boost/vector",
137 // C++ library
138 libcpp + "/vector",
139 libcpp + "/module.modulemap"};
140 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
141 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
142 EXPECT_THAT(config.GetIncludeDirs(),
143 testing::ElementsAre(libcpp, ResourceInc(), usr));
146 TEST_F(CppModuleConfigurationTest, UnrelatedLibraryWithTargetSpecificInclude) {
147 // Test that having an unrelated library in /usr/include doesn't break.
149 std::string usr = "/usr/include";
150 std::string libcpp = "/home/user/llvm-build/include/c++/v1";
151 std::string libcpp_target =
152 "/home/user/llvm-build/include/x86_64-unknown-linux-gnu/c++/v1";
153 std::vector<std::string> files = {// C library
154 usr + "/stdio.h",
155 // unrelated library
156 usr + "/boost/vector",
157 // C++ library
158 libcpp + "/vector",
159 libcpp + "/module.modulemap"};
160 CppModuleConfiguration config(makeFiles(files),
161 llvm::Triple("x86_64-unknown-linux-gnu"));
162 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
163 EXPECT_THAT(config.GetIncludeDirs(),
164 testing::ElementsAre(libcpp, ResourceInc(), usr, libcpp_target));
167 TEST_F(CppModuleConfigurationTest, Xcode) {
168 // Test detection of libc++ coming from Xcode with generic platform names.
170 std::string p = "/Applications/Xcode.app/Contents/Developer/";
171 std::string libcpp = p + "Toolchains/B.xctoolchain/usr/include/c++/v1";
172 std::string usr =
173 p + "Platforms/A.platform/Developer/SDKs/OSVers.sdk/usr/include";
174 std::vector<std::string> files = {
175 // C library
176 usr + "/stdio.h",
177 // C++ library
178 libcpp + "/vector",
179 libcpp + "/module.modulemap",
181 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
182 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
183 EXPECT_THAT(config.GetIncludeDirs(),
184 testing::ElementsAre(libcpp, ResourceInc(), usr));
187 TEST_F(CppModuleConfigurationTest, LibCppV2) {
188 // Test that a "v2" of libc++ is still correctly detected.
190 std::string libcpp = "/usr/include/c++/v2";
191 std::vector<std::string> files = {// C library
192 "/usr/include/stdio.h",
193 // C++ library
194 libcpp + "/vector",
195 libcpp + "/module.modulemap"};
196 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
197 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
198 EXPECT_THAT(config.GetIncludeDirs(),
199 testing::ElementsAre("/usr/include/c++/v2", ResourceInc(),
200 "/usr/include"));
203 TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) {
204 // Test that having some unknown file in the libc++ path doesn't break
205 // anything.
207 std::string libcpp = "/usr/include/c++/v1";
208 std::vector<std::string> files = {// C library
209 "/usr/include/stdio.h",
210 // C++ library
211 libcpp + "/non_existing_file",
212 libcpp + "/module.modulemap",
213 libcpp + "/vector"};
214 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
215 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
216 EXPECT_THAT(config.GetIncludeDirs(),
217 testing::ElementsAre("/usr/include/c++/v1", ResourceInc(),
218 "/usr/include"));
221 TEST_F(CppModuleConfigurationTest, MissingUsrInclude) {
222 // Test that we don't load 'std' if we can't find the C standard library.
224 std::string libcpp = "/usr/include/c++/v1";
225 std::vector<std::string> files = {// C++ library
226 libcpp + "/vector",
227 libcpp + "/module.modulemap"};
228 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
229 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
230 EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
233 TEST_F(CppModuleConfigurationTest, MissingLibCpp) {
234 // Test that we don't load 'std' if we don't have a libc++.
236 std::string usr = "/usr/include";
237 std::vector<std::string> files = {
238 // C library
239 usr + "/stdio.h",
241 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
242 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
243 EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
246 TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) {
247 // Test that we don't do anything bad when we encounter libstdc++ paths.
249 std::string usr = "/usr/include";
250 std::vector<std::string> files = {
251 // C library
252 usr + "/stdio.h",
253 // C++ library
254 usr + "/c++/8.0.1/vector",
256 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
257 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
258 EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
261 TEST_F(CppModuleConfigurationTest, AmbiguousCLib) {
262 // Test that we don't do anything when we are not sure where the
263 // right C standard library is.
265 std::string usr1 = "/usr/include";
266 std::string usr2 = "/usr/include/other/path";
267 std::string libcpp = usr1 + "c++/v1";
268 std::vector<std::string> files = {
269 // First C library
270 usr1 + "/stdio.h",
271 // Second C library
272 usr2 + "/stdio.h",
273 // C++ library
274 libcpp + "/vector",
275 libcpp + "/module.modulemap",
277 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
278 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
279 EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
282 TEST_F(CppModuleConfigurationTest, AmbiguousLibCpp) {
283 // Test that we don't do anything when we are not sure where the
284 // right libc++ is.
286 std::string usr = "/usr/include";
287 std::string libcpp1 = usr + "c++/v1";
288 std::string libcpp2 = usr + "c++/v2";
289 std::vector<std::string> files = {
290 // C library
291 usr + "/stdio.h",
292 // First C++ library
293 libcpp1 + "/vector",
294 libcpp1 + "/module.modulemap",
295 // Second C++ library
296 libcpp2 + "/vector",
297 libcpp2 + "/module.modulemap",
299 CppModuleConfiguration config(makeFiles(files), llvm::Triple());
300 EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
301 EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());