microsoft / microsoft/STL

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

Open
#6,253 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug compiler high priority
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the supplied bug.cpp with both cl and clang-cl, then trace the mdspan and ranges::enumerate/chunk implementations involved in the two static assertions. Compare how [[no_unique_address]] affects their layouts across the reported compilers. Done means the layout behavior is resolved or clearly covered by tests for both cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.