diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-08-20 04:21:42 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-08-20 04:21:42 +0000 |
commit | 04e8357f6801e9ff52673e7e899a67bbabf9de93 (patch) | |
tree | 5f2ac85906d8ad5d147841d6ca95c0969793e7dd /lib | |
parent | d5c3b1339e842619fc3ae79482424f901aeb89f3 (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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 79 |
2 files changed, 50 insertions, 60 deletions
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); |