]> granicus.if.org Git - clang/commitdiff
When determining whether an expression refers to a bit-field, look
authorDouglas Gregor <dgregor@apple.com>
Sat, 2 May 2009 02:18:30 +0000 (02:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 2 May 2009 02:18:30 +0000 (02:18 +0000)
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

include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOverload.cpp
test/Sema/bitfield.c

index 8ba69fcc09e652476499459a9a0ad14759155f64..38d2124e6433dfd5afed4ceac5b445c530766fd1 100644 (file)
@@ -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
index d89290bbb97092a2d87a8cb7efcf011b901b2318..19d67bb7f8a11960223bd483e06ccf102f6132bb 100644 (file)
@@ -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,
index cc633e738d75d03e36aa8024291b4f3a2a434286..d385e9c0759b31610583efd24dc2c50de48ca0a0 100644 (file)
@@ -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;
 
index 47b9fbd7bce9d132d5cd775fca6ca92cdf594b79..33d308ee3982171545c5e94668e92703a941de04 100644 (file)
@@ -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();
index eb4c4e6706dd1162bb60423fe872ff61db5a2c29..e6b8056a428a11883ab8f757e19cad1c07dc0eb8 100644 (file)
@@ -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) {
index 526a225ff2c8bf4231c94997d36b11fdf99b8277..655f74121a32126a2618777d44d927b82d365865 100644 (file)
@@ -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;