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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions