[cfe-commits] r70571 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CodeGen/bitfield-promote.c test/Sema/bitfield.c
Douglas Gregor
dgregor at apple.com
Fri May 1 13:41:21 PDT 2009
Author: dgregor
Date: Fri May 1 15:41:21 2009
New Revision: 70571
URL: http://llvm.org/viewvc/llvm-project?rev=70571&view=rev
Log:
Implement bit-field promotion rules for C99. Fixes PR3500.
Added:
cfe/trunk/test/CodeGen/bitfield-promote.c
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/Sema/bitfield.c
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=70571&r1=70570&r2=70571&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri May 1 15:41:21 2009
@@ -122,6 +122,45 @@
}
}
+/// \brief Whether this is a promotable bitfield reference according
+/// to C99 6.3.1.1p2, bullet 2.
+///
+/// \returns the type this bit-field will promote to, or NULL if no
+/// promotion occurs.
+static QualType isPromotableBitField(Expr *E, ASTContext &Context) {
+ MemberExpr *MemRef = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
+ if (!MemRef)
+ return QualType();
+
+ FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl());
+ if (!Field || !Field->isBitField())
+ return QualType();
+
+ const BuiltinType *BT = Field->getType()->getAsBuiltinType();
+ if (!BT)
+ return QualType();
+
+ if (BT->getKind() != BuiltinType::Bool &&
+ BT->getKind() != BuiltinType::Int &&
+ BT->getKind() != BuiltinType::UInt)
+ return QualType();
+
+ llvm::APSInt BitWidthAP;
+ if (!Field->getBitWidth()->isIntegerConstantExpr(BitWidthAP, Context))
+ return QualType();
+
+ uint64_t BitWidth = BitWidthAP.getZExtValue();
+ uint64_t IntSize = Context.getTypeSize(Context.IntTy);
+ if (BitWidth < IntSize ||
+ (Field->getType()->isSignedIntegerType() && BitWidth == IntSize))
+ return Context.IntTy;
+
+ if (BitWidth == IntSize && Field->getType()->isUnsignedIntegerType())
+ return Context.UnsignedIntTy;
+
+ return QualType();
+}
+
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
/// sometimes surpressed. For example, the array->pointer conversion doesn't
@@ -131,11 +170,31 @@
QualType Ty = Expr->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
- if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
+ // C99 6.3.1.1p2:
+ //
+ // The following may be used in an expression wherever an int or
+ // unsigned int may be used:
+ // - an object or expression with an integer type whose integer
+ // conversion rank is less than or equal to the rank of int
+ // and unsigned int.
+ // - A bit-field of type _Bool, int, signed int, or unsigned int.
+ //
+ // If an int can represent all values of the original type, the
+ // value is converted to an int; otherwise, it is converted to an
+ // unsigned int. These are called the integer promotions. All
+ // other types are unchanged by the integer promotions.
+ if (Ty->isPromotableIntegerType()) {
ImpCastExprToType(Expr, Context.IntTy);
- else
- DefaultFunctionArrayConversion(Expr);
-
+ return Expr;
+ } else {
+ QualType T = isPromotableBitField(Expr, Context);
+ if (!T.isNull()) {
+ ImpCastExprToType(Expr, T);
+ return Expr;
+ }
+ }
+
+ DefaultFunctionArrayConversion(Expr);
return Expr;
}
Added: cfe/trunk/test/CodeGen/bitfield-promote.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/bitfield-promote.c?rev=70571&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/bitfield-promote.c (added)
+++ cfe/trunk/test/CodeGen/bitfield-promote.c Fri May 1 15:41:21 2009
@@ -0,0 +1,19 @@
+// RUN: clang -O3 -emit-llvm -S -o %t %s &&
+// RUN: grep 'ret i64 4294967292' %t | count 2 &&
+// RUN: grep 'ret i64 -4' %t | count 1 &&
+// RUN: true
+
+long long f0(void) {
+ struct { unsigned f0 : 32; } x = { 18 };
+ return (long long) (x.f0 - (int) 22);
+}
+
+long long f1(void) {
+ struct { unsigned f0 : 31; } x = { 18 };
+ return (long long) (x.f0 - (int) 22);
+}
+
+long long f2(void) {
+ struct { unsigned f0 ; } x = { 18 };
+ return (long long) (x.f0 - (int) 22);
+}
Modified: cfe/trunk/test/Sema/bitfield.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/bitfield.c?rev=70571&r1=70570&r2=70571&view=diff
==============================================================================
--- cfe/trunk/test/Sema/bitfield.c (original)
+++ cfe/trunk/test/Sema/bitfield.c Fri May 1 15:41:21 2009
@@ -25,3 +25,7 @@
unsigned : -2; // expected-error {{anonymous bit-field has negative width (-2)}}
float : 12; // expected-error {{anonymous bit-field has non-integral type 'float'}}
};
+
+struct b {unsigned x : 2;} x;
+__typeof__(x.x+1) y;
+int y;
More information about the cfe-commits
mailing list