diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-02 02:18:30 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-02 02:18:30 +0000 |
commit | 33bbbc5ec8269bc2cde5b84f970fa49319a30267 (patch) | |
tree | 229102a2c45a24da3c6f24d503de940f1c3e0900 | |
parent | b3b0b3624e462c2940f65b86e773bfc300005203 (diff) |
When determining whether an expression refers to a bit-field, look
into the left-hand side of an assignment expression. This completes
most of PR3500; the only remaining part is to deal with the
GCC-specific implementation-defined behavior for "unsigned long" (and
other) bit-fields.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70623 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Expr.h | 4 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 17 | ||||
-rw-r--r-- | test/Sema/bitfield.c | 2 |
6 files changed, 37 insertions, 33 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 8ba69fcc09..38d2124e64 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -175,7 +175,9 @@ public: isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; - bool isBitField(); + /// \brief If this expression refers to a bit-field, retrieve the + /// declaration of that bit-field. + FieldDecl *getBitField(); /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index d89290bbb9..19d67bb7f8 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1379,13 +1379,19 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const return isIntegerConstantExpr(Result, Ctx) && Result == 0; } -/// isBitField - Return true if this expression is a bit-field. -bool Expr::isBitField() { +FieldDecl *Expr::getBitField() { Expr *E = this->IgnoreParenCasts(); + if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E)) if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl())) - return Field->isBitField(); - return false; + if (Field->isBitField()) + return Field; + + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) + if (BinOp->isAssignmentOp() && BinOp->getLHS()) + return BinOp->getLHS()->getBitField(); + + return 0; } /// isArrow - Return true if the base expression is a pointer to vector, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index cc633e738d..d385e9c075 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2090,7 +2090,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // // Note that the bit-field check is skipped if we are just computing // the implicit conversion sequence (C++ [over.best.ics]p2). - if (InitLvalue == Expr::LV_Valid && (ICS || !Init->isBitField()) && + if (InitLvalue == Expr::LV_Valid && (ICS || !Init->getBitField()) && RefRelationship >= Ref_Compatible_With_Added_Qualification) { BindsDirectly = true; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 47b9fbd7bc..33d308ee39 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -128,12 +128,8 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { /// \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()) + FieldDecl *Field = E->getBitField(); + if (!Field) return QualType(); const BuiltinType *BT = Field->getType()->getAsBuiltinType(); @@ -1344,16 +1340,17 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, if (E->isTypeDependent()) return false; - if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { - if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { - if (FD->isBitField()) { - Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange; - return true; - } - // Other fields are ok. - return false; - } + if (E->getBitField()) { + Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange; + return true; } + + // Alignment of a field access is always okay, so long as it isn't a + // bit-field. + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) + if (dyn_cast<FieldDecl>(ME->getMemberDecl())) + return false; + return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false); } @@ -1385,7 +1382,7 @@ Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, // Delay type-checking for type-dependent expressions. } else if (!isSizeOf) { isInvalid = CheckAlignOfExpr(E, OpLoc, R); - } else if (E->isBitField()) { // C99 6.5.3.4p1. + } else if (E->getBitField()) { // C99 6.5.3.4p1. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0; isInvalid = true; } else { @@ -4254,7 +4251,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { << op->getSourceRange(); return QualType(); } - } else if (op->isBitField()) { // C99 6.5.3.2p1 + } else if (op->getBitField()) { // C99 6.5.3.2p1 // The operand cannot be a bit-field Diag(OpLoc, diag::err_typecheck_address_of) << "bit-field" << op->getSourceRange(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index eb4c4e6706..e6b8056a42 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -746,14 +746,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) // other value of that type for promotion purposes (C++ 4.5p3). // FIXME: We should delay checking of bit-fields until we actually // perform the conversion. - if (MemberExpr *MemRef = dyn_cast_or_null<MemberExpr>(From)) { - using llvm::APSInt; - if (FieldDecl *MemberDecl = dyn_cast<FieldDecl>(MemRef->getMemberDecl())) { + using llvm::APSInt; + if (From) + if (FieldDecl *MemberDecl = From->getBitField()) { APSInt BitWidth; - if (MemberDecl->isBitField() && - FromType->isIntegralType() && !FromType->isEnumeralType() && - From->isIntegerConstantExpr(BitWidth, Context)) { - APSInt ToSize(Context.getTypeSize(ToType)); + if (FromType->isIntegralType() && !FromType->isEnumeralType() && + MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { + APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + ToSize = Context.getTypeSize(ToType); // Are we promoting to an int from a bitfield that fits in an int? if (BitWidth < ToSize || @@ -770,8 +770,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) return false; } } - } - + // An rvalue of type bool can be converted to an rvalue of type int, // with false becoming zero and true becoming one (C++ 4.5p4). if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) { diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c index 526a225ff2..655f74121a 100644 --- a/test/Sema/bitfield.c +++ b/test/Sema/bitfield.c @@ -31,6 +31,6 @@ __typeof__(x.x+1) y; int y; struct {unsigned x : 2;} x2; -// FIXME: __typeof__((x.x+=1)+1) y; +__typeof__((x.x+=1)+1) y; __typeof__(x.x<<1) y; int y; |