Skip to content

Commit 328d9f6

Browse files
committed
Reland "[lldb] Print empty enums as if they were unrecognised normal enums (#97553)"
This reverts commit 927def4. I've refactored the tests so that we're explicit about whether the enum is signed or not. Which means we use the proper types throughout.
1 parent 173514d commit 328d9f6

File tree

3 files changed

+67
-42
lines changed

3 files changed

+67
-42
lines changed

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8656,20 +8656,25 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream &s,
86568656
// every enumerator is either a one bit value or a superset of the previous
86578657
// enumerators. Also 0 doesn't make sense when the enumerators are used as
86588658
// flags.
8659-
for (auto *enumerator : enum_decl->enumerators()) {
8660-
llvm::APSInt init_val = enumerator->getInitVal();
8661-
uint64_t val =
8662-
qual_type_is_signed ? init_val.getSExtValue() : init_val.getZExtValue();
8663-
if (qual_type_is_signed)
8664-
val = llvm::SignExtend64(val, 8 * byte_size);
8665-
if (llvm::popcount(val) != 1 && (val & ~covered_bits) != 0)
8666-
can_be_bitfield = false;
8667-
covered_bits |= val;
8668-
++num_enumerators;
8669-
if (val == enum_svalue) {
8670-
// Found an exact match, that's all we need to do.
8671-
s.PutCString(enumerator->getNameAsString());
8672-
return true;
8659+
clang::EnumDecl::enumerator_range enumerators = enum_decl->enumerators();
8660+
if (enumerators.empty())
8661+
can_be_bitfield = false;
8662+
else {
8663+
for (auto *enumerator : enumerators) {
8664+
llvm::APSInt init_val = enumerator->getInitVal();
8665+
uint64_t val = qual_type_is_signed ? init_val.getSExtValue()
8666+
: init_val.getZExtValue();
8667+
if (qual_type_is_signed)
8668+
val = llvm::SignExtend64(val, 8 * byte_size);
8669+
if (llvm::popcount(val) != 1 && (val & ~covered_bits) != 0)
8670+
can_be_bitfield = false;
8671+
covered_bits |= val;
8672+
++num_enumerators;
8673+
if (val == enum_svalue) {
8674+
// Found an exact match, that's all we need to do.
8675+
s.PutCString(enumerator->getNameAsString());
8676+
return true;
8677+
}
86738678
}
86748679
}
86758680

lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ PRINTEC: use of undeclared identifier 'EC'
2222

2323
RUN: %lldb %t -b -o "target variable a e ec" | FileCheck --check-prefix=VARS %s
2424
VARS: (const (unnamed struct)) a = <incomplete type "const (unnamed struct)">
25-
VARS: (const (unnamed enum)) e = 0x1
26-
VARS: (const (unnamed enum)) ec = 0x1
25+
VARS: (const (unnamed enum)) e = 1
26+
VARS: (const (unnamed enum)) ec = 1

lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include "gtest/gtest.h"
2020

21+
#include <type_traits>
22+
2123
using namespace lldb;
2224
using namespace lldb_private;
2325

@@ -70,28 +72,12 @@ class ValueObjectMockProcessTest : public ::testing::Test {
7072
m_type_system = m_holder->GetAST();
7173
}
7274

73-
CompilerType
74-
MakeEnumType(const std::vector<std::pair<const char *, int>> enumerators) {
75-
CompilerType uint_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
76-
lldb::eEncodingUint, 32);
77-
CompilerType enum_type = m_type_system->CreateEnumerationType(
78-
"TestEnum", m_type_system->GetTranslationUnitDecl(),
79-
OptionalClangModuleID(), Declaration(), uint_type, false);
80-
81-
m_type_system->StartTagDeclarationDefinition(enum_type);
82-
Declaration decl;
83-
for (auto [name, value] : enumerators)
84-
m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, name,
85-
value, 32);
86-
m_type_system->CompleteTagDeclarationDefinition(enum_type);
87-
88-
return enum_type;
89-
}
90-
91-
void TestDumpValueObject(
92-
CompilerType enum_type,
93-
const std::vector<
94-
std::tuple<uint32_t, DumpValueObjectOptions, const char *>> &tests) {
75+
template <typename UnderlyingType>
76+
void TestDumpEnum(
77+
const std::vector<std::pair<const char *, UnderlyingType>> enumerators,
78+
const std::vector<std::tuple<UnderlyingType, DumpValueObjectOptions,
79+
const char *>> &tests) {
80+
CompilerType enum_type = MakeEnumType(enumerators);
9581
StreamString strm;
9682
ConstString var_name("test_var");
9783
ByteOrder endian = endian::InlHostByteOrder();
@@ -107,6 +93,27 @@ class ValueObjectMockProcessTest : public ::testing::Test {
10793
}
10894
}
10995

96+
template <typename UnderlyingType>
97+
CompilerType MakeEnumType(
98+
const std::vector<std::pair<const char *, UnderlyingType>> enumerators) {
99+
CompilerType int_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
100+
std::is_same<UnderlyingType, int>::value ? lldb::eEncodingSint
101+
: lldb::eEncodingUint,
102+
32);
103+
CompilerType enum_type = m_type_system->CreateEnumerationType(
104+
"TestEnum", m_type_system->GetTranslationUnitDecl(),
105+
OptionalClangModuleID(), Declaration(), int_type, false);
106+
107+
m_type_system->StartTagDeclarationDefinition(enum_type);
108+
Declaration decl;
109+
for (auto [name, value] : enumerators)
110+
m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, name,
111+
value, 32);
112+
m_type_system->CompleteTagDeclarationDefinition(enum_type);
113+
114+
return enum_type;
115+
}
116+
110117
ExecutionContext m_exe_ctx;
111118
TypeSystemClang *m_type_system;
112119

