kpdev42 created this revision.
kpdev42 added reviewers: clayborg, granata.enrico, labath.
kpdev42 added a project: LLDB.
Herald added subscribers: JDevlieghere, pengfei.
kpdev42 requested review of this revision.
Herald added a subscriber: lldb-commits.
On Linux some C++ and C include files reside in target specific directories,
like /usr/include/x86_64-linux-gnu.
Patch adds them to libclang, so LLDB jitter has more chances to compile
expression.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D110827
Files:
lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp
lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
lldb/unittests/Expression/CppModuleConfigurationTest.cpp
Index: lldb/unittests/Expression/CppModuleConfigurationTest.cpp
===================================================================
--- lldb/unittests/Expression/CppModuleConfigurationTest.cpp
+++ lldb/unittests/Expression/CppModuleConfigurationTest.cpp
@@ -63,16 +63,20 @@
// Test the average Linux configuration.
std::string usr = "/usr/include";
+ std::string usr_target = "/usr/include/x86_64-linux-gnu";
std::string libcpp = "/usr/include/c++/v1";
- std::vector<std::string> files = {// C library
- usr + "/stdio.h",
- // C++ library
- libcpp + "/vector",
- libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ std::string libcpp_target = "/usr/include/x86_64-unknown-linux-gnu/c++/v1";
+ std::vector<std::string> files = {
+ // C library
+ usr + "/stdio.h", usr_target + "/sys/cdefs.h",
+ // C++ library
+ libcpp + "/vector", libcpp + "/module.modulemap"};
+ CppModuleConfiguration config(makeFiles(files),
+ llvm::Triple("x86_64-unknown-linux-gnu"));
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
- testing::ElementsAre(libcpp, ResourceInc(), usr));
+ testing::ElementsAre(libcpp, ResourceInc(), usr, usr_target,
+ libcpp_target));
}
TEST_F(CppModuleConfigurationTest, Sysroot) {
@@ -85,7 +89,7 @@
// C++ library
libcpp + "/vector",
libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
testing::ElementsAre(libcpp, ResourceInc(), usr));
@@ -101,7 +105,7 @@
// C++ library
libcpp + "/vector",
libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
testing::ElementsAre(libcpp, ResourceInc(), usr));
@@ -112,6 +116,8 @@
std::string usr = "/usr/include";
std::string libcpp = "/home/user/llvm-build/include/c++/v1";
+ std::string libcpp_target =
+ "/home/user/llvm-build/include/x86_64-unknown-linux-gnu/c++/v1";
std::vector<std::string> files = {// C library
usr + "/stdio.h",
// unrelated library
@@ -119,10 +125,11 @@
// C++ library
libcpp + "/vector",
libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files),
+ llvm::Triple("x86_64-unknown-linux-gnu"));
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
- testing::ElementsAre(libcpp, ResourceInc(), usr));
+ testing::ElementsAre(libcpp, ResourceInc(), usr, libcpp_target));
}
TEST_F(CppModuleConfigurationTest, Xcode) {
@@ -139,7 +146,7 @@
libcpp + "/vector",
libcpp + "/module.modulemap",
};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
testing::ElementsAre(libcpp, ResourceInc(), usr));
@@ -154,7 +161,7 @@
// C++ library
libcpp + "/vector",
libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
testing::ElementsAre("/usr/include/c++/v2", ResourceInc(),
@@ -172,7 +179,7 @@
libcpp + "/non_existing_file",
libcpp + "/module.modulemap",
libcpp + "/vector"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std"));
EXPECT_THAT(config.GetIncludeDirs(),
testing::ElementsAre("/usr/include/c++/v1", ResourceInc(),
@@ -186,7 +193,7 @@
std::vector<std::string> files = {// C++ library
libcpp + "/vector",
libcpp + "/module.modulemap"};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
}
@@ -199,7 +206,7 @@
// C library
usr + "/stdio.h",
};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
}
@@ -214,7 +221,7 @@
// C++ library
usr + "/c++/8.0.1/vector",
};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
}
@@ -235,7 +242,7 @@
libcpp + "/vector",
libcpp + "/module.modulemap",
};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
}
@@ -257,7 +264,7 @@
libcpp2 + "/vector",
libcpp2 + "/module.modulemap",
};
- CppModuleConfiguration config(makeFiles(files));
+ CppModuleConfiguration config(makeFiles(files), llvm::Triple());
EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre());
EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre());
}
Index: lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
+++ lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
@@ -42,8 +42,13 @@
/// If valid, the include path used for the std module.
SetOncePath m_std_inc;
+ /// If valid, the per-target include path used for the std module.
+ SetOncePath m_std_target_inc;
/// If valid, the include path to the C library (e.g. /usr/include).
SetOncePath m_c_inc;
+ /// If valid, the include path to target-specific C library files
+ /// (e.g. /usr/include/x86_64-linux-gnu).
+ SetOncePath m_c_target_inc;
/// The Clang resource include path for this configuration.
std::string m_resource_inc;
@@ -53,11 +58,12 @@
/// Analyze a given source file to build the current configuration.
/// Returns false iff there was a fatal error that makes analyzing any
/// further files pointless as the configuration is now invalid.
- bool analyzeFile(const FileSpec &f);
+ bool analyzeFile(const FileSpec &f, const llvm::Triple &triple);
public:
/// Creates a configuration by analyzing the given list of used source files.
- explicit CppModuleConfiguration(const FileSpecList &support_files);
+ explicit CppModuleConfiguration(const FileSpecList &support_files,
+ const llvm::Triple &triple);
/// Creates an empty and invalid configuration.
CppModuleConfiguration() = default;
Index: lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp
@@ -10,6 +10,7 @@
#include "ClangHost.h"
#include "lldb/Host/FileSystem.h"
+#include "llvm/ADT/Triple.h"
using namespace lldb_private;
@@ -30,7 +31,33 @@
return false;
}
-bool CppModuleConfiguration::analyzeFile(const FileSpec &f) {
+static void getTargetIncludePaths(const llvm::Triple &triple,
+ std::vector<std::string> &paths) {
+ if (triple.str().empty())
+ return;
+ paths.push_back("/usr/include/" + triple.str());
+ if (triple.getArchName().empty() || triple.getOSAndEnvironmentName().empty())
+ return;
+ paths.push_back(("/usr/include/" + triple.getArchName() + "-" +
+ triple.getOSAndEnvironmentName())
+ .str());
+}
+
+static bool guessIncludePath(llvm::StringRef pathToFile,
+ llvm::StringRef pattern, llvm::StringRef &result) {
+ result = llvm::StringRef();
+ if (pattern.empty())
+ return false;
+ size_t pos = pathToFile.find(pattern);
+ if (pos == llvm::StringRef::npos)
+ return false;
+
+ result = pathToFile.substr(0, pos + pattern.size());
+ return true;
+}
+
+bool CppModuleConfiguration::analyzeFile(const FileSpec &f,
+ const llvm::Triple &triple) {
using namespace llvm::sys::path;
// Convert to slashes to make following operations simpler.
std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef());
@@ -43,15 +70,26 @@
// need to be specified in the header search.
if (libcpp_regex.match(f.GetPath()) &&
parent_path(posix_dir, Style::posix).endswith("c++")) {
- return m_std_inc.TrySet(posix_dir);
+ if (!m_std_inc.TrySet(posix_dir))
+ return false;
+ if (triple.str().empty())
+ return true;
+
+ posix_dir.consume_back("c++/v1");
+ llvm::SmallVector<char, 64> tmp;
+ return m_std_target_inc.TrySet(
+ (posix_dir + triple.str() + "/c++/v1").toStringRef(tmp));
}
- // Check for /usr/include. On Linux this might be /usr/include/bits, so
- // we should remove that '/bits' suffix to get the actual include directory.
- if (posix_dir.endswith("/usr/include/bits"))
- posix_dir.consume_back("/bits");
- if (posix_dir.endswith("/usr/include"))
- return m_c_inc.TrySet(posix_dir);
+ llvm::StringRef inc_path;
+ std::vector<std::string> paths_to_test;
+ getTargetIncludePaths(triple, paths_to_test);
+ // Target specific paths contains /usr/include, so we check them first
+ for (auto &path : paths_to_test)
+ if (guessIncludePath(posix_dir, path, inc_path))
+ return m_c_target_inc.TrySet(inc_path);
+ if (guessIncludePath(posix_dir, "/usr/include", inc_path))
+ return m_c_inc.TrySet(inc_path);
// File wasn't interesting, continue analyzing.
return true;
@@ -92,11 +130,11 @@
}
CppModuleConfiguration::CppModuleConfiguration(
- const FileSpecList &support_files) {
+ const FileSpecList &support_files, const llvm::Triple &triple) {
// Analyze all files we were given to build the configuration.
bool error = !llvm::all_of(support_files,
std::bind(&CppModuleConfiguration::analyzeFile,
- this, std::placeholders::_1));
+ this, std::placeholders::_1, triple));
// If we have a valid configuration at this point, set the
// include directories and module list that should be used.
if (!error && hasValidConfig()) {
@@ -109,6 +147,10 @@
// This order matches the way Clang orders these directories.
m_include_dirs = {m_std_inc.Get().str(), m_resource_inc,
m_c_inc.Get().str()};
+ if (m_c_target_inc.Valid())
+ m_include_dirs.push_back(m_c_target_inc.Get().str());
+ if (m_std_target_inc.Valid())
+ m_include_dirs.push_back(m_std_target_inc.Get().str());
m_imported_modules = {"std"};
}
}
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -516,7 +516,7 @@
// Try to create a configuration from the files. If there is no valid
// configuration possible with the files, this just returns an invalid
// configuration.
- return CppModuleConfiguration(files);
+ return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());
}
bool ClangUserExpression::PrepareForParsing(
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits