[cfe-dev] Missing implicit cast when parsing C++ ?

Enea Zaffanella zaffanella at cs.unipr.it
Wed Apr 6 13:30:01 PDT 2011


Il 06/04/2011 20:44, Eli Friedman ha scritto:
> On Wed, Apr 6, 2011 at 7:31 AM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:
>> 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?
> 
> 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:
================
struct S {
  operator int() const { return 1234; }
} s;

bool bar1() { return !s.operator int(); }
bool bar2() { return !s; }
================

Here the dump shows that the argument of ! in bar1() is not converted to
bool, while this is the case for the argument of ! in bar2(), where the
int() conversion operator is called implicitly:

================
bool bar1() (CompoundStmt 0x36db030 <lnot.cc:5:13, col:41>
  (ReturnStmt 0x36db010 <col:15, col:38>
    (UnaryOperator 0x36daff0 <col:22, col:38> '_Bool' prefix '!'
      (CXXMemberCallExpr 0x36daf80 <col:23, col:38> 'int'
        (MemberExpr 0x36daf48 <col:23, col:34> 'int (void) const'
.operator int 0x36dac70
          (ImplicitCastExpr 0x36dafd8 <col:23> 'const struct S' lvalue
<NoOp>
            (DeclRefExpr 0x36daf10 <col:23> 'struct struct S':'struct S'
lvalue Var 0x36dadc0 's' 'struct struct S':'struct S')))))))


bool bar2() (CompoundStmt 0x36db230 <lnot.cc:6:13, col:26>
  (ReturnStmt 0x36db210 <col:15, col:23>
    (UnaryOperator 0x36db1f0 <col:22, col:23> '_Bool' prefix '!'
      (ImplicitCastExpr 0x36db1d8 <col:23> '_Bool' <IntegralToBoolean>
        (CXXMemberCallExpr 0x36db1b0 <col:23> 'int'
          (MemberExpr 0x36db178 <col:23, <invalid sloc>> 'int (void)
const' .operator int 0x36dac70
            (ImplicitCastExpr 0x36db160 <col:23> 'const struct S' lvalue
<NoOp>
              (DeclRefExpr 0x36db100 <col:23> 'struct struct S':'struct
S' lvalue Var 0x36dadc0 's' 'struct struct S':'struct S'))))))))
================

If you agree, we will commit the patch sent by Abramo (it passes all of
the tests in clang).

Enea.



More information about the cfe-dev mailing list