Author: David Spickett Date: 2022-10-07T09:02:59Z New Revision: 02c1c939486f247dc80866477eaab193c634d1e2
URL: https://github.com/llvm/llvm-project/commit/02c1c939486f247dc80866477eaab193c634d1e2 DIFF: https://github.com/llvm/llvm-project/commit/02c1c939486f247dc80866477eaab193c634d1e2.diff LOG: [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 Added: Modified: lldb/include/lldb/Symbol/CompilerType.h lldb/include/lldb/Symbol/TypeSystem.h lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h lldb/source/Symbol/CompilerType.cpp lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py lldb/test/API/lang/cpp/const_static_integral_member/main.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index aefd19d0a8595..f0443fceb28d0 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -121,6 +121,8 @@ class CompilerType { bool IsIntegerOrEnumerationType(bool &is_signed) const; + bool IsBooleanType() const; + bool IsPolymorphicClass() const; /// \param target_type Can pass nullptr. diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 57bdfa5b626ab..63f9495ad916d 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -178,6 +178,8 @@ class TypeSystem : public PluginInterface { return false; } + virtual bool IsBooleanType(lldb::opaque_compiler_type_t type) = 0; + virtual bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) = 0; virtual bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 25f2a37cbab5d..988dc0236652a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2720,6 +2720,7 @@ void DWARFASTParserClang::ParseSingleMember( // TODO: Support float/double static members as well. if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) return; + llvm::Expected<llvm::APInt> const_value_or_err = ExtractIntFromFormValue(ct, *attrs.const_value_form); if (!const_value_or_err) { @@ -2728,7 +2729,13 @@ void DWARFASTParserClang::ParseSingleMember( v->getQualifiedNameAsString()); return; } - TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err); + + if (ct.IsBooleanType()) + TypeSystemClang::SetBoolInitializerForVariable( + v, !const_value_or_err->isZero()); + else + TypeSystemClang::SetIntegerInitializerForVariable(v, + *const_value_or_err); } return; } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 4adf653b6c508..b2779d6dd10aa 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -3224,6 +3224,20 @@ bool TypeSystemClang::IsIntegerType(lldb::opaque_compiler_type_t type, return false; } +bool TypeSystemClang::IsBooleanType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::BuiltinType *builtin_type = + llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); + + if (!builtin_type) + return false; + + return builtin_type->isBooleanType(); +} + bool TypeSystemClang::IsEnumerationType(lldb::opaque_compiler_type_t type, bool &is_signed) { if (type) { @@ -7574,6 +7588,18 @@ clang::VarDecl *TypeSystemClang::AddVariableToRecordType( return var_decl; } +void TypeSystemClang::SetBoolInitializerForVariable(VarDecl *var, bool value) { + assert(!var->hasInit() && "variable already initialized"); + + QualType qt = var->getType(); + assert(qt->isSpecificBuiltinType(BuiltinType::Bool) && + "only boolean supported"); + + clang::ASTContext &ast = var->getASTContext(); + var->setInit(CXXBoolLiteralExpr::Create(ast, value, qt.getUnqualifiedType(), + SourceLocation())); +} + void TypeSystemClang::SetIntegerInitializerForVariable( VarDecl *var, const llvm::APInt &init_value) { assert(!var->hasInit() && "variable already initialized"); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 7c045fdf088c5..365fa720e0da5 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -592,6 +592,8 @@ class TypeSystemClang : public TypeSystem { bool IsEnumerationType(lldb::opaque_compiler_type_t type, bool &is_signed) override; + bool IsBooleanType(lldb::opaque_compiler_type_t type) override; + bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) override; static bool IsObjCClassType(const CompilerType &type); @@ -860,6 +862,8 @@ class TypeSystemClang : public TypeSystem { static void SetIntegerInitializerForVariable(clang::VarDecl *var, const llvm::APInt &init_value); + static void SetBoolInitializerForVariable(clang::VarDecl *var, bool value); + /// Initializes a variable with a floating point value. /// \param var The variable to initialize. Must not already have an /// initializer and must have a floating point type. diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index bef456583687c..3a191644cc0d0 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -154,6 +154,12 @@ bool CompilerType::IsIntegerOrEnumerationType(bool &is_signed) const { return IsIntegerType(is_signed) || IsEnumerationType(is_signed); } +bool CompilerType::IsBooleanType() const { + if (IsValid()) + return m_type_system->IsBooleanType(m_type); + return false; +} + bool CompilerType::IsPointerType(CompilerType *pointee_type) const { if (IsValid()) { return m_type_system->IsPointerType(m_type, pointee_type); diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py index 4f51d22a86850..0482007d48147 100644 --- a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py +++ b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py @@ -32,6 +32,11 @@ def test(self): # Test a bool member. self.expect_expr("A::bool_val", result_value="true") + # Test a bool member when printing the struct it is a member of. + # TODO: replace this with printing struct A, once doing so doesn't crash lldb. + self.expect("image lookup -t StaticBoolStruct", + substrs=["static const bool value = false;"]) + # Test that minimum and maximum values for each data type are right. self.expect_expr("A::char_max == char_max", result_value="true") self.expect_expr("A::uchar_max == uchar_max", result_value="true") diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp index 977e12295760a..d078076b99dc8 100644 --- a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp +++ b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp @@ -79,8 +79,13 @@ struct ClassWithEnumAlias { ScopedEnum::scoped_enum_case1; }; +struct StaticBoolStruct { + static const bool value = false; +}; + int main() { A a; + StaticBoolStruct sbs; auto char_max = A::char_max; auto uchar_max = A::uchar_max; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits