Missing implicit cast when parsing C++ ?

According to the C++ standard, the operand of the logical negation
operator (!) is implicitly converted to type bool
(C++98/03 5.3.1p8, C++0x 5.3.1p9).

However, parsing this C++ code fragment using clang

bool foo() { return !1234; }

we obtain the following AST, with no implicit cast:

bool foo() (CompoundStmt 0x479b2f8 <ex.cc:1:12, col:28>
  (ReturnStmt 0x479b2d8 <col:14, col:22>
    (UnaryOperator 0x479b2b8 <col:21, col:22> '_Bool' prefix '!'
      (IntegerLiteral 0x479b290 <col:22> 'int' 1234))))

Usually, clang inserts all implicit casts in its AST.
Is the behavior above a _meant_ exception to this general rule?

(Side note: if the integer literal is replaced by some non-boolean
variable, an CK_LValueToRValue implicit cast is added, but again no cast
from the variable type to the Boolean type.)

Enea.

I've attached a candidate patch to fix this. Ok to commit?

LNot-casts.patch (929 Bytes)

Probably nobody noticed... the C definition of "!x" is "x==0", and in
practice that's the same as the definition in C++.

-Eli

Yes, it might be the case that this can never affect traditional clients
such as code generators.
However, it could affect source-based tools that have to check for and,
e.g., forbid some implicit conversions.

The "problem" is put into greater evidence by the following code:

Does this affect -O0 code generation for constructs like "if (!foo)"?

For references to the C++ standard, we generally prefer to use
"[expr.unary.op]" over "5.3.1", to make it easier to find in future
versions which might renumber the headings.

Otherwise, it should be fine.

-Eli

We consistently insert these implicit conversions everywhere else
in C++ that converts to bool; this isn't an intentional oversight.

Instead of going through an expensive re-analysis, since you
already know that we're converting a scalar to a bool (which
always suceeds), you can just switch on getScalarTypeKind() to
find the appropriate cast kind. Feel free to extract the logic from
SemaExprCXX.cpp:2187 out into its own function for this purpose.

Also, I'm not really sure that there's a good reason for us to not
represent these explicitly in C, except for the design questions
around operands that are already of type 'int'.

John.

According to the C++ standard, the operand of the logical negation
operator (!) is implicitly converted to type bool
(C++98/03 5.3.1p8, C++0x 5.3.1p9).

However, parsing this C++ code fragment using clang

bool foo() { return !1234; }

we obtain the following AST, with no implicit cast:

We consistently insert these implicit conversions everywhere else
in C++ that converts to bool; this isn't an intentional oversight.

Instead of going through an expensive re-analysis, since you
already know that we're converting a scalar to a bool (which
always suceeds), you can just switch on getScalarTypeKind() to
find the appropriate cast kind. Feel free to extract the logic from
SemaExprCXX.cpp:2187 out into its own function for this purpose.

Committed in r129066.

Also, I'm not really sure that there's a good reason for us to not
represent these explicitly in C, except for the design questions
around operands that are already of type 'int'.

This would be incongruent with C99 6.5.3.3p5.

Think also for:

int f(void* p) {
  return !p;
}

if we put an implicit cast around p we'd be forced to change logical not
argument type and to violate the standard.

I’m not that interested in the AST being slavishly obedient to the
standard down to the types of operands after implicit conversion.
The conversion’s cast kind pretty clearly identifies what’s going on.

But I don’t much care either way.

John.