diff options
| author | Michael Buch <michaelbuch12@gmail.com> | 2022-09-22 16:17:31 +0200 |
|---|---|---|
| committer | Michael Buch <michaelbuch12@gmail.com> | 2022-09-23 12:27:08 +0200 |
| commit | d5d90428500870107909fb8f90023ff608cd1ec2 (patch) | |
| tree | 8f277f649991401ce8eb683f29f102724d30bd6a /lldb/test/API/python_api | |
| parent | 6c6b48434ed85841f147c789a96a309e1fff16ae (diff) | |
| download | llvm-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.py | 18 | ||||
| -rw-r--r-- | lldb/test/API/python_api/sbvalue_unsigned_enum_bitfield_value/main.cpp | 14 |
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") +} |
