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/AST/ASTContext.cpp | |
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/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 31 |
1 files changed, 31 insertions, 0 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. |