llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Nerixyz (Nerixyz) <details> <summary>Changes</summary> Static constants with bit widths less than 16 (e.g. char/unsigned char) in classes were not available. These constants are still encoded with 16 bits ([here](https://github.com/llvm/llvm-project/blob/dd145eb8997878143f648a7601741f6409330963/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp#L341-L343)) even though they only need less bits. When we tried to create an initializer for them, we'd check if the bit width (=16) was small enough to fit into the target (<16). This would fail. This was a problem in the following code: ```cpp struct Foo { // width(unsigned char) = 8, but 255 was encoded and read as 16 bit static constexpr unsigned char u8_max = 255; }; ``` This PR fixes the issue by using `APSInt::getActiveBits` for unsigned types and `APSInt::getSignificantBits` for signed types. They get the number of bits required to encode the value. For example a constant 64 would need 7 bits in unsigned and 8 bits in signed types. --- Full diff: https://github.com/llvm/llvm-project/pull/196104.diff 4 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp (+13-5) - (modified) lldb/test/Shell/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit (+6-1) - (modified) lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp (+20) - (added) lldb/test/Shell/SymbolFile/NativePDB/static-class-constants.cpp (+109) ``````````diff diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 84813ad677d1c..9840b976d2713 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -179,10 +179,18 @@ Error UdtRecordCompleter::visitKnownMember( clang::QualType qual_type = decl->getType(); unsigned type_width = decl->getASTContext().getIntWidth(qual_type); - unsigned constant_width = constant.Value.getBitWidth(); + + // Get the minimum bit width to encode this constant value. + // The bit width of the APSInt might be larger than the bits required to + // encode the value. + unsigned min_constant_width = 0; + if (qual_type->isUnsignedIntegerOrEnumerationType()) + min_constant_width = constant.Value.getActiveBits(); + else + min_constant_width = constant.Value.getSignificantBits(); if (qual_type->isIntegralOrEnumerationType()) { - if (type_width >= constant_width) { + if (type_width >= min_constant_width) { TypeSystemClang::SetIntegerInitializerForVariable( decl, constant.Value.extOrTrunc(type_width)); } else { @@ -191,7 +199,7 @@ Error UdtRecordCompleter::visitKnownMember( "which resolves to a wider constant value ({4} bits). " "Ignoring constant.", m_derived_ct.GetTypeName(), static_data_member.Name, - member_ct.GetTypeName(), type_width, constant_width); + member_ct.GetTypeName(), type_width, min_constant_width); } } else { lldb::BasicType basic_type_enum = member_ct.GetBasicTypeEnumeration(); @@ -199,7 +207,7 @@ Error UdtRecordCompleter::visitKnownMember( case lldb::eBasicTypeFloat: case lldb::eBasicTypeDouble: case lldb::eBasicTypeLongDouble: - if (type_width == constant_width) { + if (type_width == min_constant_width) { TypeSystemClang::SetFloatingInitializerForVariable( decl, basic_type_enum == lldb::eBasicTypeFloat ? llvm::APFloat(constant.Value.bitsToFloat()) @@ -212,7 +220,7 @@ Error UdtRecordCompleter::visitKnownMember( "which resolves to a constant value of mismatched width " "({4} bits). Ignoring constant.", m_derived_ct.GetTypeName(), static_data_member.Name, - member_ct.GetTypeName(), type_width, constant_width); + member_ct.GetTypeName(), type_width, min_constant_width); } break; default: diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit index 4af8b658742b3..8af31b80eb67f 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit @@ -62,10 +62,15 @@ target variable CD target variable ConstexprBFalse target variable ConstexprBTrue +target variable ConstexprCMin +target variable ConstexprCMax target variable ConstexprCA target variable ConstexprCZ +target variable ConstexprSCMin +target variable ConstexprSCMax target variable ConstexprSCa target variable ConstexprSCz +target variable ConstexprUCMax target variable ConstexprUC24 target variable ConstexprUC42 target variable ConstexprC16_24 @@ -219,4 +224,4 @@ target variable CRWCP target modules dump ast -quit \ No newline at end of file +quit diff --git a/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp b/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp index 299dd0b02671d..999d09bae9c6c 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp @@ -199,18 +199,33 @@ constexpr bool ConstexprBFalse = false; constexpr bool ConstexprBTrue = true; // CHECK-NEXT: (lldb) target variable ConstexprBTrue // CHECK-NEXT: (const bool) ConstexprBTrue = true +constexpr char ConstexprCMin = -128; +// CHECK-NEXT: (lldb) target variable ConstexprCMin +// CHECK-NEXT: (const char) ConstexprCMin = '\x80' +constexpr char ConstexprCMax = 127; +// CHECK-NEXT: (lldb) target variable ConstexprCMax +// CHECK-NEXT: (const char) ConstexprCMax = '\x7f' constexpr char ConstexprCA = 'A'; // CHECK-NEXT: (lldb) target variable ConstexprCA // CHECK-NEXT: (const char) ConstexprCA = 'A' constexpr char ConstexprCZ = 'Z'; // CHECK-NEXT: (lldb) target variable ConstexprCZ // CHECK-NEXT: (const char) ConstexprCZ = 'Z' +constexpr signed char ConstexprSCMin = -128; +// CHECK-NEXT: (lldb) target variable ConstexprSCMin +// CHECK-NEXT: (const signed char) ConstexprSCMin = '\x80' +constexpr signed char ConstexprSCMax = 127; +// CHECK-NEXT: (lldb) target variable ConstexprSCMax +// CHECK-NEXT: (const signed char) ConstexprSCMax = '\x7f' constexpr signed char ConstexprSCa = 'a'; // CHECK-NEXT: (lldb) target variable ConstexprSCa // CHECK-NEXT: (const signed char) ConstexprSCa = 'a' constexpr signed char ConstexprSCz = 'z'; // CHECK-NEXT: (lldb) target variable ConstexprSCz // CHECK-NEXT: (const signed char) ConstexprSCz = 'z' +constexpr unsigned char ConstexprUCMax = 255; +// CHECK-NEXT: (lldb) target variable ConstexprUCMax +// CHECK-NEXT: (const unsigned char) ConstexprUCMax = '\xff' constexpr unsigned char ConstexprUC24 = 24; // CHECK-NEXT: (lldb) target variable ConstexprUC24 // CHECK-NEXT: (const unsigned char) ConstexprUC24 = '\x18' @@ -725,10 +740,15 @@ const wchar_t &CRWCP = WCP; // CHECK-NEXT: |-VarDecl {{.*}} CD 'const double' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprBFalse 'const bool' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprBTrue 'const bool' +// CHECK-NEXT: |-VarDecl {{.*}} ConstexprCMin 'const char' +// CHECK-NEXT: |-VarDecl {{.*}} ConstexprCMax 'const char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprCA 'const char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprCZ 'const char' +// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCMin 'const signed char' +// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCMax 'const signed char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCa 'const signed char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCz 'const signed char' +// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUCMax 'const unsigned char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprUC24 'const unsigned char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprUC42 'const unsigned char' // CHECK-NEXT: |-VarDecl {{.*}} ConstexprC16_24 'const char16_t' diff --git a/lldb/test/Shell/SymbolFile/NativePDB/static-class-constants.cpp b/lldb/test/Shell/SymbolFile/NativePDB/static-class-constants.cpp new file mode 100644 index 0000000000000..e65618f9774ba --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/static-class-constants.cpp @@ -0,0 +1,109 @@ +// REQUIRES: lld, x86 + +// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -GS- -c /Fo%t.obj -- %s +// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb +// RUN: %lldb -f %t.exe -o "type lookup Foo" | FileCheck %s + +enum class U8Enum : unsigned char { + Max = 255, +}; +enum class I8Enum : char { + Min = 127, + Max = -128, +}; +enum class U16Enum : unsigned short { + Max = 65535, +}; +enum class I16Enum : short { + Min = -32768, + Max = 32767, +}; +enum class U32Enum : unsigned { + Max = 4294967295U, +}; +enum class I32Enum : int { + Min = -2147483648, + Max = 2147483647, +}; +enum class U64Enum : unsigned long long { + Max = 18446744073709551615ULL, +}; +enum class I64Enum : long long { + Min = -9223372036854775807LL - 1, + Max = 9223372036854775807LL, +}; + +// CHECK: struct Foo { +struct Foo { + // CHECK-NEXT: static const U8Enum u8_enum_max = 255Ui8; + static constexpr U8Enum u8_enum_max = U8Enum::Max; + + // CHECK-NEXT: static const I8Enum i8_enum_min = 127i8; + static constexpr I8Enum i8_enum_min = I8Enum::Min; + // CHECK-NEXT: static const I8Enum i8_enum_max = -128i8; + static constexpr I8Enum i8_enum_max = I8Enum::Max; + + // CHECK-NEXT: static const U16Enum u16_enum_max = 65535Ui16; + static constexpr U16Enum u16_enum_max = U16Enum::Max; + + // CHECK-NEXT: static const I16Enum i16_enum_min = -32768i16; + static constexpr I16Enum i16_enum_min = I16Enum::Min; + // CHECK-NEXT: static const I16Enum i16_enum_max = 32767i16; + static constexpr I16Enum i16_enum_max = I16Enum::Max; + + // CHECK-NEXT: static const U32Enum u32_enum_max = 4294967295U; + static constexpr U32Enum u32_enum_max = U32Enum::Max; + + // CHECK-NEXT: static const I32Enum i32_enum_min = -2147483648; + static constexpr I32Enum i32_enum_min = I32Enum::Min; + // CHECK-NEXT: static const I32Enum i32_enum_max = 2147483647; + static constexpr I32Enum i32_enum_max = I32Enum::Max; + + // CHECK-NEXT: static const U64Enum u64_enum_max = 18446744073709551615ULL; + static constexpr U64Enum u64_enum_max = U64Enum::Max; + + // CHECK-NEXT: static const I64Enum i64_enum_min = -9223372036854775808LL; + static constexpr I64Enum i64_enum_min = I64Enum::Min; + // CHECK-NEXT: static const I64Enum i64_enum_max = 9223372036854775807LL; + static constexpr I64Enum i64_enum_max = I64Enum::Max; + + // CHECK-NEXT: static const unsigned char u8_max = 255Ui8; + static constexpr unsigned char u8_max = 255; + + // CHECK-NEXT: static const char i8_min = -128i8; + static constexpr char i8_min = -128; + // CHECK-NEXT: static const char i8_max = 127i8; + static constexpr char i8_max = 127; + + // CHECK-NEXT: static const unsigned short u16_max = 65535Ui16; + static constexpr unsigned short u16_max = 65535; + + // CHECK-NEXT: static const short i16_min = -32768i16; + static constexpr short i16_min = -32767 - 1; + // CHECK-NEXT: static const short i16_max = 32767i16; + static constexpr short i16_max = 32767; + + // CHECK-NEXT: static const unsigned int u32_max = 4294967295U; + static constexpr unsigned u32_max = 4294967295; + + // CHECK-NEXT: static const int i32_min = -2147483648; + static constexpr int i32_min = -2147483648; + // CHECK-NEXT: static const int i32_max = 2147483647; + static constexpr int i32_max = 2147483647; + + // CHECK-NEXT: static const unsigned long long u64_max = 18446744073709551615ULL; + static constexpr unsigned long long u64_max = 18446744073709551615ULL; + + // CHECK-NEXT: static const long long i64_min = -9223372036854775808LL; + static constexpr long long i64_min = -9223372036854775807LL - 1; + // CHECK-NEXT: static const long long i64_max = 9223372036854775807LL; + static constexpr long long i64_max = 9223372036854775807LL; + + // CHECK-NEXT: int i; + int i; +}; + +int main() { + Foo f{42}; + return f.i; +} `````````` </details> https://github.com/llvm/llvm-project/pull/196104 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
