5

There is a related "what" question here: C11 grammar ambiguity between _Atomic type specifier and qualifier

What I'm interested is why, since the C11 rationale hasn't been published yet, and this seems needlessly complex.

The grammar includes both of these (and resolves the ambiguity in favor of shifting the ( rather than reduce (which would otherwise be in lookahead if followed by a declarator or abstract-declarator)), reachable from declaration-specifiers or specifier-qualifier-list:

atomic-type-specifier: _Atomic ( type-name )
type-qualifier: _Atomic

This leads to the following code:

int i1;
int (i2); // valid, same as i1 - usually seen in the context of pointer-to-function or pointer-to-array
int _Atomic a1;
int _Atomic (a2); // invalid
_Atomic (int) a3; // valid, same as a1

Thoughts:

  • _Atomic must not modify an array or function. Barring redundant parentheses around a declarator, this means it would be valid to #define _Atomic(x) x _Atomic (if it were legal to #define keywords of course).

  • When it occurs as a qualifier, _Atomic is the same syntactical part as const, and C programmers are already used to putting const on the correct side, so it can't be for "ease of use".

o11c
  • 15,265
  • 4
  • 50
  • 75
  • Perhaps this obviously gratuitous introduction of a shift-reduce conflict into otherwise a fairly clean context free grammar to implement an unneeded feature is to warm us up for http://www.open-std.org/jtc1/sc22//WG14/www/docs/n2137.pdf (Attributes in C), which introduces tens if not hundreds of them. (But hey, at least we'll be more C++-compatible even though we already aren't). – Petr Skocik Sep 18 '19 at 14:31
  • Seriously, though the redundancies around _Atomic are disappointing. http://port70.net/~nsz/c/c11/n1570.html#6.7.3p3 is redundant too as no qualifiers can be used to apply to whole arrays of functions. Also, why do we also need a bazillion of atomic type aliases -- http://port70.net/~nsz/c/c11/n1570.html#7.17.6p1 ? It'd be nice if the standards explained themselves more. I wish standards were more genius.com for code--public, publicly commentable and with contextual rationalizations that pop up whenever you click on a piece of text. – Petr Skocik Sep 18 '19 at 14:36
  • For the C++ compatibility thing they could have rather standardized `__typeof`. It's been around forever, it's widely used, and it's been proposed for inclusion in the C standard a long time ago. With __typeof, you could do `#define _Atomic(T) __typeof(T _Atomic)` and it would work with `_Atomic(T) x,y;` to define both x and y as the same type even if `T` is a had a `*` at the end. – Petr Skocik Sep 18 '19 at 14:51

1 Answers1

5

The rationale is found in N1485:

The _Atomic keyword also can also be used in the form _Atomic(T), where T is a type, as a type specifier equivalent to _Atomic T. Thus, _Atomic(T) x, y; declares x and y with the same type, even if T is a pointer type. This allows for trivial C++0x compatibility with a C++ only _Atomic(T) macro definition as atomic<T>.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • 1
    Another way of looking at it: `const int *x, *const y;` == `const int *x; const int *const y;`. The same can be done with the `_Atomic` type qualifier as can be done with the `const` type qualifier, qualifying an atomic pointer type. That's the only plausible reason for the `_Atomic` type qualifier to even exist as far as I'm aware. Otherwise, it's pointlessly redundant. –  Apr 03 '16 at 04:13
  • As an aside -- at least we know where some of the *casting malloc* garbage comes from [**N1485 pp.4**](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1485.pdf) – David C. Rankin Apr 03 '16 at 04:26