[cfe-dev] Clang miscompiles casted bitfields expression

Abramo Bagnara abramobagnara at tin.it
Thu Jul 2 01:09:41 PDT 2009

The following typescript show the problem:

$ cat w.c

struct s {
  int v:8;

long long f(struct s *a) {
    ((long long)(a->v)) << 32;

$ ~/eclair/src/parser/dest/bin/clang-cc -ast-dump w.c
typedef char *__builtin_va_list;
struct s {
    int v : (IntegerLiteral 0x9933c28 'int' 8)
long long f(struct s *a) (CompoundStmt 0x9932c28
  (ReturnStmt 0x9933fc0
    (ImplicitCastExpr 0x9933fa0 'long long'
      (BinaryOperator 0x9933f78 'int' '<<'
        (ImplicitCastExpr 0x99120f8 'int'
          (ParenExpr 0x99120b0 'long long'
            (CStyleCastExpr 0x9912088 'long long'
              (ParenExpr 0x9934e68 'int'
                (MemberExpr 0x9934e40 'int' ->v 0x9933c50
                  (DeclRefExpr 0x9933d38 'struct s *' ParmVar='a'
        (IntegerLiteral 0x99120d0 'int' 32)))))

As you see the long long value is casted to int before the left shift
and this is wrong.

I've tracked down the problem to

Expr *Sema::UsualUnaryConversions(Expr *&Expr)

which calls

QualType isPromotableBitField(Expr *E, ASTContext &Context)

which calls

FieldDecl *Expr::getBitField()

which calls

Expr *Expr::IgnoreParenCasts()

The problem is that the latter goes down in the expression bypassing
also the CStyleCastExpr then inducing isPromotableBitField to return the
type of the bitfield and not the type of CStyleCastExpr.

The fix should be trivial (and the problem is currently rather severe),
but I want to be sure to not misunderstand something.

More information about the cfe-dev mailing list