1061da546Spatrick //===-- CppModuleConfiguration.cpp ----------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "CppModuleConfiguration.h" 10061da546Spatrick 11061da546Spatrick #include "ClangHost.h" 12061da546Spatrick #include "lldb/Host/FileSystem.h" 13061da546Spatrick 14061da546Spatrick using namespace lldb_private; 15061da546Spatrick 16061da546Spatrick bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { 17061da546Spatrick // Setting for the first time always works. 18061da546Spatrick if (m_first) { 19061da546Spatrick m_path = path.str(); 20061da546Spatrick m_valid = true; 21061da546Spatrick m_first = false; 22061da546Spatrick return true; 23061da546Spatrick } 24061da546Spatrick // Changing the path to the same value is fine. 25061da546Spatrick if (m_path == path) 26061da546Spatrick return true; 27061da546Spatrick 28061da546Spatrick // Changing the path after it was already set is not allowed. 29061da546Spatrick m_valid = false; 30061da546Spatrick return false; 31061da546Spatrick } 32061da546Spatrick 33061da546Spatrick bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { 34061da546Spatrick using namespace llvm::sys::path; 35061da546Spatrick // Convert to slashes to make following operations simpler. 36061da546Spatrick std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef()); 37061da546Spatrick llvm::StringRef posix_dir(dir_buffer); 38061da546Spatrick 39061da546Spatrick // Check for /c++/vX/ that is used by libc++. 40061da546Spatrick static llvm::Regex libcpp_regex(R"regex(/c[+][+]/v[0-9]/)regex"); 41061da546Spatrick if (libcpp_regex.match(f.GetPath())) { 42061da546Spatrick // Strip away libc++'s /experimental directory if there is one. 43061da546Spatrick posix_dir.consume_back("/experimental"); 44061da546Spatrick return m_std_inc.TrySet(posix_dir); 45061da546Spatrick } 46061da546Spatrick 47061da546Spatrick // Check for /usr/include. On Linux this might be /usr/include/bits, so 48061da546Spatrick // we should remove that '/bits' suffix to get the actual include directory. 49061da546Spatrick if (posix_dir.endswith("/usr/include/bits")) 50061da546Spatrick posix_dir.consume_back("/bits"); 51061da546Spatrick if (posix_dir.endswith("/usr/include")) 52061da546Spatrick return m_c_inc.TrySet(posix_dir); 53061da546Spatrick 54061da546Spatrick // File wasn't interesting, continue analyzing. 55061da546Spatrick return true; 56061da546Spatrick } 57061da546Spatrick 58061da546Spatrick bool CppModuleConfiguration::hasValidConfig() { 59061da546Spatrick // We all these include directories to have a valid usable configuration. 60061da546Spatrick return m_c_inc.Valid() && m_std_inc.Valid(); 61061da546Spatrick } 62061da546Spatrick 63061da546Spatrick CppModuleConfiguration::CppModuleConfiguration( 64061da546Spatrick const FileSpecList &support_files) { 65061da546Spatrick // Analyze all files we were given to build the configuration. 66061da546Spatrick bool error = !llvm::all_of(support_files, 67061da546Spatrick std::bind(&CppModuleConfiguration::analyzeFile, 68061da546Spatrick this, std::placeholders::_1)); 69061da546Spatrick // If we have a valid configuration at this point, set the 70061da546Spatrick // include directories and module list that should be used. 71061da546Spatrick if (!error && hasValidConfig()) { 72061da546Spatrick // Calculate the resource directory for LLDB. 73061da546Spatrick llvm::SmallString<256> resource_dir; 74061da546Spatrick llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(), 75061da546Spatrick "include"); 76*dda28197Spatrick m_resource_inc = std::string(resource_dir.str()); 77061da546Spatrick 78061da546Spatrick // This order matches the way Clang orders these directories. 79061da546Spatrick m_include_dirs = {m_std_inc.Get(), m_resource_inc, m_c_inc.Get()}; 80061da546Spatrick m_imported_modules = {"std"}; 81061da546Spatrick } 82061da546Spatrick } 83