diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-06-28 21:17:55 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-06-28 21:17:55 +0000 |
commit | aadb254a79558de8ad5911ac7b4a6dacb45d44dc (patch) | |
tree | 5893a0f17b5372e26ddbbe6d1f4c9bb87d777e49 /clang/lib/AST/ASTContext.cpp | |
parent | 019d3cd3b4c08dd2d39def08c983f3af9f9b2cd9 (diff) | |
download | bcm5719-llvm-aadb254a79558de8ad5911ac7b4a6dacb45d44dc.tar.gz bcm5719-llvm-aadb254a79558de8ad5911ac7b4a6dacb45d44dc.zip |
PR37979: integral promotions in C++ treat enum bit-fields like enums,
not like bit-fields.
We used to get this right "by accident", because conversions for the
selected built-in overloaded operator would convert the enum bit-field
to its corresponding underlying type early. But after DR1687 that no
longer happens.
Technically this change should also apply to C, where bit-fields only
have special promotion rules if the bit-field's declared type is
_Bool, int, signed int, or unsigned int, but for GCC compatibility we
only look at the bit-width and not the underlying type when performing
bit-field integral promotions in C.
llvm-svn: 335925
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 43577e8640a..ca54d8f6759 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5456,6 +5456,12 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) return {}; + // C++ [conv.prom]p5: + // If the bit-field has an enumerated type, it is treated as any other + // value of that type for promotion purposes. + if (getLangOpts().CPlusPlus && E->getType()->isEnumeralType()) + return {}; + // FIXME: We should not do this unless E->refersToBitField() is true. This // matters in C where getSourceBitField() will find bit-fields for various // cases where the source expression is not a bit-field designator. @@ -5482,13 +5488,15 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { // // FIXME: C does not permit promotion of a 'long : 3' bitfield to int. // We perform that promotion here to match GCC and C++. + // FIXME: C does not permit promotion of an enum bit-field whose rank is + // greater than that of 'int'. We perform that promotion to match GCC. 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 + // Bit-fields wider than int are not subject to promotions, and therefore act // like the base type. GCC has some weird bugs in this area that we // deliberately do not follow (GCC follows a pre-standard resolution to // C's DR315 which treats bit-width as being part of the type, and this leaks |