aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API/python_api
diff options
context:
space:
mode:
authorMichael Buch <michaelbuch12@gmail.com>2022-09-22 16:17:31 +0200
committerMichael Buch <michaelbuch12@gmail.com>2022-09-23 12:27:08 +0200
commitd5d90428500870107909fb8f90023ff608cd1ec2 (patch)
tree8f277f649991401ce8eb683f29f102724d30bd6a /lldb/test/API/python_api
parent6c6b48434ed85841f147c789a96a309e1fff16ae (diff)
downloadllvm-d5d90428500870107909fb8f90023ff608cd1ec2.zip
llvm-d5d90428500870107909fb8f90023ff608cd1ec2.tar.gz
llvm-d5d90428500870107909fb8f90023ff608cd1ec2.tar.bz2
[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
Diffstat (limited to 'lldb/test/API/python_api')
-rw-r--r--lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/TestSBValueUnsignedEnumBitField.py18
-rw-r--r--lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp14
2 files changed, 32 insertions, 0 deletions
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 0000000..eb01fd6
--- /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 0000000..9859754
--- /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")
+}