Skip to content

Commit 02c1c93

Browse files
committed
[LLDB] Fix printing a static bool struct member when using "image lookup -t"
Fixes #58135 Somehow lldb was able to print the member on its own but when we try to print the whole type found by "image lookup -t" lldb would crash. This is because we'd encoded the initial value of the member as an integer. Which isn't the end of the world because bool is integral for C++. However, clang has a special AST node to handle literal bool and it expected us to use that instead. This adds a new codepath to handle static bool which uses cxxBoolLiteralExpr and we get the member printed as you'd expect. For testing I added a struct with just the bool because trying to print all of "A" crashes as well. Presumably because one of the other member's types isn't handled properly either. So for now I just added the bool case, we can merge it with A later. Reviewed By: aeubanks Differential Revision: https://reviews.llvm.org/D135169
1 parent 7b442b0 commit 02c1c93

File tree

8 files changed

+58
-1
lines changed

8 files changed

+58
-1
lines changed

lldb/include/lldb/Symbol/CompilerType.h

+2
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ class CompilerType {
121121

122122
bool IsIntegerOrEnumerationType(bool &is_signed) const;
123123

124+
bool IsBooleanType() const;
125+
124126
bool IsPolymorphicClass() const;
125127

126128
/// \param target_type Can pass nullptr.

lldb/include/lldb/Symbol/TypeSystem.h

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class TypeSystem : public PluginInterface {
178178
return false;
179179
}
180180

181+
virtual bool IsBooleanType(lldb::opaque_compiler_type_t type) = 0;
182+
181183
virtual bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) = 0;
182184

183185
virtual bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,7 @@ void DWARFASTParserClang::ParseSingleMember(
27202720
// TODO: Support float/double static members as well.
27212721
if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused))
27222722
return;
2723+
27232724
llvm::Expected<llvm::APInt> const_value_or_err =
27242725
ExtractIntFromFormValue(ct, *attrs.const_value_form);
27252726
if (!const_value_or_err) {
@@ -2728,7 +2729,13 @@ void DWARFASTParserClang::ParseSingleMember(
27282729
v->getQualifiedNameAsString());
27292730
return;
27302731
}
2731-
TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err);
2732+
2733+
if (ct.IsBooleanType())
2734+
TypeSystemClang::SetBoolInitializerForVariable(
2735+
v, !const_value_or_err->isZero());
2736+
else
2737+
TypeSystemClang::SetIntegerInitializerForVariable(v,
2738+
*const_value_or_err);
27322739
}
27332740
return;
27342741
}

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

+26
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,20 @@ bool TypeSystemClang::IsIntegerType(lldb::opaque_compiler_type_t type,
32243224
return false;
32253225
}
32263226

3227+
bool TypeSystemClang::IsBooleanType(lldb::opaque_compiler_type_t type) {
3228+
if (!type)
3229+
return false;
3230+
3231+
clang::QualType qual_type(GetCanonicalQualType(type));
3232+
const clang::BuiltinType *builtin_type =
3233+
llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
3234+
3235+
if (!builtin_type)
3236+
return false;
3237+
3238+
return builtin_type->isBooleanType();
3239+
}
3240+
32273241
bool TypeSystemClang::IsEnumerationType(lldb::opaque_compiler_type_t type,
32283242
bool &is_signed) {
32293243
if (type) {
@@ -7574,6 +7588,18 @@ clang::VarDecl *TypeSystemClang::AddVariableToRecordType(
75747588
return var_decl;
75757589
}
75767590

7591+
void TypeSystemClang::SetBoolInitializerForVariable(VarDecl *var, bool value) {
7592+
assert(!var->hasInit() && "variable already initialized");
7593+
7594+
QualType qt = var->getType();
7595+
assert(qt->isSpecificBuiltinType(BuiltinType::Bool) &&
7596+
"only boolean supported");
7597+
7598+
clang::ASTContext &ast = var->getASTContext();
7599+
var->setInit(CXXBoolLiteralExpr::Create(ast, value, qt.getUnqualifiedType(),
7600+
SourceLocation()));
7601+
}
7602+
75777603
void TypeSystemClang::SetIntegerInitializerForVariable(
75787604
VarDecl *var, const llvm::APInt &init_value) {
75797605
assert(!var->hasInit() && "variable already initialized");

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

+4
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,8 @@ class TypeSystemClang : public TypeSystem {
592592
bool IsEnumerationType(lldb::opaque_compiler_type_t type,
593593
bool &is_signed) override;
594594

595+
bool IsBooleanType(lldb::opaque_compiler_type_t type) override;
596+
595597
bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) override;
596598

597599
static bool IsObjCClassType(const CompilerType &type);
@@ -860,6 +862,8 @@ class TypeSystemClang : public TypeSystem {
860862
static void SetIntegerInitializerForVariable(clang::VarDecl *var,
861863
const llvm::APInt &init_value);
862864

865+
static void SetBoolInitializerForVariable(clang::VarDecl *var, bool value);
866+
863867
/// Initializes a variable with a floating point value.
864868
/// \param var The variable to initialize. Must not already have an
865869
/// initializer and must have a floating point type.

lldb/source/Symbol/CompilerType.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ bool CompilerType::IsIntegerOrEnumerationType(bool &is_signed) const {
154154
return IsIntegerType(is_signed) || IsEnumerationType(is_signed);
155155
}
156156

157+
bool CompilerType::IsBooleanType() const {
158+
if (IsValid())
159+
return m_type_system->IsBooleanType(m_type);
160+
return false;
161+
}
162+
157163
bool CompilerType::IsPointerType(CompilerType *pointee_type) const {
158164
if (IsValid()) {
159165
return m_type_system->IsPointerType(m_type, pointee_type);

lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ def test(self):
3232
# Test a bool member.
3333
self.expect_expr("A::bool_val", result_value="true")
3434

35+
# Test a bool member when printing the struct it is a member of.
36+
# TODO: replace this with printing struct A, once doing so doesn't crash lldb.
37+
self.expect("image lookup -t StaticBoolStruct",
38+
substrs=["static const bool value = false;"])
39+
3540
# Test that minimum and maximum values for each data type are right.
3641
self.expect_expr("A::char_max == char_max", result_value="true")
3742
self.expect_expr("A::uchar_max == uchar_max", result_value="true")

lldb/test/API/lang/cpp/const_static_integral_member/main.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,13 @@ struct ClassWithEnumAlias {
7979
ScopedEnum::scoped_enum_case1;
8080
};
8181

82+
struct StaticBoolStruct {
83+
static const bool value = false;
84+
};
85+
8286
int main() {
8387
A a;
88+
StaticBoolStruct sbs;
8489

8590
auto char_max = A::char_max;
8691
auto uchar_max = A::uchar_max;

0 commit comments

Comments
 (0)