[Lldb-commits] [lldb] 02c1c93 - [LLDB] Fix printing a static bool struct member when using "image lookup -t"

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 7 02:03:09 PDT 2022


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;


        


More information about the lldb-commits mailing list