aaron.ballman added a comment. In D125919#3556754 <https://reviews.llvm.org/D125919#3556754>, @rsmith wrote:
> In D125919#3556418 <https://reviews.llvm.org/D125919#3556418>, @aaron.ballman > wrote: > >> In D125919#3556319 <https://reviews.llvm.org/D125919#3556319>, @rjmccall >> wrote: >> >>> Now, the standard has chosen not to talk about `_Atomic` as a qualifier, I >>> assume because there's a fair number of rules in the standard that assume >>> that qualifiers can be freely added to pointers and don't change layout and >>> so on, none of which apply to `_Atomic`. But those rules also don't apply >>> to a large number of other extended qualifiers, like address spaces and the >>> ARC ownership qualifiers and `__ptrauth`. The committee should probably >>> just come to terms with the fact that it's the relatively easy-come-easy-go >>> nature of the CVR qualifiers which is the special case. I've thought for >>> awhile that Clang should really be representing `_Atomic` as a qualifier >>> instead of having to treat `AtomicType` as a special case in a million >>> places. >> >> I'm not certain if we can get away with that. IIRC, Microsoft uses embedded >> locks on Windows in some circumstances. However, cl doesn't support >> `_Atomic` and so maybe we can get away with it on the assumption we have no >> other targets where the size/alignment would be different for an atomic type >> vs a non-atomic type? > > That assumption does not hold. Given `struct A { char c[3]; };`, `struct A` > has size 3 and align 1, but `_Atomic struct A` has size 4 and align 4 across > many (perhaps all?) of our targets. (This is an ABI divergence between GCC > and Clang, which as far as I know the psABI owners have so far not succeeded > in resolving.) Good point! > I saw some talk in WG14 of separating `_Atomic(T)` and `_Atomic T` so that > `_Atomic T` would be a qualifier that doesn't affect size or alignment, only > what code is generated to access the value, and `_Atomic(T)` would be a > distinct type with potentially a different representation in order to support > lock-free atomic access. Did that go anywhere? (I'd assume not, it seems to > be at least a decade too late for such an idea.) So far that's just been talk (and I'm not convinced it'll be possible to change the semantics there without silently breaking code). In D125919#3558062 <https://reviews.llvm.org/D125919#3558062>, @rjmccall wrote: >> I disagree with the assessment that _Atomic behaves exactly like a >> qualifier. It *should* (IMHO), but it doesn't. C allows the size and >> alignment of an atomic type be *different* from its unqualified version, to >> allow for embedded locks and such. Because the size and alignment can be >> different, to my mind, _Atomic int and int are different types in the same >> way as _Complex float and float -- the object representations can (must, in >> the case of _Complex) be different, so they're different types. The same is >> not true for const, volatile, or restrict qualifiers -- those are required >> to have the same size and alignment as the unqualified type. > > I think our apparent disagreement here is rooted in something quite simple: > you seem to be assuming that a qualified type by definition cannot have a > different size and alignment from the unqualified type, and I think that's a > property that's *guaranteed* for the CVR qualifiers and merely *happens to be > true* for our current set of extended qualifiers, and only really because we > don't represent `_Atomic` as a qualifier. I think you're right about the root of our disagreement. Any qualifiers other than CVR, _Atomic, and address spaces are fully implementation-defined and can do whatever they want, thus aren't really relevant to how standard qualifiers behave. Address spaces are covered by TR 18037 (which states they're extending the list of CVR qualifiers in C, thus I'd expect would follow the same rules as CVR despite predating DR423). We treat all standards-based qualifiers as a `Qualifier` in Clang, except for `_Atomic`, which I believe we treat differently because it behaves as a distinct type. I think we *want* that behavior -- these are not valid redeclarations: `void func(int a); void func(_Atomic int a);` while these are valid (and have utility): `void func(int a); void func(const int a);`. > Many of our extended qualifiers completely change the ABI of the type they > qualify, and they can change the basic semantic properties of types they're > nested within. I don't see why we'd draw a line around type layout for what > counts as a qualifier and what doesn't. For example, ObjC ARC happens to > implement `__weak` references without using extra inline storage, but it > would certainly be a reasonable ABI choice to make them larger than just a > pointer — Swift does with its native weak references, for example. That ABI > choice wouldn't make `__weak` suddenly not a qualifier. Type constructors > like `_Atomic`, `_Complex`, `const`, and `*` are qualifiers or not based on > the role and behavior of the constructed type in the language, not its ABI > properties. For our implementation-defined qualifiers, I think the design space is wide open and we can do what we want. However, I think `_Atomic` specifically is more closely related to a new type than a qualified type for the other standards-based qualifiers. The C standard goes out of its way to segregate atomic types from other types but doesn't do anything similar for any other qualifier. All that said, I think you can see why I'm hoping to get an answer from WG14 as to what to do. Reasonable folks are disagreeing on what the standard requires here. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D125919/new/ https://reviews.llvm.org/D125919 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits