rupprecht created this revision.
rupprecht added reviewers: labath, Michael137, kastiglione.
Herald added a subscriber: arphaman.
Herald added a project: All.
rupprecht requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
This data formatter should print "No Value" if a variant is unset. It does so
by checking if `__index` has a value of `-1`, however it does so by
interpreting it as a signed int.
By default, `__index` has type `unsigned int`. When
`_LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION` is enabled, the type of `__index`
is either `unsigned char`, `unsigned short`, or `unsigned int`, depending on
how many fields there are -- as small as possible. For example, when
`std::variant` has only a few types, the index type is `unsigned char`, and the
npos value will be interpreted by LLDB as `255` when it should be `-1`.
This change does not special case the variant optimization; it just reads the
type instead of assuming it's `unsigned int`.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D138892
Files:
lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
===================================================================
--- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
@@ -29,6 +29,30 @@
std::variant<int, double, char> v3;
std::variant<std::variant<int,double,char>> v_v1 ;
std::variant<int, double, char> v_no_value;
+ std::variant<
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int>
+ v_300_types_no_value;
v1 = 12; // v contains int
v_v1 = v1 ;
@@ -54,6 +78,13 @@
} catch( ... ) {}
printf( "%zu\n", v_no_value.index() ) ;
+
+ try {
+ v_300_types_no_value.emplace<0>(S());
+ } catch (...) {
+ }
+
+ printf("%zu\n", v_300_types_no_value.index());
#endif
return 0; // break here
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
===================================================================
--- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
@@ -76,3 +76,6 @@
self.expect("frame variable v_no_value",
substrs=['v_no_value = No Value'])
+
+ self.expect("frame variable v_300_types_no_value",
+ substrs=['v_300_types_no_value = No Value'])
Index: lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
@@ -9,6 +9,8 @@
#include "LibCxxVariant.h"
#include "LibCxx.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/ScopeExit.h"
@@ -66,6 +68,19 @@
// 3) NPos, its value is variant_npos which means the variant has no value
enum class LibcxxVariantIndexValidity { Valid, Invalid, NPos };
+uint64_t VariantNposValue(uint64_t index_byte_size) {
+ switch (index_byte_size) {
+ case 1:
+ return static_cast<unsigned char>(-1);
+ case 2:
+ return static_cast<unsigned short>(-1);
+ case 4:
+ return static_cast<unsigned int>(-1);
+ }
+ lldbassert(false && "Unknown index type size");
+ return static_cast<unsigned int>(-1); // Fallback to stable ABI type.
+}
+
LibcxxVariantIndexValidity
LibcxxVariantGetIndexValidity(ValueObjectSP &impl_sp) {
ValueObjectSP index_sp(
@@ -74,9 +89,23 @@
if (!index_sp)
return LibcxxVariantIndexValidity::Invalid;
- int64_t index_value = index_sp->GetValueAsSigned(0);
+ // In the stable ABI, the type of __index is just int.
+ // In the unstable ABI, where _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION is
+ // enabled, the type can either be unsigned char/short/int depending on
+ // how many variant types there are.
+ // We only need to do this here when comparing against npos, because npos is
+ // just `-1`, but that translates to different unsigned values depending on
+ // the byte size.
+ CompilerType index_type = index_sp->GetCompilerType();
+
+ llvm::Optional<uint64_t> index_type_bytes = index_type.GetByteSize(nullptr);
+ if (!index_type_bytes)
+ return LibcxxVariantIndexValidity::Invalid;
+
+ uint64_t npos_value = VariantNposValue(*index_type_bytes);
+ uint64_t index_value = index_sp->GetValueAsUnsigned(0);
- if (index_value == -1)
+ if (index_value == npos_value)
return LibcxxVariantIndexValidity::NPos;
return LibcxxVariantIndexValidity::Valid;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits