Defect report #4nn

Previous Defect Report < - > Next Defect Report


Submitter: Jens Gustedt
Submission Date:
2015-04-15 Source:
Reference Document: N/A
Version: 1.0
Date: 2015-04-15
Subject: Defect Report relative to C11: controlling expression of _Generic primary expression

Summary

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 expression of _Generic primary expression:

Does the controlling expression of a _Generic primary 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 6.3.2.1, that is lvalue to rvalue and array to pointer conversions.

Discussion

Problem

The problem arises to know whether or not the conversions of 6.3 apply to the controlling expression.

Case 1: integer promotions

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.

Case 2: Consequences of lvalue conversion

All conversion in 6.3.2.1 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 uninitialized register variables lead to undefined behavior when undergoing lvalue conversion. As a consequence:

Any lvalue conversion of a register variable leads to undefined behavior.

And thus

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.

Case 3: Consequences not doing conversions

In view of the resolution of DR 423 (rvalues drop qualifiers) using _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])   // -> 0
F(""[0])     // -> 1
F(+strc[0])  // -> 2

So the problem is here, that there is no type agnostic operator that results in a simple lvalue conversion for char const objects to char; all such operators also promote char to int.

Under the hypothesis that the controlling expression doesn't undergo conversion, any _Generic primary expression that uses a qualified lvalue of narrow type T can't trigger the association for T itself.

Possible solutions

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 6.5.1.1 p3, first sentence from

The controlling expression of a generic selection is not evaluated.
to
The controlling expression of a generic selection is not evaluated and the type of that expression is used without applying any conversions described in Section 6.3.

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:

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:

Whether or not the type of that expression is determined as if any of conversions described in Section 6.3 are applied to the controlling expression is implementation defined.


Previous Defect Report < - > Next Defect Report