diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -121,6 +121,8 @@ 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 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -178,6 +178,8 @@ 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 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2720,6 +2720,7 @@ // TODO: Support float/double static members as well. if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) return; + llvm::Expected const_value_or_err = ExtractIntFromFormValue(ct, *attrs.const_value_form); if (!const_value_or_err) { @@ -2728,7 +2729,13 @@ 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.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -592,6 +592,8 @@ 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 @@ 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/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -3224,6 +3224,20 @@ 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(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 @@ 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/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -154,6 +154,12 @@ 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 --- 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 @@ # 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 --- 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 @@ 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;