Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[expr.add] p4 lacks to specify the case when the expression J has an unscoped enumeration type CWG1642 #5199

Closed
xmh0511 opened this issue Jan 12, 2022 · 9 comments · Fixed by #6328

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Jan 12, 2022

[expr.add] p4 only specifies the calculation process for the case when J has an integral type and P has a pointer type

When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.

Since we admit that J can also have an unscoped enumeration type in [expr.add] p1 and [expr.add] p2. And, I think the usual arithmetic conversion is not applied to the case when J has an unscoped enumeration type and P has a pointer type. Should we augment [expr.add] p4 to be that?

When an expression J that has an integral type or unscoped enumeration type is added to or subtracted from an expression P of pointer type, the result has the type of P. If J has an unscoped enumeration type, the integral promotion conversion is performed on J, and the converted operand is used in place of the original operand for the remainder of this subclause.

  • [...]
@languagelawyer
Copy link
Contributor

[expr.add]/1: The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Jan 15, 2022

[expr.add]/1: The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.

All cases defined in [expr.arith.conv] do not mention the operand with pointer type.

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • [...]

Presumably, the usual arithmetic conversions are only performed when two operands are both of arithmetic or enumeration type.

enum A{
    a = 0;
};
int arr[2];
int* ptr = arr;
ptr + A::a;

R8N T_@T 85C0$VUFAX_~7F

@TheCalligrapher
Copy link

TheCalligrapher commented Aug 18, 2022

[expr.add]/1: The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.

Specification of the usual arithmetic conversions fails if we allow pointer operands to get there. For pointer operands we'd be forced to execute the very last - unconditional - entry in the sub-list (1.5.5 in the screenshot above) and convert the pointer to some integer type. This, of course, does not make a shred of sense.

If the original intent was to perform integral promotions (for enums and bool) as part of usual arithmetic conversions, then the spec of usual arithmetic conversions has to be updated to accommodate for that possibility. In its current form it is defective, if pointer operands are allowed to get there.

@TheCalligrapher
Copy link

TheCalligrapher commented Aug 18, 2022

R8N T_@T 85C0$VUFAX_~7F

It is not clear what you mean by your side note about the bullets being "all false". The very last bullet in this list does not have an "if" condition associated with it. So, it can't be "true" or "false". It is unconditional. If you get to that bullet in the list you have to follow it. Which implies that if pointers get here, they shall be converted to unsigned integer type.

This, of course, is definitely not the intent. Clearly, usual arithmetic conversions are not supposed to be applied when one operand is a pointer.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 18, 2022

The very last bullet in this list does not have an "if" condition associated with it.

It does not make sense that this bullet would be performed on an operand of pointer type. The exact issue is that [expr.add] p1 and p2 have listed the permitted types of operands for addition and subtraction, respectively, which comprises unscoped enumeration type, but the usual arithmetic conversions obviously does not apply to the case where one operand has pointer type and the other has unscoped enumeration type, and [expr.add] p4 only defines the case where one operand has a pointer type and the other has an integral type. Obviously, unscoped enumeration type is not an integral type.

From the context of the definition of usual arithmetic conversion, it is only performed for the case where both operands of a binary operator are of arithmetic or enumeration type. So, it may be an improvement if we change the following sentence

The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.

to

The usual arithmetic conversions are performed if both operands that are of arithmetic or enumeration type.

For all binary operators in [expr] that expect usual arithmetic conversions to perform on their operands.

For the subject of this issue. We should augment [expr.add] p4 to make integer promotion conversion first apply to the operand that is of the unscoped enumeration or integral type.

@TheCalligrapher
Copy link

The very last bullet in this list does not have an "if" condition associated with it.

It does not make sense that this bullet would be performed on an operand of pointer type. The exact issue is that [expr.add] p1 and p2 have listed the permitted types of operands for addition and subtraction, respectively, which comprises unscoped enumeration type, but the usual arithmetic conversions obviously does not apply to the case where one operand has pointer type and the other has unscoped enumeration type, and [expr.add] p4 only defines the case where one operand has a pointer type and the other has an integral type. Obviously, unscoped enumeration type is not an integral type.

Yes, that's exactly my point. It makes no sense to stuff pointer + anything into usual arithmetic conversions, because it is obvious that usual arithmetic conversions cannot handle this situation (and have never been intended to).

Note that the problem exists with bool as well, even though bool is formally an integer type. bool still needs an integral promotion to become a "normal" integer (0 or 1), because the standard does not define the behavior of [non-promoted] false and true in addition or subtraction contexts.

For the subject of this issue. We should augment [expr.add] p4 to make integer promotion conversion first apply to the operand that is of the unscoped enumeration or integral type.

Precisely.

There's no reason to modify the definition of usual arithmetic conversions to make them handle pointer operand. They have never been intended for that purpose. All that needs to be done is apply integral promotions early in [expr.add].

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 19, 2022

It should note that adding the restriction regarding what situation the usual arithmetic conversion can apply is also a key point.

The usual arithmetic conversions are performed if both operands are of arithmetic or enumeration type.

This can emphasize the scope of the application of the usual arithmetic conversion.

@frederick-vs-ja
Copy link
Contributor

Seemingly fixed by #6328 (9edd682).

@jensmaurer jensmaurer changed the title [expr.add] p4 lacks to specify the case when the expression J has an unscoped enumeration type [expr.add] p4 lacks to specify the case when the expression J has an unscoped enumeration type CWG1642 Oct 23, 2023
@jensmaurer
Copy link
Member

Fixed by CWG1642

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants