[Lldb-commits] [lldb] d5d9042 - [lldb][TypeSystemClang] Deduce lldb::eEncodingUint for unsigned enum types

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Fri Sep 23 03:27:49 PDT 2022


Author: Michael Buch
Date: 2022-09-23T12:27:08+02:00
New Revision: d5d90428500870107909fb8f90023ff608cd1ec2

URL: https://github.com/llvm/llvm-project/commit/d5d90428500870107909fb8f90023ff608cd1ec2
DIFF: https://github.com/llvm/llvm-project/commit/d5d90428500870107909fb8f90023ff608cd1ec2.diff

LOG: [lldb][TypeSystemClang] Deduce lldb::eEncodingUint for unsigned enum types

The motivating issue was the following:
```
$ cat main.cpp
enum class EnumVals : uint16_t {
    VAL1 = 0
};

struct Foo {
    EnumVals b1 : 4;
};

int main() {
    // Assign value out-of-range if
    // bit-field were signed
    Foo f{.b1 = (EnumVals)8};

    return 0; // Break here
}

(lldb) script
>>> lldb.frame.FindVariable("f").GetChildMemberWithName("b1").GetValueAsUnsigned()
4294967288
```

In the above example we observe a unsigned integer wrap-around
because we sign-extended the bit-fields underlying Scalar value
before casting it to an unsigned. The sign extension occurs because
we don't mark APSInt::IsUnsigned == true correctly when extracting
the value from memory (in Value::ResolveValue). The reason why sign
extension causes the wraparound is that the value we're assigning
to the bit-field is out-of-range (if it were a signed bit-field),
which causes `Scalar::sext` to left-fill the Scalar with 1s.

This patch corrects GetEncoding to account for unsigned enum types.
With this change the Scalar would be zero-extended instead.

This is mainly a convenience fix which well-formed code wouldn't
encounter.

rdar://99785324

Differential Revision: https://reviews.llvm.org/D134493

Added: 
    lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/TestSBValueUnsignedEnumBitField.py
    lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp

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

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index e298d7fee4214..6164b978f2f24 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -5097,7 +5097,9 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
   case clang::Type::Record:
     break;
   case clang::Type::Enum:
-    return lldb::eEncodingSint;
+    return qual_type->isUnsignedIntegerOrEnumerationType()
+               ? lldb::eEncodingUint
+               : lldb::eEncodingSint;
   case clang::Type::DependentSizedArray:
   case clang::Type::DependentSizedExtVector:
   case clang::Type::UnresolvedUsing:

diff  --git a/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/TestSBValueUnsignedEnumBitField.py b/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/TestSBValueUnsignedEnumBitField.py
new file mode 100644
index 0000000000000..eb01fd6ee63a7
--- /dev/null
+++ b/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/TestSBValueUnsignedEnumBitField.py
@@ -0,0 +1,18 @@
+"""
+Test that SBValue doesn't incorrectly sign-extend
+the Scalar value of a bitfield that has an unsigned
+enum type.
+
+We test this by assigning to a bit-field a value
+that is out-of-range of it's signed counterpart.
+I.e., with a bit-field of width 4, assigning
+8 to it would be out-of-range if we treated it
+as a signed. If LLDB were to sign-extend the Scalar
+(which shouldn't happen for unsigned bit-fields)
+it would left-fill the result with 1s; we test
+for this not to happen.
+"""
+
+import lldbsuite.test.lldbinline as lldbinline
+
+lldbinline.MakeInlineTest(__file__, globals())

diff  --git a/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp b/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp
new file mode 100644
index 0000000000000..9859754d4973f
--- /dev/null
+++ b/lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp
@@ -0,0 +1,14 @@
+#include <stdint.h>
+
+enum class EnumVals : uint16_t { VAL0 = 0 };
+
+struct Foo {
+  EnumVals b : 4;
+};
+
+int main(int argc, char const *argv[], char const *envp[]) {
+  Foo f{.b = static_cast<EnumVals>(8)};
+  return 0; //% b = self.frame().FindVariable("f").GetChildMemberWithName("b")
+            //% val = b.GetValueAsUnsigned()
+            //% self.assertEqual(val, 8, "Bit-field not correctly extracted")
+}


        


More information about the lldb-commits mailing list