Path: blob/main/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp
39587 views
//===-- RichManglingContext.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/RichManglingContext.h"9#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"10#include "lldb/Utility/LLDBLog.h"1112#include "llvm/ADT/StringRef.h"1314using namespace lldb;15using namespace lldb_private;1617// RichManglingContext18RichManglingContext::~RichManglingContext() {19std::free(m_ipd_buf);20ResetCxxMethodParser();21}2223void RichManglingContext::ResetCxxMethodParser() {24// If we want to support parsers for other languages some day, we need a25// switch here to delete the correct parser type.26if (m_cxx_method_parser.has_value()) {27assert(m_provider == PluginCxxLanguage);28delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);29m_cxx_method_parser.reset();30}31}3233void RichManglingContext::ResetProvider(InfoProvider new_provider) {34ResetCxxMethodParser();3536assert(new_provider != None && "Only reset to a valid provider");37m_provider = new_provider;38}3940bool RichManglingContext::FromItaniumName(ConstString mangled) {41bool err = m_ipd.partialDemangle(mangled.GetCString());42if (!err) {43ResetProvider(ItaniumPartialDemangler);44}4546if (Log *log = GetLog(LLDBLog::Demangle)) {47if (!err) {48ParseFullName();49LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);50} else {51LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",52mangled);53}54}5556return !err; // true == success57}5859bool RichManglingContext::FromCxxMethodName(ConstString demangled) {60ResetProvider(PluginCxxLanguage);61m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);62return true;63}6465bool RichManglingContext::IsCtorOrDtor() const {66assert(m_provider != None && "Initialize a provider first");67switch (m_provider) {68case ItaniumPartialDemangler:69return m_ipd.isCtorOrDtor();70case PluginCxxLanguage: {71// We can only check for destructors here.72auto base_name =73get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();74return base_name.starts_with("~");75}76case None:77return false;78}79llvm_unreachable("Fully covered switch above!");80}8182llvm::StringRef RichManglingContext::processIPDStrResult(char *ipd_res,83size_t res_size) {84// Error case: Clear the buffer.85if (LLVM_UNLIKELY(ipd_res == nullptr)) {86assert(res_size == m_ipd_buf_size &&87"Failed IPD queries keep the original size in the N parameter");8889m_ipd_buf[0] = '\0';90return llvm::StringRef(m_ipd_buf, 0);91}9293// IPD's res_size includes null terminator.94assert(ipd_res[res_size - 1] == '\0' &&95"IPD returns null-terminated strings and we rely on that");9697// Update buffer/size on realloc.98if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) {99m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer.100m_ipd_buf_size = res_size; // May actually be bigger, but we can't know.101102if (Log *log = GetLog(LLDBLog::Demangle))103LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",104m_ipd_buf_size);105}106107// 99% case: Just remember the string length.108return llvm::StringRef(m_ipd_buf, res_size - 1);109}110111llvm::StringRef RichManglingContext::ParseFunctionBaseName() {112assert(m_provider != None && "Initialize a provider first");113switch (m_provider) {114case ItaniumPartialDemangler: {115auto n = m_ipd_buf_size;116auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);117return processIPDStrResult(buf, n);118}119case PluginCxxLanguage:120return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)121->GetBasename();122case None:123return {};124}125llvm_unreachable("Fully covered switch above!");126}127128llvm::StringRef RichManglingContext::ParseFunctionDeclContextName() {129assert(m_provider != None && "Initialize a provider first");130switch (m_provider) {131case ItaniumPartialDemangler: {132auto n = m_ipd_buf_size;133auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);134return processIPDStrResult(buf, n);135}136case PluginCxxLanguage:137return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)138->GetContext();139case None:140return {};141}142llvm_unreachable("Fully covered switch above!");143}144145llvm::StringRef RichManglingContext::ParseFullName() {146assert(m_provider != None && "Initialize a provider first");147switch (m_provider) {148case ItaniumPartialDemangler: {149auto n = m_ipd_buf_size;150auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);151return processIPDStrResult(buf, n);152}153case PluginCxxLanguage:154return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)155->GetFullName()156.GetStringRef();157case None:158return {};159}160llvm_unreachable("Fully covered switch above!");161}162163164