This revision was automatically updated to reflect the committed changes.
Closed by commit rG3c51ea3619e4: [DataFormatter] Fix variant npos with 
`_LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZAT… (authored by rupprecht).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138892/new/

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,34 @@
     std::variant<int, double, char> v3;
     std::variant<std::variant<int,double,char>> v_v1 ;
     std::variant<int, double, char> v_no_value;
+    // The next variant has 300 types, meaning the type index does not fit in
+    // a byte and must be `unsigned short` instead of `unsigned char` when
+    // using the unstable libc++ ABI. With stable libc++ ABI, the type index
+    // is always just `unsigned int`.
+    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 +82,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<uint8_t>(-1);
+  case 2:
+    return static_cast<uint16_t>(-1);
+  case 4:
+    return static_cast<uint32_t>(-1);
+  }
+  lldbassert(false && "Unknown index type size");
+  return static_cast<uint32_t>(-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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to