Commit d25db7ed authored by John McCall's avatar John McCall
Browse files

Grab-bag of bit-field fixes:

  - References to ObjC bit-field ivars are bit-field lvalues;
    fixes rdar://13794269, which got me started down this.
  - Introduce Expr::refersToBitField, switch a couple users to
    it where semantically important, and comment the difference
    between this and the existing API.
  - Discourage Expr::getBitField by making it a bit longer and
    less general-sounding.
  - Lock down on const_casts of bit-field gl-values until we
    hear back from the committee as to whether they're allowed.

llvm-svn: 181252
parent 252a0acc
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -427,12 +427,24 @@ private:

public:

  /// \brief Returns true if this expression is a gl-value that
  /// potentially refers to a bit-field.
  ///
  /// In C++, whether a gl-value refers to a bitfield is essentially
  /// an aspect of the value-kind type system.
  bool refersToBitField() const { return getObjectKind() == OK_BitField; }

  /// \brief If this expression refers to a bit-field, retrieve the
  /// declaration of that bit-field.
  FieldDecl *getBitField();

  const FieldDecl *getBitField() const {
    return const_cast<Expr*>(this)->getBitField();
  ///
  /// Note that this returns a non-null pointer in subtly different
  /// places than refersToBitField returns true.  In particular, this can
  /// return a non-null pointer even for r-values loaded from
  /// bit-fields, but it will return null for a conditional bit-field.
  FieldDecl *getSourceBitField();

  const FieldDecl *getSourceBitField() const {
    return const_cast<Expr*>(this)->getSourceBitField();
  }

  /// \brief If this expression is an l-value for an Objective C
+2 −1
Original line number Diff line number Diff line
@@ -476,7 +476,8 @@ public:
                  SourceLocation l, SourceLocation oploc,
                  Expr *base,
                  bool arrow = false, bool freeIvar = false) :
    Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary,
    Expr(ObjCIvarRefExprClass, t, VK_LValue,
         d->isBitField() ? OK_BitField : OK_Ordinary,
         /*TypeDependent=*/false, base->isValueDependent(), 
         base->isInstantiationDependent(),
         base->containsUnexpandedParameterPack()), 
+5 −1
Original line number Diff line number Diff line
@@ -1307,7 +1307,8 @@ def err_member_function_call_bad_cvr : Error<"member function %0 not viable: "
    "volatile or restrict|const, volatile, or restrict}2">;

def err_reference_bind_to_bitfield : Error<
  "%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
  "%select{non-const|volatile}0 reference cannot bind to "
  "bit-field%select{| %1}2">;
def err_reference_bind_to_vector_element : Error<
  "%select{non-const|volatile}0 reference cannot bind to vector element">;
def err_reference_var_requires_init : Error<
@@ -4629,6 +4630,9 @@ def err_bad_cxx_cast_generic : Error<
def err_bad_cxx_cast_rvalue : Error<
  "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
  "functional-style cast}0 from rvalue to reference type %2">;
def err_bad_cxx_cast_bitfield : Error<
  "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
  "functional-style cast}0 from bit-field lvalue to reference type %2">;
def err_bad_cxx_cast_qualifiers_away : Error<
  "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
  "functional-style cast}0 from %1 to %2 casts away qualifiers">;
+1 −1
Original line number Diff line number Diff line
@@ -4277,7 +4277,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
  if (E->isTypeDependent() || E->isValueDependent())
    return QualType();
  
  FieldDecl *Field = E->getBitField();
  FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields?
  if (!Field)
    return QualType();

+8 −3
Original line number Diff line number Diff line
@@ -3149,7 +3149,7 @@ bool Expr::isObjCSelfExpr() const {
  return M->getSelfDecl() == Param;
}

FieldDecl *Expr::getBitField() {
FieldDecl *Expr::getSourceBitField() {
  Expr *E = this->IgnoreParens();

  while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
@@ -3165,6 +3165,11 @@ FieldDecl *Expr::getBitField() {
      if (Field->isBitField())
        return Field;

  if (ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E))
    if (FieldDecl *Ivar = dyn_cast<FieldDecl>(IvarRef->getDecl()))
      if (Ivar->isBitField())
        return Ivar;

  if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E))
    if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
      if (Field->isBitField())
@@ -3172,10 +3177,10 @@ FieldDecl *Expr::getBitField() {

  if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) {
    if (BinOp->isAssignmentOp() && BinOp->getLHS())
      return BinOp->getLHS()->getBitField();
      return BinOp->getLHS()->getSourceBitField();

    if (BinOp->getOpcode() == BO_Comma && BinOp->getRHS())
      return BinOp->getRHS()->getBitField();
      return BinOp->getRHS()->getSourceBitField();
  }

  return 0;
Loading