summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-08-20 04:21:42 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-08-20 04:21:42 +0000
commit04e8357f6801e9ff52673e7e899a67bbabf9de93 (patch)
tree5f2ac85906d8ad5d147841d6ca95c0969793e7dd
parentd5c3b1339e842619fc3ae79482424f901aeb89f3 (diff)
Fix bit-field promotion to be a bit closer to the behavior of gcc.
Patch by Enea Zaffanella, with some simplifications/corrections to isPromotableBitField by me. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79510 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h7
-rw-r--r--lib/AST/ASTContext.cpp31
-rw-r--r--lib/Sema/SemaExpr.cpp79
-rw-r--r--test/Sema/bitfield-promote-int-16bit.c25
-rw-r--r--test/Sema/bitfield-promote.c28
5 files changed, 108 insertions, 62 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index e4166c117c..e8b4e57ce8 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -818,6 +818,13 @@ public:
/// integer type.
QualType getPromotedIntegerType(QualType PromotableType);
+ /// \brief Whether this is a promotable bitfield reference according
+ /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
+ ///
+ /// \returns the type this bit-field will promote to, or NULL if no
+ /// promotion occurs.
+ QualType isPromotableBitField(Expr *E);
+
/// getIntegerTypeOrder - Returns the highest ranked integer type:
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
/// LHS < RHS, return -1.
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8a1f601603..cf7ad26f33 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2487,6 +2487,37 @@ unsigned ASTContext::getIntegerRank(Type *T) {
}
}
+/// \brief Whether this is a promotable bitfield reference according
+/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
+///
+/// \returns the type this bit-field will promote to, or NULL if no
+/// promotion occurs.
+QualType ASTContext::isPromotableBitField(Expr *E) {
+ FieldDecl *Field = E->getBitField();
+ if (!Field)
+ return QualType();
+
+ QualType FT = Field->getType();
+
+ llvm::APSInt BitWidthAP = Field->getBitWidth()->EvaluateAsInt(*this);
+ uint64_t BitWidth = BitWidthAP.getZExtValue();
+ uint64_t IntSize = getTypeSize(IntTy);
+ // GCC extension compatibility: if the bit-field size is less than or equal
+ // to the size of int, it gets promoted no matter what its type is.
+ // For instance, unsigned long bf : 4 gets promoted to signed int.
+ if (BitWidth < IntSize)
+ return IntTy;
+
+ if (BitWidth == IntSize)
+ return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy;
+
+ // Types bigger than int are not subject to promotions, and therefore act
+ // like the base type.
+ // FIXME: This doesn't quite match what gcc does, but what gcc does here
+ // is ridiculous.
+ return QualType();
+}
+
/// getPromotedIntegerType - Returns the type that Promotable will
/// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
/// integer type.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ef8165e167..e7d9d505b2 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -215,41 +215,6 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
}
}
-/// \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) {
- FieldDecl *Field = E->getBitField();
- if (!Field)
- 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
@@ -272,18 +237,17 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
// 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.
+ QualType PTy = Context.isPromotableBitField(Expr);
+ if (!PTy.isNull()) {
+ ImpCastExprToType(Expr, PTy);
+ return Expr;
+ }
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
ImpCastExprToType(Expr, PT);
return Expr;
- } else {
- QualType T = isPromotableBitField(Expr, Context);
- if (!T.isNull()) {
- ImpCastExprToType(Expr, T);
- return Expr;
- }
- }
-
+ }
+
DefaultFunctionArrayConversion(Expr);
return Expr;
}
@@ -355,10 +319,10 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
return lhs;
// Perform bitfield promotions.
- QualType LHSBitfieldPromoteTy = isPromotableBitField(lhsExpr, Context);
+ QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr);
if (!LHSBitfieldPromoteTy.isNull())
lhs = LHSBitfieldPromoteTy;
- QualType RHSBitfieldPromoteTy = isPromotableBitField(rhsExpr, Context);
+ QualType RHSBitfieldPromoteTy = Context.isPromotableBitField(rhsExpr);
if (!RHSBitfieldPromoteTy.isNull())
rhs = RHSBitfieldPromoteTy;
@@ -3948,15 +3912,12 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
}
if (CompLHSTy) {
- QualType LHSTy = lex->getType();
- if (LHSTy->isPromotableIntegerType())
- LHSTy = Context.getPromotedIntegerType(LHSTy);
- else {
- QualType T = isPromotableBitField(lex, Context);
- if (!T.isNull())
- LHSTy = T;
+ QualType LHSTy = Context.isPromotableBitField(lex);
+ if (LHSTy.isNull()) {
+ LHSTy = lex->getType();
+ if (LHSTy->isPromotableIntegerType())
+ LHSTy = Context.getPromotedIntegerType(LHSTy);
}
-
*CompLHSTy = LHSTy;
}
return PExp->getType();
@@ -4118,13 +4079,11 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
- QualType LHSTy = lex->getType();
- if (LHSTy->isPromotableIntegerType())
- LHSTy = Context.getPromotedIntegerType(LHSTy);
- else {
- QualType T = isPromotableBitField(lex, Context);
- if (!T.isNull())
- LHSTy = T;
+ QualType LHSTy = Context.isPromotableBitField(lex);
+ if (LHSTy.isNull()) {
+ LHSTy = lex->getType();
+ if (LHSTy->isPromotableIntegerType())
+ LHSTy = Context.getPromotedIntegerType(LHSTy);
}
if (!isCompAssign)
ImpCastExprToType(lex, LHSTy);
diff --git a/test/Sema/bitfield-promote-int-16bit.c b/test/Sema/bitfield-promote-int-16bit.c
new file mode 100644
index 0000000000..12d47205e8
--- /dev/null
+++ b/test/Sema/bitfield-promote-int-16bit.c
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s -triple pic16-unknown-unknown
+
+// Check that int-sized unsigned bit-fields promote to unsigned int
+// on targets where sizeof(unsigned short) == sizeof(unsigned int)
+
+enum E { ec1, ec2, ec3 };
+struct S {
+ enum E e : 16;
+ unsigned short us : 16;
+ unsigned long ul1 : 8;
+ unsigned long ul2 : 16;
+} s;
+
+__typeof(s.e + s.e) x_e;
+unsigned x_e;
+
+__typeof(s.us + s.us) x_us;
+unsigned x_us;
+
+__typeof(s.ul1 + s.ul1) x_ul1;
+signed x_ul1;
+
+__typeof(s.ul2 + s.ul2) x_ul2;
+unsigned x_ul2;
+
diff --git a/test/Sema/bitfield-promote.c b/test/Sema/bitfield-promote.c
index 42d4f5a196..066f5d78e7 100644
--- a/test/Sema/bitfield-promote.c
+++ b/test/Sema/bitfield-promote.c
@@ -1,4 +1,4 @@
-// RUN: clang -fsyntax-only -Xclang -verify %s
+// RUN: clang-cc -fsyntax-only -verify %s
struct {unsigned x : 2;} x;
__typeof__((x.x+=1)+1) y;
__typeof__(x.x<<1) y;
@@ -7,4 +7,28 @@ int y;
struct { int x : 8; } x1;
long long y1;
-__typeof__(((long long)x1.x + 1)) y1; \ No newline at end of file
+__typeof__(((long long)x1.x + 1)) y1;
+
+
+// Check for extensions: variously sized unsigned bit-fields fitting
+// into a signed int promote to signed int.
+enum E { ec1, ec2, ec3 };
+struct S {
+ enum E e : 2;
+ unsigned short us : 4;
+ unsigned long long ul1 : 8;
+ unsigned long long ul2 : 50;
+} s;
+
+__typeof(s.e + s.e) x_e;
+int x_e;
+
+__typeof(s.us + s.us) x_us;
+int x_us;
+
+__typeof(s.ul1 + s.ul1) x_ul1;
+int x_ul1;
+
+__typeof(s.ul2 + s.ul2) x_ul2;
+unsigned long long x_ul2;
+