4 ms·
But, you’d have an even harder time making that work with mask-and-shift macros! It also doesn’t seem like something that would come up very often. I can’t thi
by iainmerrick 5y ago
But, you’d have an even harder time making that work with mask-and-shift macros!
It also doesn’t seem like something that would come up very often. I can’t think of the last time I conditionally stored to one of two struct fields, if I ever have.
The much more normal case would be:
val = choice ? a.x : a.y;
That one seems pretty straightforward from a codegen perspective.
- ncmncm 5y ago"Seems" is not the domain under discussion.
- jcranmer 5y agoThe example I gave is an example of something legal with bitfields (in C++) that is legitimately challenging to implement [1] that leads to bugs in compilers. It's not meant to be something that anyone is intended to use--indeed, I'd firmly suggest that the standard ought to prohibit this kind of usage. The broader point is that bitfields are actually weird little objects that look a lot like regular objects in many, but not all, contexts. And it's very easy from a language design or implementation perspective to forget to account for the possibility that you're dealing with a weird little object. This leads to underspecified language specifications and compilers that crash if you do something weird (but legal) such as virtually inherit from a struct containing a bitfield as its last member. [1] So challenging, in fact, that Clang gives an error message "cannot compile this conditional operator yet". It does work in g++, icx, and MSVC though.
- iainmerrick 5y agoThat all makes it sound like a C++ problem, not a C problem.
- jcranmer 5y agoYou can make a lot of the "fun" of bitfields go away with lvalue-to-rvalue conversion, and C tends to do this conversion very rapidly so that it's hard to find good cases for truly bizarre stuff, whereas C++ makes lvalues last a lot longer. Of course, if you go reach for C's standard "fun with lvalue" operations, you can get some crazy nonsense. What machine code should you generate here [1]: struct A { int x : 5; volatile _Atomic int y: 3; } a; a.y++; I will note that the intersection of volatile and bitfields has been another fruitful area of compiler bugs [2] historically speaking. While C++ does provide better what-the-ever-living-fuck moments for bitfields, C has had its fair share of issues with bitfields. [1] Whether or not you can make a bitfield _Atomic in C is implementation-defined, so it's possible that someone writes a C implementation where this is legal. I will note that, in a rare display of sanity, all C compilers I can test do in fact sensibly reject _Atomic bitfields, but for the purposes of argument, assume that someone has one where it's permitted, since it is allowable by the standard. [2] Or programmer bugs blamed on the compiler. This is the intersection of two areas that are notorious for underspecification to begin with, and combined with the general tendency of programmers to expect C compilers to be a thin veneer over assembly, makes it awfully difficult to figure out which behavior is language-intended.
- dfox 5y agoI vaguely recall that gcc supports this even in C mode. The underlying problem has to do with whether the IR has first-class concept of arbitrary lvalue or whether the frontend has to convert lvalues that get passed around to some pointer-like thing. It might look irrelevant for discussion of low-level AOT compilers, but it is also interesting to compare how this is implemented in dynamic/“scripting” runtimes and how the choice of underlying implementation of the concept of “lvalue”/“place” influences the user visible language. Somewhat notably first draft of Common Lisp had something akin to first-class lvalues and the final standard replaced all that with significantly simpler mechanism that purely relies on macros.
- ncmncm 5y agoMissing the point, again. He is describing a trivial difference between C and C++ that is not the problem you are being warned about.