llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: David Spickett (DavidSpickett) <details> <summary>Changes</summary> Reverts llvm/llvm-project#<!-- -->132274 Broke a test on LLDB Widows on Arm: https://lab.llvm.org/buildbot/#/builders/141/builds/7726 ``` FAIL: test_dwarf (lldbsuite.test.lldbtest.TestExternCSymbols.test_dwarf) <...> self.assertTrue(self.res.Succeeded(), msg + output) AssertionError: False is not true : Command 'expression -- foo()' did not return successfully Error output: error: Couldn't look up symbols: int foo(void) Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler. ``` --- Patch is 38.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/134995.diff 17 Files Affected: - (modified) lldb/include/lldb/Core/Mangled.h (-2) - (modified) lldb/include/lldb/Core/RichManglingContext.h (+14-2) - (modified) lldb/include/lldb/Target/Language.h (-98) - (modified) lldb/source/Core/CMakeLists.txt (+4-1) - (modified) lldb/source/Core/Mangled.cpp (+5-5) - (modified) lldb/source/Core/Module.cpp (+88-63) - (modified) lldb/source/Core/RichManglingContext.cpp (+13-9) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp (+5-6) - (modified) lldb/source/Plugins/Language/CMakeLists.txt (-2) - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+76-52) - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h (+49-9) - (modified) lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp (-13) - (modified) lldb/source/Plugins/Language/ObjC/ObjCLanguage.h (-3) - (modified) lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (+2-2) - (modified) lldb/unittests/Core/CMakeLists.txt (-1) - (modified) lldb/unittests/Core/RichManglingContextTest.cpp (-7) - (modified) lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp (+11-11) ``````````diff diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h index 7db63eeeb6ee0..5988d919a89b8 100644 --- a/lldb/include/lldb/Core/Mangled.h +++ b/lldb/include/lldb/Core/Mangled.h @@ -246,8 +246,6 @@ class Mangled { /// for s, otherwise the enumerator for the mangling scheme detected. static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name); - static bool IsMangledName(llvm::StringRef name); - /// Decode a serialized version of this object from data. /// /// \param data diff --git a/lldb/include/lldb/Core/RichManglingContext.h b/lldb/include/lldb/Core/RichManglingContext.h index 50ec2ae361098..3b79924e88a9a 100644 --- a/lldb/include/lldb/Core/RichManglingContext.h +++ b/lldb/include/lldb/Core/RichManglingContext.h @@ -12,7 +12,6 @@ #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" -#include "lldb/Target/Language.h" #include "lldb/Utility/ConstString.h" #include "llvm/ADT/Any.h" @@ -68,7 +67,11 @@ class RichManglingContext { char *m_ipd_buf; size_t m_ipd_buf_size = 2048; - std::unique_ptr<Language::MethodName> m_cxx_method_parser; + /// Members for PluginCxxLanguage + /// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The + /// respective header is in Plugins and including it from here causes cyclic + /// dependency. Instead keep a llvm::Any and cast it on-access in the cpp. + llvm::Any m_cxx_method_parser; /// Clean up memory when using PluginCxxLanguage void ResetCxxMethodParser(); @@ -78,6 +81,15 @@ class RichManglingContext { /// Uniform handling of string buffers for ItaniumPartialDemangler. llvm::StringRef processIPDStrResult(char *ipd_res, size_t res_len); + + /// Cast the given parser to the given type. Ideally we would have a type + /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we + /// can't access CPlusPlusLanguage::MethodName from within the header. + template <class ParserT> static ParserT *get(llvm::Any parser) { + assert(parser.has_value()); + assert(llvm::any_cast<ParserT *>(&parser)); + return *llvm::any_cast<ParserT *>(&parser); + } }; } // namespace lldb_private diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index d46969cb3b4e4..b699a90aff8e4 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -214,104 +214,6 @@ class Language : public PluginInterface { return std::vector<Language::MethodNameVariant>(); }; - class MethodName { - public: - MethodName() {} - - MethodName(ConstString full) - : m_full(full), m_basename(), m_context(), m_arguments(), - m_qualifiers(), m_return_type(), m_scope_qualified(), m_parsed(false), - m_parse_error(false) {} - - virtual ~MethodName() {}; - - void Clear() { - m_full.Clear(); - m_basename = llvm::StringRef(); - m_context = llvm::StringRef(); - m_arguments = llvm::StringRef(); - m_qualifiers = llvm::StringRef(); - m_return_type = llvm::StringRef(); - m_scope_qualified.clear(); - m_parsed = false; - m_parse_error = false; - } - - bool IsValid() { - if (!m_parsed) - Parse(); - if (m_parse_error) - return false; - return (bool)m_full; - } - - ConstString GetFullName() const { return m_full; } - - llvm::StringRef GetBasename() { - if (!m_parsed) - Parse(); - return m_basename; - } - - llvm::StringRef GetContext() { - if (!m_parsed) - Parse(); - return m_context; - } - - llvm::StringRef GetArguments() { - if (!m_parsed) - Parse(); - return m_arguments; - } - - llvm::StringRef GetQualifiers() { - if (!m_parsed) - Parse(); - return m_qualifiers; - } - - llvm::StringRef GetReturnType() { - if (!m_parsed) - Parse(); - return m_return_type; - } - - std::string GetScopeQualifiedName() { - if (!m_parsed) - Parse(); - return m_scope_qualified; - } - - protected: - virtual void Parse() { - m_parsed = true; - m_parse_error = true; - } - - ConstString m_full; // Full name: - // "size_t lldb::SBTarget::GetBreakpointAtIndex(unsigned - // int) const" - llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex" - llvm::StringRef m_context; // Decl context: "lldb::SBTarget" - llvm::StringRef m_arguments; // Arguments: "(unsigned int)" - llvm::StringRef m_qualifiers; // Qualifiers: "const" - llvm::StringRef m_return_type; // Return type: "size_t" - std::string m_scope_qualified; - bool m_parsed = false; - bool m_parse_error = false; - }; - - virtual std::unique_ptr<Language::MethodName> - GetMethodName(ConstString name) const { - return std::make_unique<Language::MethodName>(name); - }; - - virtual std::pair<lldb::FunctionNameType, llvm::StringRef> - GetFunctionNameInfo(ConstString name) const { - return std::pair{lldb::eFunctionNameTypeNone, llvm::StringRef()}; - }; - /// Returns true iff the given symbol name is compatible with the mangling /// scheme of this language. /// diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt index f09b451ac414d..0a08da0fec230 100644 --- a/lldb/source/Core/CMakeLists.txt +++ b/lldb/source/Core/CMakeLists.txt @@ -16,7 +16,8 @@ if (LLDB_ENABLE_CURSES) endif() endif() -add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES +# TODO: Add property `NO_PLUGIN_DEPENDENCIES` to lldbCore +add_lldb_library(lldbCore Address.cpp AddressRange.cpp AddressRangeListImpl.cpp @@ -70,6 +71,8 @@ add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES lldbUtility lldbValueObject lldbVersion + lldbPluginCPlusPlusLanguage + lldbPluginObjCLanguage ${LLDB_CURSES_LIBS} CLANG_LIBS diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index c41f0fdb5ff1b..ddaaedea04183 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -33,12 +33,12 @@ #include <cstring> using namespace lldb_private; -#pragma mark Mangled - -bool Mangled::IsMangledName(llvm::StringRef name) { - return Mangled::GetManglingScheme(name) != Mangled::eManglingSchemeNone; +static inline bool cstring_is_mangled(llvm::StringRef s) { + return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone; } +#pragma mark Mangled + Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { if (name.empty()) return Mangled::eManglingSchemeNone; @@ -121,7 +121,7 @@ int Mangled::Compare(const Mangled &a, const Mangled &b) { void Mangled::SetValue(ConstString name) { if (name) { - if (IsMangledName(name.GetStringRef())) { + if (cstring_is_mangled(name.GetStringRef())) { m_demangled.Clear(); m_mangled = name; } else { diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index ea6c2a1679aa0..53dc6fcde0381 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -52,6 +52,9 @@ #include "lldb/Host/windows/PosixApi.h" #endif +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" + #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DJB.h" @@ -638,75 +641,98 @@ void Module::FindCompileUnits(const FileSpec &path, Module::LookupInfo::LookupInfo(ConstString name, FunctionNameType name_type_mask, LanguageType language) - : m_name(name), m_lookup_name(name), m_language(language) { + : m_name(name), m_lookup_name(), m_language(language) { + const char *name_cstr = name.GetCString(); llvm::StringRef basename; - - std::vector<Language *> languages; - auto collect_language_plugins = [&languages](Language *lang) { - languages.push_back(lang); - return true; - }; + llvm::StringRef context; if (name_type_mask & eFunctionNameTypeAuto) { - if (language == eLanguageTypeUnknown) { - Language::ForEach(collect_language_plugins); - for (Language *lang : languages) { - auto info = lang->GetFunctionNameInfo(name); - if (info.first != eFunctionNameTypeNone) { - m_name_type_mask |= info.first; - basename = info.second; - break; - } - } + if (CPlusPlusLanguage::IsCPPMangledName(name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCMethodName(name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if (Language::LanguageIsC(language)) { + m_name_type_mask = eFunctionNameTypeFull; } else { - if (auto *lang = Language::FindPlugin(language)) { - auto info = lang->GetFunctionNameInfo(name); - m_name_type_mask = info.first; - basename = info.second; + if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCSelector(name_cstr)) + m_name_type_mask |= eFunctionNameTypeSelector; + + CPlusPlusLanguage::MethodName cpp_method(name); + basename = cpp_method.GetBasename(); + if (basename.empty()) { + if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename)) + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); + else + m_name_type_mask |= eFunctionNameTypeFull; + } else { + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); } } - - // NOTE: There are several ways to get here, but this is a fallback path in - // case the above does not succeed at extracting any useful information from - // the loaded language plugins. - if (m_name_type_mask == eFunctionNameTypeNone) - m_name_type_mask = eFunctionNameTypeFull; - } else { m_name_type_mask = name_type_mask; - if (language == eLanguageTypeUnknown) { - Language::ForEach(collect_language_plugins); - for (Language *lang : languages) { - auto info = lang->GetFunctionNameInfo(name); - if (info.first & m_name_type_mask) { - m_name_type_mask &= info.first; - basename = info.second; - break; + if (name_type_mask & eFunctionNameTypeMethod || + name_type_mask & eFunctionNameTypeBase) { + // If they've asked for a CPP method or function name and it can't be + // that, we don't even need to search for CPP methods or names. + CPlusPlusLanguage::MethodName cpp_method(name); + if (cpp_method.IsValid()) { + basename = cpp_method.GetBasename(); + + if (!cpp_method.GetQualifiers().empty()) { + // There is a "const" or other qualifier following the end of the + // function parens, this can't be a eFunctionNameTypeBase + m_name_type_mask &= ~(eFunctionNameTypeBase); + if (m_name_type_mask == eFunctionNameTypeNone) + return; } + } else { + // If the CPP method parser didn't manage to chop this up, try to fill + // in the base name if we can. If a::b::c is passed in, we need to just + // look up "c", and then we'll filter the result later. + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename); } - } else { - if (auto *lang = Language::FindPlugin(language)) { - auto info = lang->GetFunctionNameInfo(name); - if (info.first & m_name_type_mask) { - // If the user asked for FunctionNameTypes that aren't possible, - // then filter those out. (e.g. asking for Selectors on - // C++ symbols, or even if the symbol given can't be a selector in - // ObjC) - m_name_type_mask &= info.first; - basename = info.second; - } + } + + if (name_type_mask & eFunctionNameTypeSelector) { + if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) { + m_name_type_mask &= ~(eFunctionNameTypeSelector); + if (m_name_type_mask == eFunctionNameTypeNone) + return; + } + } + + // Still try and get a basename in case someone specifies a name type mask + // of eFunctionNameTypeFull and a name like "A::func" + if (basename.empty()) { + if (name_type_mask & eFunctionNameTypeFull && + !CPlusPlusLanguage::IsCPPMangledName(name_cstr)) { + CPlusPlusLanguage::MethodName cpp_method(name); + basename = cpp_method.GetBasename(); + if (basename.empty()) + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename); } } } if (!basename.empty()) { - // The name supplied was incomplete for lookup purposes. For example, in C++ - // we may have gotten something like "a::count". In this case, we want to do - // a lookup on the basename "count" and then make sure any matching results - // contain "a::count" so that it would match "b::a::count" and "a::count". - // This is why we set match_name_after_lookup to true. + // The name supplied was a partial C++ path like "a::count". In this case + // we want to do a lookup on the basename "count" and then make sure any + // matching results contain "a::count" so that it would match "b::a::count" + // and "a::count". This is why we set "match_name_after_lookup" to true m_lookup_name.SetString(basename); m_match_name_after_lookup = true; + } else { + // The name is already correct, just use the exact name as supplied, and we + // won't need to check if any matches contain "name" + m_lookup_name = name; + m_match_name_after_lookup = false; } } @@ -765,8 +791,7 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, // "func" and specified eFunctionNameTypeFull, but we might have found // "a::func()", "a::b::func()", "c::func()", "func()" and "func". Only // "func()" and "func" should end up matching. - auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus); - if (lang && m_name_type_mask == eFunctionNameTypeFull) { + if (m_name_type_mask == eFunctionNameTypeFull) { SymbolContext sc; size_t i = start_idx; while (i < sc_list.GetSize()) { @@ -777,21 +802,20 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled)); ConstString full_name(sc.GetFunctionName()); if (mangled_name != m_name && full_name != m_name) { - std::unique_ptr<Language::MethodName> cpp_method = - lang->GetMethodName(full_name); - if (cpp_method->IsValid()) { - if (cpp_method->GetContext().empty()) { - if (cpp_method->GetBasename().compare(m_name) != 0) { + CPlusPlusLanguage::MethodName cpp_method(full_name); + if (cpp_method.IsValid()) { + if (cpp_method.GetContext().empty()) { + if (cpp_method.GetBasename().compare(m_name) != 0) { sc_list.RemoveContextAtIndex(i); continue; } } else { std::string qualified_name; llvm::StringRef anon_prefix("(anonymous namespace)"); - if (cpp_method->GetContext() == anon_prefix) - qualified_name = cpp_method->GetBasename().str(); + if (cpp_method.GetContext() == anon_prefix) + qualified_name = cpp_method.GetBasename().str(); else - qualified_name = cpp_method->GetScopeQualifiedName(); + qualified_name = cpp_method.GetScopeQualifiedName(); if (qualified_name != m_name.GetCString()) { sc_list.RemoveContextAtIndex(i); continue; @@ -964,7 +988,8 @@ DebuggersOwningModuleRequestingInterruption(Module &module) { for (auto debugger_sp : requestors) { if (!debugger_sp->InterruptRequested()) continue; - if (debugger_sp->GetTargetList().AnyTargetContainsModule(module)) + if (debugger_sp->GetTargetList() + .AnyTargetContainsModule(module)) interruptors.push_back(debugger_sp); } return interruptors; diff --git a/lldb/source/Core/RichManglingContext.cpp b/lldb/source/Core/RichManglingContext.cpp index 82582a5d675a9..b68c9e11581b4 100644 --- a/lldb/source/Core/RichManglingContext.cpp +++ b/lldb/source/Core/RichManglingContext.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/RichManglingContext.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "lldb/Utility/LLDBLog.h" #include "llvm/ADT/StringRef.h" @@ -23,8 +24,9 @@ RichManglingContext::~RichManglingContext() { void RichManglingContext::ResetCxxMethodParser() { // If we want to support parsers for other languages some day, we need a // switch here to delete the correct parser type. - if (m_cxx_method_parser) { + if (m_cxx_method_parser.has_value()) { assert(m_provider == PluginCxxLanguage); + delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser); m_cxx_method_parser.reset(); } } @@ -56,11 +58,8 @@ bool RichManglingContext::FromItaniumName(ConstString mangled) { } bool RichManglingContext::FromCxxMethodName(ConstString demangled) { - auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus); - if (!lang) - return false; ResetProvider(PluginCxxLanguage); - m_cxx_method_parser = lang->GetMethodName(demangled); + m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled); return true; } @@ -71,7 +70,8 @@ bool RichManglingContext::IsCtorOrDtor() const { return m_ipd.isCtorOrDtor(); case PluginCxxLanguage: { // We can only check for destructors here. - auto base_name = m_cxx_method_parser->GetBasename(); + auto base_name = + get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename(); return base_name.starts_with("~"); } case None: @@ -118,7 +118,8 @@ llvm::StringRef RichManglingContext::ParseFunctionBaseName() { return processIPDStrResult(buf, n); } case PluginCxxLanguage: - return m_cxx_method_parser->GetBasename(); + return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser) + ->GetBasename(); case None: return {}; } @@ -134,7 +135,8 @@ llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() { return processIPDStrResult(buf, n); } case PluginCxxLanguage: - return m_cxx_method_parser->GetContext(); + return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser) + ->GetContext(); case None: return {}; } @@ -150,7 +152,9 @@ llvm::StringRef RichManglingContext::ParseFullName() { return processIPDStrResult(buf, n); } case PluginCxxLanguage: - return m_cxx_method_parser->GetFullName().GetStringRef(); + return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser) + ->GetFullName() + .GetStringRef(); case None: return {}; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 667cb8a900459..9e96f6557c7ba 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -18,7 +18,6 @@ #include "NameSearchContext.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Address.h" -#include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Expression/DiagnosticManager.h" @@ -36,7 +35,6 @@ #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" @@ -58,6 +56,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Lan... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/134995 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits