llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericInitializerList.cpp
Jonas Devlieghere f866ef202c
[lldb] Bring more diagnostics in compliance with our coding standards (#190410)
The LLVM Coding Standards [1] specify that:

> [T]o match error message styles commonly produced by other tools,
> start the first sentence with a lowercase letter, and finish the last
> sentence without a period, if it would end in one otherwise.

Historically, that hasn't been something we've enforced in LLDB, but in
the past year or so I've started to pay more attention to this in code
reviews. This PR brings more error messages in compliance, further
increasing consistency.

I also adopted `createStringErrorV` where it improved the code as a
drive-by for lines I was already touching.

[1] https://llvm.org/docs/CodingStandards.html#error-and-warning-messages

Assisted-by: Claude Code
2026-04-05 10:41:47 -07:00

145 lines
4.6 KiB
C++

//===-- GenericInitializerList.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/ValueObject/ValueObject.h"
#include "llvm/Support/ErrorExtras.h"
#include <cstddef>
#include <optional>
#include <type_traits>
using namespace lldb;
using namespace lldb_private;
namespace generic_check {
template <class T>
using size_func = decltype(T::GetSizeMember(std::declval<ValueObject &>()));
template <class T>
using start_func = decltype(T::GetStartMember(std::declval<ValueObject &>()));
namespace {
template <typename...> struct check_func : std::true_type {};
} // namespace
template <typename T>
using has_functions = check_func<size_func<T>, start_func<T>>;
} // namespace generic_check
struct LibCxx {
static ValueObjectSP GetStartMember(ValueObject &backend) {
return backend.GetChildMemberWithName("__begin_");
}
static ValueObjectSP GetSizeMember(ValueObject &backend) {
return backend.GetChildMemberWithName("__size_");
}
};
struct LibStdcpp {
static ValueObjectSP GetStartMember(ValueObject &backend) {
return backend.GetChildMemberWithName("_M_array");
}
static ValueObjectSP GetSizeMember(ValueObject &backend) {
return backend.GetChildMemberWithName("_M_len");
}
};
namespace lldb_private::formatters {
template <class StandardImpl>
class GenericInitializerListSyntheticFrontEnd
: public SyntheticChildrenFrontEnd {
public:
static_assert(generic_check::has_functions<StandardImpl>::value,
"Missing Required Functions.");
GenericInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
if (valobj_sp)
Update();
}
~GenericInitializerListSyntheticFrontEnd() override {
// this needs to stay around because it's a child object who will follow its
// parent's life cycle
// delete m_start;
}
llvm::Expected<uint32_t> CalculateNumChildren() override {
m_num_elements = 0;
const ValueObjectSP size_sp(StandardImpl::GetSizeMember(m_backend));
if (size_sp)
m_num_elements = size_sp->GetValueAsUnsigned(0);
return m_num_elements;
}
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
if (!m_start)
return {};
uint64_t offset = static_cast<uint64_t>(idx) * m_element_size;
offset = offset + m_start->GetValueAsUnsigned(0);
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
return CreateValueObjectFromAddress(name.GetString(), offset,
m_backend.GetExecutionContextRef(),
m_element_type);
}
lldb::ChildCacheState Update() override {
m_start = nullptr;
m_num_elements = 0;
m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
if (!m_element_type.IsValid())
return lldb::ChildCacheState::eRefetch;
llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);
if (!size_or_err)
LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),
"{0}");
else {
m_element_size = *size_or_err;
// Store raw pointers or end up with a circular dependency.
m_start = StandardImpl::GetStartMember(m_backend).get();
}
return lldb::ChildCacheState::eRefetch;
}
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
if (!m_start) {
return llvm::createStringErrorV("type has no child named '{0}'", name);
}
auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
if (!optional_idx) {
return llvm::createStringErrorV("type has no child named '{0}'", name);
}
return *optional_idx;
}
private:
ValueObject *m_start = nullptr;
CompilerType m_element_type;
uint32_t m_element_size = 0;
size_t m_num_elements = 0;
};
SyntheticChildrenFrontEnd *GenericInitializerListSyntheticFrontEndCreator(
CXXSyntheticChildren * /*unused*/, lldb::ValueObjectSP valobj_sp) {
if (!valobj_sp)
return nullptr;
if (LibCxx::GetStartMember(*valobj_sp) != nullptr)
return new GenericInitializerListSyntheticFrontEnd<LibCxx>(valobj_sp);
return new GenericInitializerListSyntheticFrontEnd<LibStdcpp>(valobj_sp);
}
} // namespace lldb_private::formatters