Submitter: Jens Gustedt
Reference Document: N/A
Subject: Defect Report relative to C11: controlling expression of _Generic primary expression
This is a follow up of the now closed DR 423 which resulted in the clarification of the status of qualifications of rvalues.
This defect report aims to clarify the status of the controlling
_Generic primary expression:
_Genericprimary expression undergo any type of conversion to calculate the type that is used to do the selection?
Implementors have given different answers to this question; clang doesn't apply any conversion, gcc applies the applicable conversions of 184.108.40.206, that is lvalue to rvalue and array to pointer conversions.
The problem arises to know whether or not the conversions of 6.3 apply to the controlling expression.
_Genericis not an operator, but a primary expression. The wording in 220.127.116.11 talks of has a type and doesn't make any reference to any type conversion.
_Genericeither, which are listed in 18.104.22.168.
Applying promotions would have as an effect that we wouldn't be able
to distinguish narrow integer types from
int. There is
no indication that the text implies that form or conversion, nor
that anybody has proposed to use
_Generic like this.
All conversion in 22.214.171.124 p2 describe what would in normal
CS language be named the evaluation of an object. It has no
provision to apply it to types alone.
In particular it includes the special clause that
register variables lead to undefined
behavior when undergoing lvalue conversion. As a consequence:
Any lvalue conversion of a
register variable leads to
Under the hypothesis that the controlling expression undergoes
lvalue conversion, any
_Generic primary expression
that uses an uninitialized
register variable as
controlling expression leads to undefined behavior.
In view of the resolution of DR 423 (rvalues drop qualifiers)
_Generic primary expressions with objects in
controlling expression may have results that appear surprising.
#define F(X) _Generic((X), char const: 0, char: 1, int: 2) char const strc = ""; F(strc) // -> 0 F("") // -> 1 F(+strc) // -> 2
So the problem is here, that there is no type agnostic operator that
results in a simple lvalue conversion for
char; all such operators also
Under the hypothesis that the controlling expression doesn't
undergo conversion, any
_Generic primary expression
that uses a qualified lvalue of narrow type
trigger the association for
In my view, the above discussion describes what can be read from the text of C11, alone. In other words if the committee would have wanted a solution that doesn't do any conversion (such as the interpretation by clang), it would not have looked much different than what we have.
To clarify that case, a little addition may be convenient, though:
Suggested Technical Corrigendum (Case 3)
Change 126.96.36.199 p3, first sentence from
If the intent of the committee had been Case 2 or similar, bigger changes of the standard would be indicated. I only list some of the areas that would need changes:
_Genericfrom primary expressions to a proper subsection, and rename the feature to
A third possibility would be to leave this leeway to implementations. I strongly object to that, but if so, I would suggest to add a phrase like:
Previous Defect Report < - > Next Defect Report