[Lldb-commits] [lldb] [LLDB] Reapply refactored CPlusPlusLanguage::MethodName to break lldb-server dependencies (PR #135033)
Dmitry Vasilyev via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 9 07:31:47 PDT 2025
https://github.com/slydiman created https://github.com/llvm/llvm-project/pull/135033
The original PR is #132274.
>From 08b6d2b832d3f40ed56f05e7e7da26d6f3f0a8cc Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev <dvassiliev at accesssoftek.com>
Date: Wed, 9 Apr 2025 17:06:49 +0400
Subject: [PATCH] [LLDB] Reapply refactored CPlusPlusLanguage::MethodName to
break lldb-server dependencies
The original PR is #132274.
---
lldb/include/lldb/Core/Mangled.h | 2 +
lldb/include/lldb/Core/RichManglingContext.h | 16 +-
lldb/include/lldb/Target/Language.h | 98 +++++++++++
lldb/source/Core/CMakeLists.txt | 5 +-
lldb/source/Core/Mangled.cpp | 10 +-
lldb/source/Core/Module.cpp | 152 ++++++++----------
lldb/source/Core/RichManglingContext.cpp | 22 ++-
.../Clang/ClangExpressionDeclMap.cpp | 11 +-
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 128 ++++++---------
.../Language/CPlusPlus/CPlusPlusLanguage.h | 58 ++-----
.../Plugins/Language/ObjC/ObjCLanguage.cpp | 12 ++
.../Plugins/Language/ObjC/ObjCLanguage.h | 3 +
.../Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 4 +-
lldb/unittests/Core/CMakeLists.txt | 1 +
.../Core/RichManglingContextTest.cpp | 7 +
.../CPlusPlus/CPlusPlusLanguageTest.cpp | 22 +--
16 files changed, 285 insertions(+), 266 deletions(-)
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index 5988d919a89b8..7db63eeeb6ee0 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -246,6 +246,8 @@ 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 3b79924e88a9a..50ec2ae361098 100644
--- a/lldb/include/lldb/Core/RichManglingContext.h
+++ b/lldb/include/lldb/Core/RichManglingContext.h
@@ -12,6 +12,7 @@
#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"
@@ -67,11 +68,7 @@ class RichManglingContext {
char *m_ipd_buf;
size_t m_ipd_buf_size = 2048;
- /// 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;
+ std::unique_ptr<Language::MethodName> m_cxx_method_parser;
/// Clean up memory when using PluginCxxLanguage
void ResetCxxMethodParser();
@@ -81,15 +78,6 @@ 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 b699a90aff8e4..d46969cb3b4e4 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -214,6 +214,104 @@ 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 0a08da0fec230..f09b451ac414d 100644
--- a/lldb/source/Core/CMakeLists.txt
+++ b/lldb/source/Core/CMakeLists.txt
@@ -16,8 +16,7 @@ if (LLDB_ENABLE_CURSES)
endif()
endif()
-# TODO: Add property `NO_PLUGIN_DEPENDENCIES` to lldbCore
-add_lldb_library(lldbCore
+add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES
Address.cpp
AddressRange.cpp
AddressRangeListImpl.cpp
@@ -71,8 +70,6 @@ add_lldb_library(lldbCore
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 ddaaedea04183..c41f0fdb5ff1b 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -33,12 +33,12 @@
#include <cstring>
using namespace lldb_private;
-static inline bool cstring_is_mangled(llvm::StringRef s) {
- return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
-}
-
#pragma mark Mangled
+bool Mangled::IsMangledName(llvm::StringRef name) {
+ return Mangled::GetManglingScheme(name) != Mangled::eManglingSchemeNone;
+}
+
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 (cstring_is_mangled(name.GetStringRef())) {
+ if (IsMangledName(name.GetStringRef())) {
m_demangled.Clear();
m_mangled = name;
} else {
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 53dc6fcde0381..8855d46396bdc 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -52,9 +52,6 @@
#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"
@@ -641,98 +638,78 @@ void Module::FindCompileUnits(const FileSpec &path,
Module::LookupInfo::LookupInfo(ConstString name,
FunctionNameType name_type_mask,
LanguageType language)
- : m_name(name), m_lookup_name(), m_language(language) {
- const char *name_cstr = name.GetCString();
+ : m_name(name), m_lookup_name(name), m_language(language) {
llvm::StringRef basename;
- llvm::StringRef context;
+ std::vector<Language *> languages;
if (name_type_mask & eFunctionNameTypeAuto) {
- 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)) {
+ if (Mangled::IsMangledName(name_cstr) || Language::LanguageIsC(language))
m_name_type_mask = eFunctionNameTypeFull;
+ else if (language == eLanguageTypeUnknown) {
+ languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
+ languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
+ for (Language *lang : languages) {
+ if (!lang)
+ continue;
+ auto info = lang->GetFunctionNameInfo(name);
+ if (info.first != eFunctionNameTypeNone) {
+ m_name_type_mask = info.first;
+ basename = info.second;
+ break;
+ }
+ }
} else {
- 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);
+ if (auto *lang = Language::FindPlugin(language)) {
+ auto info = lang->GetFunctionNameInfo(name);
+ m_name_type_mask = info.first;
+ basename = info.second;
}
}
+
+ // 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 (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;
+ if (language == eLanguageTypeUnknown) {
+ languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
+ languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
+ for (Language *lang : languages) {
+ if (!lang)
+ continue;
+ auto info = lang->GetFunctionNameInfo(name);
+ if (info.first & m_name_type_mask) {
+ m_name_type_mask &= info.first;
+ basename = info.second;
+ break;
}
- } 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);
- }
- }
-
- 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);
+ } 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 (!basename.empty()) {
- // 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
+ // 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.
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;
}
}
@@ -791,7 +768,8 @@ 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.
- if (m_name_type_mask == eFunctionNameTypeFull) {
+ auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus);
+ if (lang && m_name_type_mask == eFunctionNameTypeFull) {
SymbolContext sc;
size_t i = start_idx;
while (i < sc_list.GetSize()) {
@@ -802,20 +780,21 @@ 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) {
- CPlusPlusLanguage::MethodName cpp_method(full_name);
- if (cpp_method.IsValid()) {
- if (cpp_method.GetContext().empty()) {
- if (cpp_method.GetBasename().compare(m_name) != 0) {
+ 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) {
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;
@@ -988,8 +967,7 @@ 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 b68c9e11581b4..82582a5d675a9 100644
--- a/lldb/source/Core/RichManglingContext.cpp
+++ b/lldb/source/Core/RichManglingContext.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/RichManglingContext.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "lldb/Utility/LLDBLog.h"
#include "llvm/ADT/StringRef.h"
@@ -24,9 +23,8 @@ 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.has_value()) {
+ if (m_cxx_method_parser) {
assert(m_provider == PluginCxxLanguage);
- delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
m_cxx_method_parser.reset();
}
}
@@ -58,8 +56,11 @@ 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 = new CPlusPlusLanguage::MethodName(demangled);
+ m_cxx_method_parser = lang->GetMethodName(demangled);
return true;
}
@@ -70,8 +71,7 @@ bool RichManglingContext::IsCtorOrDtor() const {
return m_ipd.isCtorOrDtor();
case PluginCxxLanguage: {
// We can only check for destructors here.
- auto base_name =
- get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
+ auto base_name = m_cxx_method_parser->GetBasename();
return base_name.starts_with("~");
}
case None:
@@ -118,8 +118,7 @@ llvm::StringRef RichManglingContext::ParseFunctionBaseName() {
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
- return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
- ->GetBasename();
+ return m_cxx_method_parser->GetBasename();
case None:
return {};
}
@@ -135,8 +134,7 @@ llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
- return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
- ->GetContext();
+ return m_cxx_method_parser->GetContext();
case None:
return {};
}
@@ -152,9 +150,7 @@ llvm::StringRef RichManglingContext::ParseFullName() {
return processIPDStrResult(buf, n);
}
case PluginCxxLanguage:
- return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
- ->GetFullName()
- .GetStringRef();
+ return 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 9e96f6557c7ba..667cb8a900459 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -18,6 +18,7 @@
#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"
@@ -35,6 +36,7 @@
#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"
@@ -56,7 +58,6 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/RecursiveASTVisitor.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
@@ -1809,10 +1810,10 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
const auto lang = function->GetCompileUnit()->GetLanguage();
const auto name = function->GetMangled().GetMangledName().AsCString();
- const bool extern_c = (Language::LanguageIsC(lang) &&
- !CPlusPlusLanguage::IsCPPMangledName(name)) ||
- (Language::LanguageIsObjC(lang) &&
- !Language::LanguageIsCPlusPlus(lang));
+ const bool extern_c =
+ (Language::LanguageIsC(lang) && !Mangled::IsMangledName(name)) ||
+ (Language::LanguageIsObjC(lang) &&
+ !Language::LanguageIsCPlusPlus(lang));
if (!extern_c) {
TypeSystem *type_system = function->GetDeclContext().GetTypeSystem();
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 4b045d12ad494..89c2a52df4da8 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -62,9 +62,44 @@ void CPlusPlusLanguage::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
+std::unique_ptr<Language::MethodName>
+CPlusPlusLanguage::GetMethodName(ConstString full_name) const {
+ std::unique_ptr<CPlusPlusLanguage::CPPMethodName> cpp_method =
+ std::make_unique<CPlusPlusLanguage::CPPMethodName>(full_name);
+ cpp_method->IsValid();
+ return cpp_method;
+}
+
+std::pair<FunctionNameType, llvm::StringRef>
+CPlusPlusLanguage::GetFunctionNameInfo(ConstString name) const {
+ if (Mangled::IsMangledName(name.GetCString()))
+ return {eFunctionNameTypeFull, llvm::StringRef()};
+
+ FunctionNameType func_name_type = eFunctionNameTypeNone;
+ CPlusPlusLanguage::CPPMethodName method(name);
+ llvm::StringRef basename = method.GetBasename();
+ if (basename.empty()) {
+ llvm::StringRef context;
+ func_name_type |=
+ (ExtractContextAndIdentifier(name.GetCString(), context, basename)
+ ? (eFunctionNameTypeMethod | eFunctionNameTypeBase)
+ : eFunctionNameTypeFull);
+ } else {
+ func_name_type |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
+ }
+
+ if (!method.GetQualifiers().empty()) {
+ // There is a 'const' or other qualifier following the end of the function
+ // parens, this can't be a eFunctionNameTypeBase.
+ func_name_type &= ~eFunctionNameTypeBase;
+ }
+
+ return {func_name_type, basename};
+}
+
bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
const char *mangled_name = mangled.GetMangledName().GetCString();
- return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name);
+ return mangled_name && Mangled::IsMangledName(mangled_name);
}
ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(
@@ -81,7 +116,7 @@ ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(
// eventually handle eSymbolTypeData,
// we will want this back)
{
- CPlusPlusLanguage::MethodName cxx_method(demangled_name);
+ CPlusPlusLanguage::CPPMethodName cxx_method(demangled_name);
if (!cxx_method.GetBasename().empty()) {
std::string shortname;
if (!cxx_method.GetContext().empty())
@@ -106,17 +141,6 @@ Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
return nullptr;
}
-void CPlusPlusLanguage::MethodName::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_parsed = false;
- m_parse_error = false;
-}
-
static bool ReverseFindMatchingChars(const llvm::StringRef &s,
const llvm::StringRef &left_right_chars,
size_t &left_pos, size_t &right_pos,
@@ -181,7 +205,7 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
char const *full_name,
ExecutionContextScope *exe_scope,
VariableList const &args) {
- CPlusPlusLanguage::MethodName cpp_method{ConstString(full_name)};
+ CPlusPlusLanguage::CPPMethodName cpp_method{ConstString(full_name)};
if (!cpp_method.IsValid())
return false;
@@ -208,7 +232,7 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
return true;
}
-bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
+bool CPlusPlusLanguage::CPPMethodName::TrySimplifiedParse() {
// This method tries to parse simple method definitions which are presumably
// most comman in user programs. Definitions that can be parsed by this
// function don't have return types and templates in the name.
@@ -251,7 +275,7 @@ bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
return false;
}
-void CPlusPlusLanguage::MethodName::Parse() {
+void CPlusPlusLanguage::CPPMethodName::Parse() {
if (!m_parsed && m_full) {
if (TrySimplifiedParse()) {
m_parse_error = false;
@@ -268,55 +292,19 @@ void CPlusPlusLanguage::MethodName::Parse() {
m_parse_error = true;
}
}
+ if (m_context.empty()) {
+ m_scope_qualified = std::string(m_basename);
+ } else {
+ m_scope_qualified = m_context;
+ m_scope_qualified += "::";
+ m_scope_qualified += m_basename;
+ }
m_parsed = true;
}
}
-llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
- if (!m_parsed)
- Parse();
- return m_basename;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
- if (!m_parsed)
- Parse();
- return m_context;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
- if (!m_parsed)
- Parse();
- return m_arguments;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
- if (!m_parsed)
- Parse();
- return m_qualifiers;
-}
-
-llvm::StringRef CPlusPlusLanguage::MethodName::GetReturnType() {
- if (!m_parsed)
- Parse();
- return m_return_type;
-}
-
-std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
- if (!m_parsed)
- Parse();
- if (m_context.empty())
- return std::string(m_basename);
-
- std::string res;
- res += m_context;
- res += "::";
- res += m_basename;
- return res;
-}
-
llvm::StringRef
-CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
+CPlusPlusLanguage::CPPMethodName::GetBasenameNoTemplateParameters() {
llvm::StringRef basename = GetBasename();
size_t arg_start, arg_end;
llvm::StringRef parens("<>", 2);
@@ -326,7 +314,7 @@ CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
return basename;
}
-bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
+bool CPlusPlusLanguage::CPPMethodName::ContainsPath(llvm::StringRef path) {
if (!m_parsed)
Parse();
@@ -375,21 +363,9 @@ bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
return false;
}
-bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
- // FIXME!! we should really run through all the known C++ Language plugins
- // and ask each one if this is a C++ mangled name
-
- Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
-
- if (scheme == Mangled::eManglingSchemeNone)
- return false;
-
- return true;
-}
-
bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path,
ConstString demangled) const {
- MethodName demangled_name(demangled);
+ CPPMethodName demangled_name(demangled);
return demangled_name.ContainsPath(path);
}
@@ -588,7 +564,7 @@ ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName(
if (!demangled)
return ConstString();
- CPlusPlusLanguage::MethodName cpp_name(demangled);
+ CPlusPlusLanguage::CPPMethodName cpp_name(demangled);
std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
if (!scope_qualified_name.size())
@@ -611,7 +587,7 @@ ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName(
Mangled mangled(alternate_mangled_name);
ConstString demangled = mangled.GetDemangledName();
- CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
+ CPlusPlusLanguage::CPPMethodName alternate_cpp_name(demangled);
if (!cpp_name.IsValid())
continue;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 623d481bf117f..4529bd1dafea5 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -25,42 +25,9 @@ class CPlusPlusLanguage : public Language {
ClangHighlighter m_highlighter;
public:
- class MethodName {
+ class CPPMethodName : public Language::MethodName {
public:
- MethodName()
- : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers() {}
-
- MethodName(ConstString s)
- : m_full(s), m_basename(), m_context(), m_arguments(), m_qualifiers(),
- m_parsed(false), m_parse_error(false) {}
-
- void Clear();
-
- bool IsValid() {
- if (!m_parsed)
- Parse();
- if (m_parse_error)
- return false;
- return (bool)m_full;
- }
-
- ConstString GetFullName() const { return m_full; }
-
- std::string GetScopeQualifiedName();
-
- llvm::StringRef GetBasename();
-
- llvm::StringRef GetContext();
-
- llvm::StringRef GetArguments();
-
- llvm::StringRef GetQualifiers();
-
- /// Returns the methods return-type.
- ///
- /// Currently returns an empty llvm::StringRef
- /// if the return-type is a function pointer.
- llvm::StringRef GetReturnType();
+ CPPMethodName(ConstString s) : Language::MethodName(s) {}
bool ContainsPath(llvm::StringRef path);
@@ -80,25 +47,20 @@ class CPlusPlusLanguage : public Language {
llvm::StringRef GetBasenameNoTemplateParameters();
protected:
- void Parse();
+ void Parse() override;
bool TrySimplifiedParse();
-
- 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"
- bool m_parsed = false;
- bool m_parse_error = false;
};
CPlusPlusLanguage() = default;
~CPlusPlusLanguage() override = default;
+ virtual std::unique_ptr<Language::MethodName>
+ GetMethodName(ConstString name) const override;
+
+ std::pair<lldb::FunctionNameType, llvm::StringRef>
+ GetFunctionNameInfo(ConstString name) const override;
+
lldb::LanguageType GetLanguageType() const override {
return lldb::eLanguageTypeC_plus_plus;
}
@@ -143,8 +105,6 @@ class CPlusPlusLanguage : public Language {
FunctionNameRepresentation representation,
Stream &s) override;
- static bool IsCPPMangledName(llvm::StringRef name);
-
// Extract C++ context and identifier from a string using heuristic matching
// (as opposed to
// CPlusPlusLanguage::MethodName which has to have a fully qualified C++ name
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 2ae203405cbba..bbd8effe4a69d 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -222,6 +222,18 @@ ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
return variant_names;
}
+std::pair<FunctionNameType, llvm::StringRef>
+ObjCLanguage::GetFunctionNameInfo(ConstString name) const {
+ FunctionNameType func_name_type = eFunctionNameTypeNone;
+
+ if (ObjCLanguage::IsPossibleObjCMethodName(name.GetCString()))
+ func_name_type = eFunctionNameTypeFull;
+ else if (ObjCLanguage::IsPossibleObjCSelector(name.GetCString()))
+ func_name_type = eFunctionNameTypeSelector;
+
+ return {func_name_type, llvm::StringRef()};
+}
+
bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
ConstString demangled_name = mangled.GetDemangledName();
if (!demangled_name)
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 6d265a9be5277..073ea1d730e52 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -142,6 +142,9 @@ class ObjCLanguage : public Language {
std::vector<Language::MethodNameVariant>
GetMethodNameVariants(ConstString method_name) const override;
+ std::pair<lldb::FunctionNameType, llvm::StringRef>
+ GetFunctionNameInfo(ConstString name) const override;
+
bool SymbolNameFitsToLanguage(Mangled mangled) const override;
lldb::TypeCategoryImplSP GetFormatters() override;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 352163ceaae9e..f1d98e780994d 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -14,6 +14,7 @@
#include "clang/Lex/Lexer.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -53,7 +54,6 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h"
@@ -1279,7 +1279,7 @@ void SymbolFilePDB::CacheFunctionNames() {
if (name.empty())
continue;
- if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
+ if (Mangled::IsMangledName(name.c_str())) {
// PDB public symbol has mangled name for its associated function.
if (auto vm_addr = pub_sym_up->getVirtualAddress()) {
if (auto it = addr_ids.find(vm_addr); it != addr_ids.end())
diff --git a/lldb/unittests/Core/CMakeLists.txt b/lldb/unittests/Core/CMakeLists.txt
index 8580f5887ea2b..2c97a0fd815c5 100644
--- a/lldb/unittests/Core/CMakeLists.txt
+++ b/lldb/unittests/Core/CMakeLists.txt
@@ -18,6 +18,7 @@ add_lldb_unittest(LLDBCoreTests
LINK_LIBS
lldbCore
lldbHost
+ lldbPluginCPlusPlusLanguage
lldbPluginObjectFileELF
lldbPluginObjectFileMachO
lldbPluginObjectFilePECOFF
diff --git a/lldb/unittests/Core/RichManglingContextTest.cpp b/lldb/unittests/Core/RichManglingContextTest.cpp
index 65a5503c61a30..dfaea7efa3af0 100644
--- a/lldb/unittests/Core/RichManglingContextTest.cpp
+++ b/lldb/unittests/Core/RichManglingContextTest.cpp
@@ -8,6 +8,8 @@
#include "lldb/Core/RichManglingContext.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "TestingSupport/SubsystemRAII.h"
#include "lldb/Utility/ConstString.h"
#include "gtest/gtest.h"
@@ -27,6 +29,9 @@ TEST(RichManglingContextTest, Basic) {
}
TEST(RichManglingContextTest, FromCxxMethodName) {
+
+ SubsystemRAII<CPlusPlusLanguage> lang;
+
RichManglingContext ItaniumRMC;
ConstString mangled("_ZN3foo3barEv");
EXPECT_TRUE(ItaniumRMC.FromItaniumName(mangled));
@@ -67,6 +72,8 @@ TEST(RichManglingContextTest, SwitchProvider) {
EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
+ SubsystemRAII<CPlusPlusLanguage> lang;
+
EXPECT_TRUE(RMC.FromCxxMethodName(ConstString(demangled)));
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
diff --git a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
index cfdc3163f6a3a..e1f8df118d744 100644
--- a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -212,7 +212,7 @@ TEST(CPlusPlusLanguage, MethodNameParsing) {
"A::operator<=>[abi:tag]<A::B>"}};
for (const auto &test : test_cases) {
- CPlusPlusLanguage::MethodName method(ConstString(test.input));
+ CPlusPlusLanguage::CPPMethodName method(ConstString(test.input));
EXPECT_TRUE(method.IsValid()) << test.input;
if (method.IsValid()) {
EXPECT_EQ(test.return_type, method.GetReturnType().str());
@@ -243,22 +243,22 @@ TEST(CPlusPlusLanguage, InvalidMethodNameParsing) {
};
for (const auto &name : test_cases) {
- CPlusPlusLanguage::MethodName method{ConstString(name)};
+ CPlusPlusLanguage::CPPMethodName method{ConstString(name)};
EXPECT_FALSE(method.IsValid()) << name;
}
}
TEST(CPlusPlusLanguage, ContainsPath) {
- CPlusPlusLanguage::MethodName
- reference_1(ConstString("int foo::bar::func01(int a, double b)"));
- CPlusPlusLanguage::MethodName
- reference_2(ConstString("int foofoo::bar::func01(std::string a, int b)"));
- CPlusPlusLanguage::MethodName reference_3(ConstString("int func01()"));
- CPlusPlusLanguage::MethodName
- reference_4(ConstString("bar::baz::operator bool()"));
- CPlusPlusLanguage::MethodName reference_5(
+ CPlusPlusLanguage::CPPMethodName reference_1(
+ ConstString("int foo::bar::func01(int a, double b)"));
+ CPlusPlusLanguage::CPPMethodName reference_2(
+ ConstString("int foofoo::bar::func01(std::string a, int b)"));
+ CPlusPlusLanguage::CPPMethodName reference_3(ConstString("int func01()"));
+ CPlusPlusLanguage::CPPMethodName reference_4(
+ ConstString("bar::baz::operator bool()"));
+ CPlusPlusLanguage::CPPMethodName reference_5(
ConstString("bar::baz::operator bool<int, Type<double>>()"));
- CPlusPlusLanguage::MethodName reference_6(ConstString(
+ CPlusPlusLanguage::CPPMethodName reference_6(ConstString(
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
EXPECT_TRUE(reference_1.ContainsPath(""));
More information about the lldb-commits
mailing list