On Tue, 4 May 2021, Liu Hao wrote:

在 5/4/21 2:48 AM, Martin Storsjö 写道:

Sure. However in practice, with e.g. code like this:

typedef void (*fp)(void);
_Atomic fp ptr1 = ((void(*)(void))0);
_Atomic fp ptr2 = ((void*)0);

Clang accepts ptr1 but errors out on ptr2: https://gcc.godbolt.org/z/3YW6EsGP4


It looks like a bug. As per C standard (N2176, ISO/IEC 9899:2017):

   ```
   6.3.2.3 Pointers
3 An integer constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. 67) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
   ```

So `(void*)0` is also a /null pointer constant/ and should be implicitly convertible to any pointer, including a function pointer.

I reported this as https://bugs.llvm.org/show_bug.cgi?id=50219 now, let's see if it gets any feedback.

In practice it shouldn't really matter, because as Jacek points out, we should be able to do without the atomics just fine in practice here.


I think I have to disagree on this. Just because something works 'in practice' doesn't mean it is correct in principle. The atomic load-store pair is essential to prevent races in case of multiple threads calling this function concurrently. One may argue that such races are harmless, but they are still undefined behavior, and could cause faults if thread sanitizer is involved.

Sure, I don't disagree that it's better to be safe with this.

We have tons of code that just update a regular pointer (and for cases where the pointer is the __imp_ pointer, the callers won't use atomic semantics for reading it), but we could at least make the updates of them atomic.

// Martin

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to