Skip to content

Classes that use [[no_unique_address]] may have different layout depending on compiler used #6253

@JMazurkiewicz

Description

@JMazurkiewicz

As in title. Repro:

#include <mdspan>
#include <ranges>

using namespace std;

class DummyAccessor {
public:
  using element_type = int;
  using reference = int;
  using offset_policy = DummyAccessor;
  struct data_handle_type {};

  reference access(data_handle_type, size_t);
  data_handle_type offset(data_handle_type, size_t);
};

class DummyIterator {
public:
  using value_type = int;
  using difference_type = ptrdiff_t;

  DummyIterator() = default;
  DummyIterator &operator++();
  DummyIterator operator++(int);
  value_type operator*() const;
  bool operator==(const DummyIterator &) const;
};

using MDS = mdspan<int, dextents<int, 1>, layout_left, DummyAccessor>;
using View = decltype(declval<ranges::subrange<DummyIterator>>() |
                      views::enumerate | views::chunk(2));

static_assert(sizeof(MDS) == sizeof(int)); // single dynamic extent
static_assert(sizeof(ranges::iterator_t<View>) == 3 * sizeof(ptrdiff_t)); // three pointers

EDG and Clang interpret [[no_unique_address]] differently from MSVC. Command line:

PS E:\no_unique_address> cl /Zs /nologo /std:c++23preview .\bug.cpp
bug.cpp
PS E:\no_unique_address> clang-cl /Zs /nologo /std:c++23preview .\bug.cpp
.\bug.cpp(33,15): error: static assertion failed due to requirement 'sizeof(std::mdspan<int, std::extents<int, 18446744073709551615>,
      std::layout_left, DummyAccessor>) == sizeof(int)'
   33 | static_assert(sizeof(MDS) == sizeof(int));
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~
.\bug.cpp(33,27): note: expression evaluates to '8 == 4'
   33 | static_assert(sizeof(MDS) == sizeof(int));
      |               ~~~~~~~~~~~~^~~~~~~~~~~~~~
.\bug.cpp(34,15): error: static assertion failed due to requirement
      'sizeof(std::ranges::chunk_view<std::ranges::enumerate_view<std::ranges::subrange<DummyIterator, DummyIterator,
      std::ranges::subrange_kind::unsized>>>::_Iterator<true>) == 3 * sizeof(long long)'
   34 | static_assert(sizeof(ranges::iterator_t<View>) == 3 * sizeof(ptrdiff_t));
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\bug.cpp(34,48): note: expression evaluates to '32 == 24'
   34 | static_assert(sizeof(ranges::iterator_t<View>) == 3 * sizeof(ptrdiff_t));
      |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
PS E:\no_unique_address> cl /Zs /nologo /std:c++23preview .\bug.cpp /BE
bug.cpp
".\bug.cpp", line 33: error: static assertion failed
  static_assert(sizeof(MDS) == sizeof(int));
  ^
".\bug.cpp", line 33: note: the final comparison was 8 == 4
  static_assert(sizeof(MDS) == sizeof(int));
                            ^

".\bug.cpp", line 34: error: static assertion failed
  static_assert(sizeof(ranges::iterator_t<View>) == 3 * sizeof(ptrdiff_t));
  ^
".\bug.cpp", line 34: note: the final comparison was 32 == 24
  static_assert(sizeof(ranges::iterator_t<View>) == 3 * sizeof(ptrdiff_t));

Introduced in #4960.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcompilerCompiler work involvedhigh priorityImportant!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions