forked from OSchip/llvm-project
[lldb] Improve RichManglingContext ergonomics (NFC)
Have the different ::Parse.* methods return the demangled string directly instead of having to go through ::GetBufferRef. Differential revision: https://reviews.llvm.org/D118953
This commit is contained in:
parent
9d1857f69f
commit
fa52788b7a
|
@ -43,25 +43,15 @@ public:
|
||||||
bool IsCtorOrDtor() const;
|
bool IsCtorOrDtor() const;
|
||||||
|
|
||||||
/// Get the base name of a function. This doesn't include trailing template
|
/// Get the base name of a function. This doesn't include trailing template
|
||||||
/// arguments, ie "a::b<int>" gives "b". The result will overwrite the
|
/// arguments, ie "a::b<int>" gives "b".
|
||||||
/// internal buffer. It can be obtained via GetBufferRef().
|
llvm::StringRef ParseFunctionBaseName();
|
||||||
void ParseFunctionBaseName();
|
|
||||||
|
|
||||||
/// Get the context name for a function. For "a::b::c", this function returns
|
/// Get the context name for a function. For "a::b::c", this function returns
|
||||||
/// "a::b". The result will overwrite the internal buffer. It can be obtained
|
/// "a::b".
|
||||||
/// via GetBufferRef().
|
llvm::StringRef ParseFunctionDeclContextName();
|
||||||
void ParseFunctionDeclContextName();
|
|
||||||
|
|
||||||
/// Get the entire demangled name. The result will overwrite the internal
|
/// Get the entire demangled name.
|
||||||
/// buffer. It can be obtained via GetBufferRef().
|
llvm::StringRef ParseFullName();
|
||||||
void ParseFullName();
|
|
||||||
|
|
||||||
/// Obtain a StringRef to the internal buffer that holds the result of the
|
|
||||||
/// most recent ParseXy() operation. The next ParseXy() call invalidates it.
|
|
||||||
llvm::StringRef GetBufferRef() const {
|
|
||||||
assert(m_provider != None && "Initialize a provider first");
|
|
||||||
return m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage };
|
enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage };
|
||||||
|
@ -69,9 +59,6 @@ private:
|
||||||
/// Selects the rich mangling info provider.
|
/// Selects the rich mangling info provider.
|
||||||
InfoProvider m_provider = None;
|
InfoProvider m_provider = None;
|
||||||
|
|
||||||
/// Reference to the buffer used for results of ParseXy() operations.
|
|
||||||
llvm::StringRef m_buffer;
|
|
||||||
|
|
||||||
/// Members for ItaniumPartialDemangler
|
/// Members for ItaniumPartialDemangler
|
||||||
llvm::ItaniumPartialDemangler m_ipd;
|
llvm::ItaniumPartialDemangler m_ipd;
|
||||||
/// Note: m_ipd_buf is a raw pointer due to being resized by realloc via
|
/// Note: m_ipd_buf is a raw pointer due to being resized by realloc via
|
||||||
|
@ -93,7 +80,7 @@ private:
|
||||||
void ResetProvider(InfoProvider new_provider);
|
void ResetProvider(InfoProvider new_provider);
|
||||||
|
|
||||||
/// Uniform handling of string buffers for ItaniumPartialDemangler.
|
/// Uniform handling of string buffers for ItaniumPartialDemangler.
|
||||||
void processIPDStrResult(char *ipd_res, size_t res_len);
|
llvm::StringRef processIPDStrResult(char *ipd_res, size_t res_len);
|
||||||
|
|
||||||
/// Cast the given parser to the given type. Ideally we would have a type
|
/// 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
|
/// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
|
||||||
|
|
|
@ -217,8 +217,7 @@ bool Mangled::DemangleWithRichManglingInfo(
|
||||||
if (context.FromItaniumName(m_mangled)) {
|
if (context.FromItaniumName(m_mangled)) {
|
||||||
// If we got an info, we have a name. Copy to string pool and connect the
|
// If we got an info, we have a name. Copy to string pool and connect the
|
||||||
// counterparts to accelerate later access in GetDemangledName().
|
// counterparts to accelerate later access in GetDemangledName().
|
||||||
context.ParseFullName();
|
m_demangled.SetStringWithMangledCounterpart(context.ParseFullName(),
|
||||||
m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(),
|
|
||||||
m_mangled);
|
m_mangled);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -80,15 +80,15 @@ bool RichManglingContext::IsCtorOrDtor() const {
|
||||||
llvm_unreachable("Fully covered switch above!");
|
llvm_unreachable("Fully covered switch above!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
|
llvm::StringRef RichManglingContext::processIPDStrResult(char *ipd_res,
|
||||||
|
size_t res_size) {
|
||||||
// Error case: Clear the buffer.
|
// Error case: Clear the buffer.
|
||||||
if (LLVM_UNLIKELY(ipd_res == nullptr)) {
|
if (LLVM_UNLIKELY(ipd_res == nullptr)) {
|
||||||
assert(res_size == m_ipd_buf_size &&
|
assert(res_size == m_ipd_buf_size &&
|
||||||
"Failed IPD queries keep the original size in the N parameter");
|
"Failed IPD queries keep the original size in the N parameter");
|
||||||
|
|
||||||
m_ipd_buf[0] = '\0';
|
m_ipd_buf[0] = '\0';
|
||||||
m_buffer = llvm::StringRef(m_ipd_buf, 0);
|
return llvm::StringRef(m_ipd_buf, 0);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPD's res_size includes null terminator.
|
// IPD's res_size includes null terminator.
|
||||||
|
@ -106,60 +106,54 @@ void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 99% case: Just remember the string length.
|
// 99% case: Just remember the string length.
|
||||||
m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
|
return llvm::StringRef(m_ipd_buf, res_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichManglingContext::ParseFunctionBaseName() {
|
llvm::StringRef RichManglingContext::ParseFunctionBaseName() {
|
||||||
assert(m_provider != None && "Initialize a provider first");
|
assert(m_provider != None && "Initialize a provider first");
|
||||||
switch (m_provider) {
|
switch (m_provider) {
|
||||||
case ItaniumPartialDemangler: {
|
case ItaniumPartialDemangler: {
|
||||||
auto n = m_ipd_buf_size;
|
auto n = m_ipd_buf_size;
|
||||||
auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
|
auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
|
||||||
processIPDStrResult(buf, n);
|
return processIPDStrResult(buf, n);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case PluginCxxLanguage:
|
case PluginCxxLanguage:
|
||||||
m_buffer =
|
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
|
||||||
get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
|
->GetBasename();
|
||||||
return;
|
|
||||||
case None:
|
case None:
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichManglingContext::ParseFunctionDeclContextName() {
|
llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {
|
||||||
assert(m_provider != None && "Initialize a provider first");
|
assert(m_provider != None && "Initialize a provider first");
|
||||||
switch (m_provider) {
|
switch (m_provider) {
|
||||||
case ItaniumPartialDemangler: {
|
case ItaniumPartialDemangler: {
|
||||||
auto n = m_ipd_buf_size;
|
auto n = m_ipd_buf_size;
|
||||||
auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
|
auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
|
||||||
processIPDStrResult(buf, n);
|
return processIPDStrResult(buf, n);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case PluginCxxLanguage:
|
case PluginCxxLanguage:
|
||||||
m_buffer =
|
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
|
||||||
get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
|
->GetContext();
|
||||||
return;
|
|
||||||
case None:
|
case None:
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichManglingContext::ParseFullName() {
|
llvm::StringRef RichManglingContext::ParseFullName() {
|
||||||
assert(m_provider != None && "Initialize a provider first");
|
assert(m_provider != None && "Initialize a provider first");
|
||||||
switch (m_provider) {
|
switch (m_provider) {
|
||||||
case ItaniumPartialDemangler: {
|
case ItaniumPartialDemangler: {
|
||||||
auto n = m_ipd_buf_size;
|
auto n = m_ipd_buf_size;
|
||||||
auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
|
auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
|
||||||
processIPDStrResult(buf, n);
|
return processIPDStrResult(buf, n);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case PluginCxxLanguage:
|
case PluginCxxLanguage:
|
||||||
m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
|
return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
|
||||||
->GetFullName()
|
->GetFullName()
|
||||||
.GetStringRef();
|
.GetStringRef();
|
||||||
return;
|
|
||||||
case None:
|
case None:
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,16 +383,13 @@ void Symtab::RegisterMangledNameEntry(
|
||||||
std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
|
std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
|
||||||
RichManglingContext &rmc) {
|
RichManglingContext &rmc) {
|
||||||
// Only register functions that have a base name.
|
// Only register functions that have a base name.
|
||||||
rmc.ParseFunctionBaseName();
|
llvm::StringRef base_name = rmc.ParseFunctionBaseName();
|
||||||
llvm::StringRef base_name = rmc.GetBufferRef();
|
|
||||||
if (base_name.empty())
|
if (base_name.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// The base name will be our entry's name.
|
// The base name will be our entry's name.
|
||||||
NameToIndexMap::Entry entry(ConstString(base_name), value);
|
NameToIndexMap::Entry entry(ConstString(base_name), value);
|
||||||
|
llvm::StringRef decl_context = rmc.ParseFunctionDeclContextName();
|
||||||
rmc.ParseFunctionDeclContextName();
|
|
||||||
llvm::StringRef decl_context = rmc.GetBufferRef();
|
|
||||||
|
|
||||||
// Register functions with no context.
|
// Register functions with no context.
|
||||||
if (decl_context.empty()) {
|
if (decl_context.empty()) {
|
||||||
|
|
|
@ -18,18 +18,12 @@ using namespace lldb_private;
|
||||||
TEST(RichManglingContextTest, Basic) {
|
TEST(RichManglingContextTest, Basic) {
|
||||||
RichManglingContext RMC;
|
RichManglingContext RMC;
|
||||||
ConstString mangled("_ZN3foo3barEv");
|
ConstString mangled("_ZN3foo3barEv");
|
||||||
|
|
||||||
EXPECT_TRUE(RMC.FromItaniumName(mangled));
|
EXPECT_TRUE(RMC.FromItaniumName(mangled));
|
||||||
|
|
||||||
EXPECT_FALSE(RMC.IsCtorOrDtor());
|
EXPECT_FALSE(RMC.IsCtorOrDtor());
|
||||||
|
EXPECT_EQ("foo", RMC.ParseFunctionDeclContextName());
|
||||||
RMC.ParseFunctionDeclContextName();
|
EXPECT_EQ("bar", RMC.ParseFunctionBaseName());
|
||||||
EXPECT_EQ("foo", RMC.GetBufferRef());
|
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
|
||||||
|
|
||||||
RMC.ParseFunctionBaseName();
|
|
||||||
EXPECT_EQ("bar", RMC.GetBufferRef());
|
|
||||||
|
|
||||||
RMC.ParseFullName();
|
|
||||||
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RichManglingContextTest, FromCxxMethodName) {
|
TEST(RichManglingContextTest, FromCxxMethodName) {
|
||||||
|
@ -41,19 +35,12 @@ TEST(RichManglingContextTest, FromCxxMethodName) {
|
||||||
ConstString demangled("foo::bar()");
|
ConstString demangled("foo::bar()");
|
||||||
EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(demangled));
|
EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(demangled));
|
||||||
|
|
||||||
EXPECT_TRUE(ItaniumRMC.IsCtorOrDtor() == CxxMethodRMC.IsCtorOrDtor());
|
EXPECT_EQ(ItaniumRMC.IsCtorOrDtor(), CxxMethodRMC.IsCtorOrDtor());
|
||||||
|
EXPECT_EQ(ItaniumRMC.ParseFunctionDeclContextName(),
|
||||||
ItaniumRMC.ParseFunctionDeclContextName();
|
CxxMethodRMC.ParseFunctionDeclContextName());
|
||||||
CxxMethodRMC.ParseFunctionDeclContextName();
|
EXPECT_EQ(ItaniumRMC.ParseFunctionBaseName(),
|
||||||
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
|
CxxMethodRMC.ParseFunctionBaseName());
|
||||||
|
EXPECT_EQ(ItaniumRMC.ParseFullName(), CxxMethodRMC.ParseFullName());
|
||||||
ItaniumRMC.ParseFunctionBaseName();
|
|
||||||
CxxMethodRMC.ParseFunctionBaseName();
|
|
||||||
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
|
|
||||||
|
|
||||||
ItaniumRMC.ParseFullName();
|
|
||||||
CxxMethodRMC.ParseFullName();
|
|
||||||
EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
|
|
||||||
|
|
||||||
// Construct with a random name.
|
// Construct with a random name.
|
||||||
{
|
{
|
||||||
|
@ -68,8 +55,7 @@ TEST(RichManglingContextTest, FromCxxMethodName) {
|
||||||
ConstString("void * operator new(unsigned __int64)")));
|
ConstString("void * operator new(unsigned __int64)")));
|
||||||
|
|
||||||
// We expect its context is empty.
|
// We expect its context is empty.
|
||||||
CxxMethodRMC.ParseFunctionDeclContextName();
|
EXPECT_TRUE(CxxMethodRMC.ParseFunctionDeclContextName().empty());
|
||||||
EXPECT_TRUE(CxxMethodRMC.GetBufferRef().empty());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,16 +65,13 @@ TEST(RichManglingContextTest, SwitchProvider) {
|
||||||
llvm::StringRef demangled = "foo::bar()";
|
llvm::StringRef demangled = "foo::bar()";
|
||||||
|
|
||||||
EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
|
EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
|
||||||
RMC.ParseFullName();
|
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
|
||||||
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
|
|
||||||
|
|
||||||
EXPECT_TRUE(RMC.FromCxxMethodName(ConstString(demangled)));
|
EXPECT_TRUE(RMC.FromCxxMethodName(ConstString(demangled)));
|
||||||
RMC.ParseFullName();
|
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
|
||||||
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
|
|
||||||
|
|
||||||
EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
|
EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
|
||||||
RMC.ParseFullName();
|
EXPECT_EQ("foo::bar()", RMC.ParseFullName());
|
||||||
EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RichManglingContextTest, IPDRealloc) {
|
TEST(RichManglingContextTest, IPDRealloc) {
|
||||||
|
@ -116,13 +99,11 @@ TEST(RichManglingContextTest, IPDRealloc) {
|
||||||
|
|
||||||
// Demangle the short one.
|
// Demangle the short one.
|
||||||
EXPECT_TRUE(RMC.FromItaniumName(ConstString(ShortMangled)));
|
EXPECT_TRUE(RMC.FromItaniumName(ConstString(ShortMangled)));
|
||||||
RMC.ParseFullName();
|
const char *ShortDemangled = RMC.ParseFullName().data();
|
||||||
const char *ShortDemangled = RMC.GetBufferRef().data();
|
|
||||||
|
|
||||||
// Demangle the long one.
|
// Demangle the long one.
|
||||||
EXPECT_TRUE(RMC.FromItaniumName(ConstString(LongMangled)));
|
EXPECT_TRUE(RMC.FromItaniumName(ConstString(LongMangled)));
|
||||||
RMC.ParseFullName();
|
const char *LongDemangled = RMC.ParseFullName().data();
|
||||||
const char *LongDemangled = RMC.GetBufferRef().data();
|
|
||||||
|
|
||||||
// Make sure a new buffer was allocated or the default buffer was extended.
|
// Make sure a new buffer was allocated or the default buffer was extended.
|
||||||
bool AllocatedNewBuffer = (ShortDemangled != LongDemangled);
|
bool AllocatedNewBuffer = (ShortDemangled != LongDemangled);
|
||||||
|
|
Loading…
Reference in New Issue