1

I was playing around with the atomic implementation in C++. I have the below code excerpt from the aforementioned SO post:

#include <atomic>
#include <cstdint>
#include <iostream>

template <class value_t, class block_t> struct my_atomic {
  using value_type = value_t;
  using difference_type = value_type;

  my_atomic() noexcept = default;
  constexpr my_atomic(value_t desired) noexcept
      : value(reinterpret_cast<block_t &>(desired)) {}
  my_atomic(const my_atomic &) = delete;

  my_atomic &operator=(const my_atomic &) = delete;
  my_atomic &operator=(const my_atomic &) volatile = delete;

  operator value_t() const noexcept {
    const block_t value = this->value;
    return reinterpret_cast<const value_t &>(value);
  }
  operator value_t() const volatile noexcept {
    const block_t value = this->value;
    return reinterpret_cast<const value_t &>(value);
  }

private:
  std::atomic<block_t> value;
};

using my_atomic_float = my_atomic<float, std::uint32_t>;

int main() {
  my_atomic_float var{5};
  float result = 5 * var;
  std::cout << "result: " << result << '\n';
  return 0;
}

When I try to compile with -Wall -Wpedantic -Werror using g++ and clang++, clang++ compiles the code whereas g++ does not. Well, of course, I can turn off the -Werror switch, but I would like to understand if the above code is dangerous.

I have already read a couple of posts ([1], [2], and some others like [3]) and still don't know

  1. if I should just ignore/disable the warning, or if I should rewrite it, and,
  2. if I should rewrite it, how should I make a change? I have tried an intermediate reinterpret_cast<char &>, for instance, which did not work, either.

I would appreciate any help. Thanks!

EDIT. Sorry for not sharing the below:

~> g++ --version
g++ (GCC) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

~> g++ -Wall -Wpedantic -Werror -std=c++14 -O3 question.cpp -o question.out
question.cpp: In instantiation of ‘constexpr my_atomic<value_t, block_t>::my_atomic(value_t) [with value_t = float; block_t = unsigned int]’:
question.cpp:33:24:   required from here
question.cpp:11:15: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
       : value(reinterpret_cast<block_t &>(desired)) {}
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
question.cpp: In instantiation of ‘my_atomic<value_t, block_t>::operator value_t() const [with value_t = float; block_t = unsigned int]’:
question.cpp:34:22:   required from here
question.cpp:19:12: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
     return reinterpret_cast<const value_t &>(value);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors

~> clang++ --version
clang version 5.0.1 (tags/RELEASE_501/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
SergeyA
  • 61,605
  • 5
  • 78
  • 137
Arda Aytekin
  • 1,231
  • 14
  • 24
  • 1
    Can you perhaps tell us what errors you get with GCC? And which version of GCC you use? – Some programmer dude Mar 16 '18 at 13:45
  • Sorry @Someprogrammerdude, I have edited my post just now. – Arda Aytekin Mar 16 '18 at 13:50
  • You are violating strict aliasing rule. You can search for it here on stack overflow. – SergeyA Mar 16 '18 at 13:59
  • Yes, that's what the `gcc` error says, @SergeyA. I have read the issue a bit, maybe not enough. Yet, I do know that this starts to happen when optimization level greater than 1 kicks in. The thing is, gcc refuses to compile (or, at least, it warns me about the issue) whereas clang silently compiles, when using the same optimization levels. As for the second part of my question, I would really appreciate if you gave me a hint on how to rewrite the above functionality without violating the strict aliasing rule. – Arda Aytekin Mar 16 '18 at 14:07
  • Strict aliasing rule is an undefined behavior. Compilers are under no obligation to detect it, so some do it better than another. gcc detects it, clang does not. I am not sure what you are trying to achieve, so I do not know how to fix your problem. – SergeyA Mar 16 '18 at 14:15
  • I am trying to have some sort of `atomic` functionality, at least until `C++20`, similar to that defined in the linked SO question or the one defined in [CUDA documentation](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#atomic-functions). They seem to be violating the strict aliasing rule, too. – Arda Aytekin Mar 16 '18 at 14:19

0 Answers0