Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lldb/include/lldb/Core/Mangled.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 IsCPPMangledName(llvm::StringRef name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about calling this IsMangledName and. dropping the CPP/Cxx part altogether? Confusingly the implementation isn't actually checking if the mangling scheme is Itanium, so. this will fire too for Rust and Swift. Maybe something (like Rust) is relying on that, I don't know.

Suggested change
static bool IsCPPMangledName(llvm::StringRef name);
static bool IsMangledName(llvm::StringRef name);

That would also provide some parity with this oddly named helper function:

static inline bool cstring_is_mangled(llvm::StringRef s) {
  return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone;
}

The current name makes it look like it should really belong in the C++ language plugin, where it was previously.


/// Decode a serialized version of this object from data.
///
/// \param data
Expand Down
16 changes: 2 additions & 14 deletions lldb/include/lldb/Core/RichManglingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand Down
98 changes: 98 additions & 0 deletions lldb/include/lldb/Target/Language.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
2 changes: 0 additions & 2 deletions lldb/source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ add_lldb_library(lldbCore
lldbUtility
lldbValueObject
lldbVersion
lldbPluginCPlusPlusLanguage
lldbPluginObjCLanguage
Comment on lines -74 to -75
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can now add NO_PLUGIN_DEPENDENCIES to add_lldb_library above and resolve the FIXME. 🥳

${LLDB_CURSES_LIBS}

CLANG_LIBS
Expand Down
5 changes: 5 additions & 0 deletions lldb/source/Core/Mangled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ static inline bool cstring_is_mangled(llvm::StringRef s) {

#pragma mark Mangled

bool Mangled::IsCPPMangledName(llvm::StringRef name) {
Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
return (scheme != Mangled::eManglingSchemeNone);
}

Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
if (name.empty())
return Mangled::eManglingSchemeNone;
Expand Down
151 changes: 63 additions & 88 deletions lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -641,98 +638,75 @@ 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;
auto collect_language_plugins = [&languages](Language *lang) {
languages.push_back(lang);
return true;
};

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;
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;
}
}
} 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) {
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;
}
} 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;
}
}

Expand Down Expand Up @@ -791,7 +765,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()) {
Expand All @@ -802,20 +777,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;
Expand Down Expand Up @@ -988,8 +964,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;
Expand Down
Loading