[LLDB] Reapply refactored CPlusPlusLanguage::MethodName to break lldb-server dependencies (#135033)
The original PR is #132274. Co-authored-by: @bulbazord Alex Langford
This commit is contained in:
@@ -246,6 +246,8 @@ public:
|
||||
/// 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
|
||||
|
||||
@@ -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 @@ private:
|
||||
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 @@ private:
|
||||
|
||||
/// 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
|
||||
|
||||
@@ -214,6 +214,104 @@ public:
|
||||
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, std::optional<ConstString>>
|
||||
GetFunctionNameInfo(ConstString name) const {
|
||||
return std::pair{lldb::eFunctionNameTypeNone, std::nullopt};
|
||||
};
|
||||
|
||||
/// Returns true iff the given symbol name is compatible with the mangling
|
||||
/// scheme of this language.
|
||||
///
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
@@ -251,7 +251,7 @@ bool Mangled::GetRichManglingInfo(RichManglingContext &context,
|
||||
return false;
|
||||
} else {
|
||||
// Demangled successfully, we can try and parse it with
|
||||
// CPlusPlusLanguage::MethodName.
|
||||
// CPlusPlusLanguage::CxxMethodName.
|
||||
return context.FromCxxMethodName(m_demangled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,98 +641,70 @@ 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();
|
||||
llvm::StringRef basename;
|
||||
llvm::StringRef context;
|
||||
: m_name(name), m_lookup_name(name), m_language(language) {
|
||||
std::optional<ConstString> basename;
|
||||
|
||||
std::vector<Language *> languages;
|
||||
{
|
||||
std::vector<LanguageType> lang_types;
|
||||
if (language != eLanguageTypeUnknown)
|
||||
lang_types.push_back(language);
|
||||
else
|
||||
lang_types = {eLanguageTypeObjC, eLanguageTypeC_plus_plus};
|
||||
|
||||
for (LanguageType lang_type : lang_types) {
|
||||
if (Language *lang = Language::FindPlugin(lang_type))
|
||||
languages.push_back(lang);
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
m_name_type_mask = eFunctionNameTypeFull;
|
||||
} 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);
|
||||
for (Language *lang : languages) {
|
||||
auto info = lang->GetFunctionNameInfo(name);
|
||||
if (info.first != eFunctionNameTypeNone) {
|
||||
m_name_type_mask |= info.first;
|
||||
if (!basename && info.second)
|
||||
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;
|
||||
}
|
||||
} 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);
|
||||
for (Language *lang : languages) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
// Still try and get a basename in case someone specifies a name type mask
|
||||
// of eFunctionNameTypeFull and a name like "A::func"
|
||||
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);
|
||||
info.first != eFunctionNameTypeNone && !basename && info.second) {
|
||||
basename = info.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
m_lookup_name.SetString(basename);
|
||||
if (basename) {
|
||||
// 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 +763,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 +775,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 +962,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;
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -62,9 +62,47 @@ void CPlusPlusLanguage::Terminate() {
|
||||
PluginManager::UnregisterPlugin(CreateInstance);
|
||||
}
|
||||
|
||||
std::unique_ptr<Language::MethodName>
|
||||
CPlusPlusLanguage::GetMethodName(ConstString full_name) const {
|
||||
std::unique_ptr<CxxMethodName> cpp_method =
|
||||
std::make_unique<CxxMethodName>(full_name);
|
||||
cpp_method->IsValid();
|
||||
return cpp_method;
|
||||
}
|
||||
|
||||
std::pair<FunctionNameType, std::optional<ConstString>>
|
||||
CPlusPlusLanguage::GetFunctionNameInfo(ConstString name) const {
|
||||
if (Mangled::IsMangledName(name.GetCString()))
|
||||
return {eFunctionNameTypeFull, std::nullopt};
|
||||
|
||||
FunctionNameType func_name_type = eFunctionNameTypeNone;
|
||||
CxxMethodName 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);
|
||||
}
|
||||
|
||||
if (basename.empty())
|
||||
return {func_name_type, std::nullopt};
|
||||
else
|
||||
return {func_name_type, ConstString(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 +119,7 @@ ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(
|
||||
// eventually handle eSymbolTypeData,
|
||||
// we will want this back)
|
||||
{
|
||||
CPlusPlusLanguage::MethodName cxx_method(demangled_name);
|
||||
CxxMethodName cxx_method(demangled_name);
|
||||
if (!cxx_method.GetBasename().empty()) {
|
||||
std::string shortname;
|
||||
if (!cxx_method.GetContext().empty())
|
||||
@@ -106,17 +144,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 +208,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::CxxMethodName cpp_method{ConstString(full_name)};
|
||||
|
||||
if (!cpp_method.IsValid())
|
||||
return false;
|
||||
@@ -208,7 +235,7 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
|
||||
bool CPlusPlusLanguage::CxxMethodName::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 +278,7 @@ bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPlusPlusLanguage::MethodName::Parse() {
|
||||
void CPlusPlusLanguage::CxxMethodName::Parse() {
|
||||
if (!m_parsed && m_full) {
|
||||
if (TrySimplifiedParse()) {
|
||||
m_parse_error = false;
|
||||
@@ -268,55 +295,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::CxxMethodName::GetBasenameNoTemplateParameters() {
|
||||
llvm::StringRef basename = GetBasename();
|
||||
size_t arg_start, arg_end;
|
||||
llvm::StringRef parens("<>", 2);
|
||||
@@ -326,7 +317,7 @@ CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() {
|
||||
return basename;
|
||||
}
|
||||
|
||||
bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) {
|
||||
bool CPlusPlusLanguage::CxxMethodName::ContainsPath(llvm::StringRef path) {
|
||||
if (!m_parsed)
|
||||
Parse();
|
||||
|
||||
@@ -375,21 +366,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);
|
||||
CxxMethodName demangled_name(demangled);
|
||||
return demangled_name.ContainsPath(path);
|
||||
}
|
||||
|
||||
@@ -588,7 +567,7 @@ ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName(
|
||||
if (!demangled)
|
||||
return ConstString();
|
||||
|
||||
CPlusPlusLanguage::MethodName cpp_name(demangled);
|
||||
CxxMethodName cpp_name(demangled);
|
||||
std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
|
||||
|
||||
if (!scope_qualified_name.size())
|
||||
@@ -611,7 +590,7 @@ ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName(
|
||||
Mangled mangled(alternate_mangled_name);
|
||||
ConstString demangled = mangled.GetDemangledName();
|
||||
|
||||
CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
|
||||
CxxMethodName alternate_cpp_name(demangled);
|
||||
if (!cpp_name.IsValid())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -25,42 +25,9 @@ class CPlusPlusLanguage : public Language {
|
||||
ClangHighlighter m_highlighter;
|
||||
|
||||
public:
|
||||
class MethodName {
|
||||
class CxxMethodName : 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();
|
||||
CxxMethodName(ConstString s) : Language::MethodName(s) {}
|
||||
|
||||
bool ContainsPath(llvm::StringRef path);
|
||||
|
||||
@@ -80,25 +47,20 @@ public:
|
||||
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, std::optional<ConstString>>
|
||||
GetFunctionNameInfo(ConstString name) const override;
|
||||
|
||||
lldb::LanguageType GetLanguageType() const override {
|
||||
return lldb::eLanguageTypeC_plus_plus;
|
||||
}
|
||||
@@ -143,12 +105,10 @@ public:
|
||||
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
|
||||
// with parens and arguments.
|
||||
// CPlusPlusLanguage::CxxMethodName which has to have a fully qualified C++
|
||||
// name with parens and arguments.
|
||||
// If the name is a lone C identifier (e.g. C) or a qualified C identifier
|
||||
// (e.g. A::B::C) it will return true,
|
||||
// and identifier will be the identifier (C and C respectively) and the
|
||||
|
||||
@@ -60,8 +60,8 @@ Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<const ObjCLanguage::MethodName>
|
||||
ObjCLanguage::MethodName::Create(llvm::StringRef name, bool strict) {
|
||||
std::optional<const ObjCLanguage::ObjCMethodName>
|
||||
ObjCLanguage::ObjCMethodName::Create(llvm::StringRef name, bool strict) {
|
||||
if (name.empty())
|
||||
return std::nullopt;
|
||||
|
||||
@@ -96,11 +96,11 @@ ObjCLanguage::MethodName::Create(llvm::StringRef name, bool strict) {
|
||||
|
||||
// If we've gotten here, we're confident that this looks enough like an
|
||||
// Objective-C method to treat it like one.
|
||||
ObjCLanguage::MethodName method_name(name, type);
|
||||
ObjCLanguage::ObjCMethodName method_name(name, type);
|
||||
return method_name;
|
||||
}
|
||||
|
||||
llvm::StringRef ObjCLanguage::MethodName::GetClassName() const {
|
||||
llvm::StringRef ObjCLanguage::ObjCMethodName::GetClassName() const {
|
||||
llvm::StringRef full = m_full;
|
||||
const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
|
||||
const size_t paren_pos = full.find('(', class_start_pos);
|
||||
@@ -113,14 +113,14 @@ llvm::StringRef ObjCLanguage::MethodName::GetClassName() const {
|
||||
return full.substr(class_start_pos, space_pos - class_start_pos);
|
||||
}
|
||||
|
||||
llvm::StringRef ObjCLanguage::MethodName::GetClassNameWithCategory() const {
|
||||
llvm::StringRef ObjCLanguage::ObjCMethodName::GetClassNameWithCategory() const {
|
||||
llvm::StringRef full = m_full;
|
||||
const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
|
||||
const size_t space_pos = full.find(' ', class_start_pos);
|
||||
return full.substr(class_start_pos, space_pos - class_start_pos);
|
||||
}
|
||||
|
||||
llvm::StringRef ObjCLanguage::MethodName::GetSelector() const {
|
||||
llvm::StringRef ObjCLanguage::ObjCMethodName::GetSelector() const {
|
||||
llvm::StringRef full = m_full;
|
||||
const size_t space_pos = full.find(' ');
|
||||
if (space_pos == llvm::StringRef::npos)
|
||||
@@ -129,7 +129,7 @@ llvm::StringRef ObjCLanguage::MethodName::GetSelector() const {
|
||||
return full.substr(space_pos + 1, closing_bracket - space_pos - 1);
|
||||
}
|
||||
|
||||
llvm::StringRef ObjCLanguage::MethodName::GetCategory() const {
|
||||
llvm::StringRef ObjCLanguage::ObjCMethodName::GetCategory() const {
|
||||
llvm::StringRef full = m_full;
|
||||
const size_t open_paren_pos = full.find('(');
|
||||
const size_t close_paren_pos = full.find(')');
|
||||
@@ -142,7 +142,7 @@ llvm::StringRef ObjCLanguage::MethodName::GetCategory() const {
|
||||
close_paren_pos - (open_paren_pos + 1));
|
||||
}
|
||||
|
||||
std::string ObjCLanguage::MethodName::GetFullNameWithoutCategory() const {
|
||||
std::string ObjCLanguage::ObjCMethodName::GetFullNameWithoutCategory() const {
|
||||
llvm::StringRef full = m_full;
|
||||
const size_t open_paren_pos = full.find('(');
|
||||
const size_t close_paren_pos = full.find(')');
|
||||
@@ -179,8 +179,8 @@ std::string ObjCLanguage::MethodName::GetFullNameWithoutCategory() const {
|
||||
std::vector<Language::MethodNameVariant>
|
||||
ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
|
||||
std::vector<Language::MethodNameVariant> variant_names;
|
||||
std::optional<const ObjCLanguage::MethodName> objc_method =
|
||||
ObjCLanguage::MethodName::Create(method_name.GetStringRef(), false);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(method_name.GetStringRef(), false);
|
||||
if (!objc_method)
|
||||
return variant_names;
|
||||
|
||||
@@ -222,6 +222,19 @@ ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
|
||||
return variant_names;
|
||||
}
|
||||
|
||||
std::pair<FunctionNameType, std::optional<ConstString>>
|
||||
ObjCLanguage::GetFunctionNameInfo(ConstString name) const {
|
||||
FunctionNameType func_name_type = eFunctionNameTypeNone;
|
||||
|
||||
if (ObjCLanguage::IsPossibleObjCMethodName(name.GetCString()))
|
||||
func_name_type = eFunctionNameTypeFull;
|
||||
|
||||
if (ObjCLanguage::IsPossibleObjCSelector(name.GetCString()))
|
||||
func_name_type |= eFunctionNameTypeSelector;
|
||||
|
||||
return {func_name_type, std::nullopt};
|
||||
}
|
||||
|
||||
bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
|
||||
ConstString demangled_name = mangled.GetDemangledName();
|
||||
if (!demangled_name)
|
||||
|
||||
@@ -23,9 +23,9 @@ class ObjCLanguage : public Language {
|
||||
ClangHighlighter m_highlighter;
|
||||
|
||||
public:
|
||||
class MethodName {
|
||||
class ObjCMethodName {
|
||||
public:
|
||||
/// The static factory method for creating a MethodName.
|
||||
/// The static factory method for creating a ObjCMethodName.
|
||||
///
|
||||
/// \param[in] name
|
||||
/// The name of the method.
|
||||
@@ -35,9 +35,9 @@ public:
|
||||
/// front of the name.
|
||||
///
|
||||
/// \return If the name failed to parse as a valid Objective-C method name,
|
||||
/// returns std::nullopt. Otherwise returns a const MethodName.
|
||||
static std::optional<const MethodName> Create(llvm::StringRef name,
|
||||
bool strict);
|
||||
/// returns std::nullopt. Otherwise returns a const ObjCMethodName.
|
||||
static std::optional<const ObjCMethodName> Create(llvm::StringRef name,
|
||||
bool strict);
|
||||
|
||||
/// Determines if this method is a class method
|
||||
///
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
protected:
|
||||
enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
|
||||
|
||||
MethodName(llvm::StringRef name, Type type)
|
||||
ObjCMethodName(llvm::StringRef name, Type type)
|
||||
: m_full(name.str()), m_type(type) {}
|
||||
|
||||
const std::string m_full;
|
||||
@@ -142,6 +142,9 @@ public:
|
||||
std::vector<Language::MethodNameVariant>
|
||||
GetMethodNameVariants(ConstString method_name) const override;
|
||||
|
||||
std::pair<lldb::FunctionNameType, std::optional<ConstString>>
|
||||
GetFunctionNameInfo(ConstString name) const override;
|
||||
|
||||
bool SymbolNameFitsToLanguage(Mangled mangled) const override;
|
||||
|
||||
lldb::TypeCategoryImplSP GetFormatters() override;
|
||||
|
||||
@@ -1066,7 +1066,7 @@ ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) {
|
||||
}
|
||||
|
||||
bool DWARFASTParserClang::ParseObjCMethod(
|
||||
const ObjCLanguage::MethodName &objc_method, const DWARFDIE &die,
|
||||
const ObjCLanguage::ObjCMethodName &objc_method, const DWARFDIE &die,
|
||||
CompilerType clang_type, const ParsedDWARFTypeAttributes &attrs,
|
||||
bool is_variadic) {
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
@@ -1318,9 +1318,9 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
|
||||
if (attrs.name) {
|
||||
bool type_handled = false;
|
||||
if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
|
||||
if (std::optional<const ObjCLanguage::MethodName> objc_method =
|
||||
ObjCLanguage::MethodName::Create(attrs.name.GetStringRef(),
|
||||
true)) {
|
||||
if (std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(attrs.name.GetStringRef(),
|
||||
true)) {
|
||||
type_handled =
|
||||
ParseObjCMethod(*objc_method, die, clang_type, attrs, is_variadic);
|
||||
} else if (is_cxx_method) {
|
||||
@@ -2753,16 +2753,16 @@ PropertyAttributes::PropertyAttributes(const DWARFDIE &die) {
|
||||
// Check if the property getter/setter were provided as full names.
|
||||
// We want basenames, so we extract them.
|
||||
if (prop_getter_name && prop_getter_name[0] == '-') {
|
||||
std::optional<const ObjCLanguage::MethodName> prop_getter_method =
|
||||
ObjCLanguage::MethodName::Create(prop_getter_name, true);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> prop_getter_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(prop_getter_name, true);
|
||||
if (prop_getter_method)
|
||||
prop_getter_name =
|
||||
ConstString(prop_getter_method->GetSelector()).GetCString();
|
||||
}
|
||||
|
||||
if (prop_setter_name && prop_setter_name[0] == '-') {
|
||||
std::optional<const ObjCLanguage::MethodName> prop_setter_method =
|
||||
ObjCLanguage::MethodName::Create(prop_setter_name, true);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> prop_setter_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(prop_setter_name, true);
|
||||
if (prop_setter_method)
|
||||
prop_setter_name =
|
||||
ConstString(prop_setter_method->GetSelector()).GetCString();
|
||||
|
||||
@@ -449,7 +449,7 @@ private:
|
||||
///
|
||||
/// \returns true on success
|
||||
bool
|
||||
ParseObjCMethod(const lldb_private::ObjCLanguage::MethodName &objc_method,
|
||||
ParseObjCMethod(const lldb_private::ObjCLanguage::ObjCMethodName &objc_method,
|
||||
const lldb_private::plugin::dwarf::DWARFDIE &die,
|
||||
lldb_private::CompilerType clang_type,
|
||||
const ParsedDWARFTypeAttributes &attrs, bool is_variadic);
|
||||
|
||||
@@ -308,8 +308,8 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
|
||||
bool is_objc_method = false;
|
||||
if (cu_language == eLanguageTypeObjC ||
|
||||
cu_language == eLanguageTypeObjC_plus_plus) {
|
||||
std::optional<const ObjCLanguage::MethodName> objc_method =
|
||||
ObjCLanguage::MethodName::Create(name, true);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(name, true);
|
||||
if (objc_method) {
|
||||
is_objc_method = true;
|
||||
ConstString class_name_with_category(
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -19,6 +19,7 @@ add_lldb_unittest(LLDBCoreTests
|
||||
LINK_LIBS
|
||||
lldbCore
|
||||
lldbHost
|
||||
lldbPluginCPlusPlusLanguage
|
||||
lldbPluginObjectFileELF
|
||||
lldbPluginObjectFileMachO
|
||||
lldbPluginObjectFilePECOFF
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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::CxxMethodName 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::CxxMethodName 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::CxxMethodName reference_1(
|
||||
ConstString("int foo::bar::func01(int a, double b)"));
|
||||
CPlusPlusLanguage::CxxMethodName reference_2(
|
||||
ConstString("int foofoo::bar::func01(std::string a, int b)"));
|
||||
CPlusPlusLanguage::CxxMethodName reference_3(ConstString("int func01()"));
|
||||
CPlusPlusLanguage::CxxMethodName reference_4(
|
||||
ConstString("bar::baz::operator bool()"));
|
||||
CPlusPlusLanguage::CxxMethodName reference_5(
|
||||
ConstString("bar::baz::operator bool<int, Type<double>>()"));
|
||||
CPlusPlusLanguage::MethodName reference_6(ConstString(
|
||||
CPlusPlusLanguage::CxxMethodName reference_6(ConstString(
|
||||
"bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
|
||||
|
||||
EXPECT_TRUE(reference_1.ContainsPath(""));
|
||||
|
||||
@@ -42,8 +42,8 @@ TEST(ObjCLanguage, MethodNameParsing) {
|
||||
|
||||
// First, be strict
|
||||
for (const auto &test : strict_cases) {
|
||||
std::optional<const ObjCLanguage::MethodName> method =
|
||||
ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> method =
|
||||
ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ true);
|
||||
EXPECT_TRUE(method.has_value());
|
||||
EXPECT_EQ(test.full_name_sans_category,
|
||||
method->GetFullNameWithoutCategory());
|
||||
@@ -56,15 +56,15 @@ TEST(ObjCLanguage, MethodNameParsing) {
|
||||
|
||||
// We should make sure strict parsing does not accept lax cases
|
||||
for (const auto &test : lax_cases) {
|
||||
std::optional<const ObjCLanguage::MethodName> method =
|
||||
ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> method =
|
||||
ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ true);
|
||||
EXPECT_FALSE(method.has_value());
|
||||
}
|
||||
|
||||
// All strict cases should work when not lax
|
||||
for (const auto &test : strict_cases) {
|
||||
std::optional<const ObjCLanguage::MethodName> method =
|
||||
ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> method =
|
||||
ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ false);
|
||||
EXPECT_TRUE(method.has_value());
|
||||
EXPECT_EQ(test.full_name_sans_category,
|
||||
method->GetFullNameWithoutCategory());
|
||||
@@ -77,8 +77,8 @@ TEST(ObjCLanguage, MethodNameParsing) {
|
||||
|
||||
// Make sure non-strict parsing works
|
||||
for (const auto &test : lax_cases) {
|
||||
std::optional<const ObjCLanguage::MethodName> method =
|
||||
ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> method =
|
||||
ObjCLanguage::ObjCMethodName::Create(test.input, /*strict = */ false);
|
||||
EXPECT_TRUE(method.has_value());
|
||||
EXPECT_EQ(test.full_name_sans_category,
|
||||
method->GetFullNameWithoutCategory());
|
||||
@@ -103,12 +103,12 @@ TEST(ObjCLanguage, InvalidMethodNameParsing) {
|
||||
"[]"};
|
||||
|
||||
for (const auto &name : test_cases) {
|
||||
std::optional<const ObjCLanguage::MethodName> strict_method =
|
||||
ObjCLanguage::MethodName::Create(name, /*strict = */ false);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> strict_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);
|
||||
EXPECT_FALSE(strict_method.has_value());
|
||||
|
||||
std::optional<const ObjCLanguage::MethodName> lax_method =
|
||||
ObjCLanguage::MethodName::Create(name, /*strict = */ false);
|
||||
std::optional<const ObjCLanguage::ObjCMethodName> lax_method =
|
||||
ObjCLanguage::ObjCMethodName::Create(name, /*strict = */ false);
|
||||
EXPECT_FALSE(lax_method.has_value());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user