@@ -123,12 +130,25 @@ class ValueObjectMockProcessTest : public ::testing::Test {
123130
lldb::ProcessSP m_process_sp;
124131
};
125132

133+
TEST_F(ValueObjectMockProcessTest, EmptyEnum) {
134+
// All values of an empty enum should be shown as plain numbers.
135+
TestDumpEnum<unsigned>({}, {{0, {}, "(TestEnum) test_var = 0\n"},
136+
{1, {}, "(TestEnum) test_var = 1\n"},
137+
{2, {}, "(TestEnum) test_var = 2\n"}});
138+
139+
TestDumpEnum<int>({}, {{-2, {}, "(TestEnum) test_var = -2\n"},
140+
{-1, {}, "(TestEnum) test_var = -1\n"},
141+
{0, {}, "(TestEnum) test_var = 0\n"},
142+
{1, {}, "(TestEnum) test_var = 1\n"},
143+
{2, {}, "(TestEnum) test_var = 2\n"}});
144+
}
145+
126146
TEST_F(ValueObjectMockProcessTest, Enum) {
127147
// This is not a bitfield-like enum, so values are printed as decimal by
128148
// default. Also we only show the enumerator name if the value is an
129149
// exact match.
130-
TestDumpValueObject(
131-
MakeEnumType({{"test_2", 2}, {"test_3", 3}}),
150+
TestDumpEnum<unsigned>(
151+
{{"test_2", 2}, {"test_3", 3}},
132152
{{0, {}, "(TestEnum) test_var = 0\n"},
133153
{1, {}, "(TestEnum) test_var = 1\n"},
134154
{2, {}, "(TestEnum) test_var = test_2\n"},
@@ -151,8 +171,8 @@ TEST_F(ValueObjectMockProcessTest, BitFieldLikeEnum) {
151171
// set. lldb treats this as a "bitfield like enum". This means we show values
152172
// as hex, and values without exact matches are shown as a combination of
153173
// enumerators and any remaining value left over.
154-
TestDumpValueObject(
155-
MakeEnumType({{"test_2", 2}, {"test_4", 4}}),
174+
TestDumpEnum<unsigned>(
175+
{{"test_2", 2}, {"test_4", 4}},
156176
{
157177
{0, {}, "(TestEnum) test_var = 0x0\n"},
158178
{1, {}, "(TestEnum) test_var = 0x1\n"},

0 commit comments

Comments
 (0)