diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 20 | ||||
| -rw-r--r-- | clang/include/clang/AST/ExprObjC.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp | 23 | ||||
| -rw-r--r-- | clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp | 17 | ||||
| -rw-r--r-- | clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp | 20 | ||||
| -rw-r--r-- | clang/test/Sema/bitfield.c | 15 | ||||
| -rw-r--r-- | clang/test/SemaObjCXX/references.mm | 19 | 
15 files changed, 147 insertions, 24 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 2e66df33eee..4ff1257b7dc 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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 diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index dfd45279dd1..a94c69a115d 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -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()),  diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index bc0640eaa71..f5345eb8c35 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2a405271b6d..176aec53a25 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -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(); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index cf7ddbce937..9538ddf9416 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index d6c378e3d48..eb11a577cb0 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1452,7 +1452,7 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,    DestType = Self.Context.getCanonicalType(DestType);    QualType SrcType = SrcExpr->getType();    if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) { -    if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) { +    if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr->isLValue()) {        // Cannot const_cast non-lvalue to lvalue reference type. But if this        // is C-style, static_cast might find a way, so we simply suggest a        // message and tell the parent to keep searching. @@ -1460,6 +1460,16 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,        return TC_NotApplicable;      } +    // It's not completely clear under the standard whether we can +    // const_cast bit-field gl-values.  Doing so would not be +    // intrinsically complicated, but for now, we say no for +    // consistency with other compilers and await the word of the +    // committee. +    if (SrcExpr->refersToBitField()) { +      msg = diag::err_bad_cxx_cast_bitfield; +      return TC_NotApplicable; +    } +      // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2      //   [...] if a pointer to T1 can be [cast] to the type pointer to T2.      DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index e14635ee25d..a0998a46c66 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4311,7 +4311,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {      IntRange::forValueOfType(C, E->getType());    } -  if (FieldDecl *BitField = E->getBitField()) +  if (FieldDecl *BitField = E->getSourceBitField())      return IntRange(BitField->getBitWidthValue(C),                      BitField->getType()->isUnsignedIntegerOrEnumerationType()); @@ -4688,7 +4688,7 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {    // We want to recurse on the RHS as normal unless we're assigning to    // a bitfield. -  if (FieldDecl *Bitfield = E->getLHS()->getBitField()) { +  if (FieldDecl *Bitfield = E->getLHS()->getSourceBitField()) {      if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(),                                    E->getOperatorLoc())) {        // Recurse, ignoring any implicit conversions on the RHS. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0c1065813eb..dd05b822364 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3383,7 +3383,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,      isInvalid = CheckAlignOfExpr(*this, E);    } else if (ExprKind == UETT_VecStep) {      isInvalid = CheckVecStepExpr(E); -  } else if (E->getBitField()) {  // C99 6.5.3.4p1. +  } else if (E->refersToBitField()) {  // C99 6.5.3.4p1.      Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;      isInvalid = true;    } else { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index de93adb6be1..9e8936e17b8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3440,7 +3440,7 @@ convertQualifiersAndValueKindIfNecessary(Sema &S,                                           Qualifiers T1Quals,                                           Qualifiers T2Quals,                                           bool IsLValueRef) { -  bool IsNonAddressableType = Initializer->getBitField() || +  bool IsNonAddressableType = Initializer->refersToBitField() ||                                Initializer->refersToVectorElement();    if (IsNonAddressableType) { @@ -5225,13 +5225,18 @@ InitializationSequence::Perform(Sema &S,      }      case SK_BindReference: -      if (FieldDecl *BitField = CurInit.get()->getBitField()) { -        // References cannot bind to bit fields (C++ [dcl.init.ref]p5). +      // References cannot bind to bit-fields (C++ [dcl.init.ref]p5). +      if (CurInit.get()->refersToBitField()) { +        // We don't necessarily have an unambiguous source bit-field. +        FieldDecl *BitField = CurInit.get()->getSourceBitField();          S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)            << Entity.getType().isVolatileQualified() -          << BitField->getDeclName() +          << (BitField ? BitField->getDeclName() : DeclarationName()) +          << (BitField != NULL)            << CurInit.get()->getSourceRange(); -        S.Diag(BitField->getLocation(), diag::note_bitfield_decl); +        if (BitField) +          S.Diag(BitField->getLocation(), diag::note_bitfield_decl); +          return ExprError();        } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index c11a0756e70..529ba127cba 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1837,7 +1837,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {    // conversion.    using llvm::APSInt;    if (From) -    if (FieldDecl *MemberDecl = From->getBitField()) { +    if (FieldDecl *MemberDecl = From->getSourceBitField()) {        APSInt BitWidth;        if (FromType->isIntegralType(Context) &&            MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp index 51d61a52a67..263f661208c 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -38,3 +38,26 @@ namespace PR6066 {      return 0;    }  } + +namespace test3 { +  struct A { +    unsigned bitX : 4; // expected-note 4 {{bit-field is declared here}} +    unsigned bitY : 4; // expected-note {{bit-field is declared here}} +    unsigned var; + +    void foo(); +  }; + +  void test(A *a) { +    unsigned &t0 = a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} +    unsigned &t1 = (unsigned&) a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} +    unsigned &t2 = const_cast<unsigned&>(a->bitX); // expected-error {{const_cast from bit-field lvalue to reference type 'unsigned int &'}} +    unsigned &t3 = (a->foo(), a->bitX); // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} +    unsigned &t4 = (a->var ? a->bitX : a->bitY); // expected-error {{non-const reference cannot bind to bit-field}} +    unsigned &t5 = (a->var ? a->bitX : a->bitX); // expected-error {{non-const reference cannot bind to bit-field}} +    unsigned &t6 = (a->var ? a->bitX : a->var); // expected-error {{non-const reference cannot bind to bit-field}} +    unsigned &t7 = (a->var ? a->var : a->bitY); // expected-error {{non-const reference cannot bind to bit-field}} +    unsigned &t8 = (a->bitX = 3); // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} +    unsigned &t9 = (a->bitY += 3); // expected-error {{non-const reference cannot bind to bit-field 'bitY'}} +  } +} diff --git a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp index be898761faf..76ea96fe14a 100644 --- a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp +++ b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp @@ -1,5 +1,4 @@  // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// expected-no-diagnostics  // The result of the expression const_cast<T>(v) is of type T. If T is  // an lvalue reference to object type, the result is an lvalue; if T @@ -16,3 +15,19 @@ void test_classification(const int *ptr) {    int *ptr1 = const_cast<int *&&>(xvalue<const int*>());    int *ptr2 = const_cast<int *&&>(prvalue<const int*>());  } + +struct A { +  volatile unsigned ubf : 4; +  volatile unsigned uv; +  volatile int sv; +  void foo(); +  bool pred(); +}; + +void test(A &a) { +  unsigned &t0 = const_cast<unsigned&>(a.ubf); // expected-error {{const_cast from bit-field lvalue to reference type}} +  unsigned &t1 = const_cast<unsigned&>(a.foo(), a.ubf); // expected-error {{const_cast from bit-field lvalue to reference type}} +  unsigned &t2 = const_cast<unsigned&>(a.pred() ? a.ubf : a.ubf); // expected-error {{const_cast from bit-field lvalue to reference type}} +  unsigned &t3 = const_cast<unsigned&>(a.pred() ? a.ubf : a.uv); // expected-error {{const_cast from bit-field lvalue to reference type}} +  unsigned &t4 = const_cast<unsigned&>(a.pred() ? a.ubf : a.sv); // expected-error {{const_cast from rvalue to reference type}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp new file mode 100644 index 00000000000..6a59e3d7ae5 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { +  unsigned bitX : 4; +  unsigned bitY : 4; +  unsigned var; + +  void foo(); +}; + +void test(A *a) { +  int x; +  x = sizeof(a->bitX); // expected-error {{invalid application of 'sizeof' to bit-field}} +  x = sizeof((unsigned) a->bitX); +  x = sizeof(a->foo(), a->bitX); // expected-error {{invalid application of 'sizeof' to bit-field}} +  x = sizeof(a->var ? a->bitX : a->bitY); // expected-error {{invalid application of 'sizeof' to bit-field}} +  x = sizeof(a->var ? a->bitX : a->bitX); // expected-error {{invalid application of 'sizeof' to bit-field}} +  x = sizeof(a->bitX = 3); // expected-error {{invalid application of 'sizeof' to bit-field}} +  x = sizeof(a->bitY += 3); // expected-error {{invalid application of 'sizeof' to bit-field}} +} diff --git a/clang/test/Sema/bitfield.c b/clang/test/Sema/bitfield.c index a1ce894037f..ab05a7773d9 100644 --- a/clang/test/Sema/bitfield.c +++ b/clang/test/Sema/bitfield.c @@ -39,3 +39,18 @@ int y;  struct PR8025 {    double : 2; // expected-error{{anonymous bit-field has non-integral type 'double'}}  }; + +struct Test4 { +  unsigned bitX : 4; +  unsigned bitY : 4; +  unsigned var; +}; +void test4(struct Test4 *t) { +  (void) sizeof(t->bitX); // expected-error {{invalid application of 'sizeof' to bit-field}} +  (void) sizeof((t->bitY)); // expected-error {{invalid application of 'sizeof' to bit-field}} +  (void) sizeof(t->bitX = 4); // not a bitfield designator in C +  (void) sizeof(t->bitX += 4); // not a bitfield designator in C +  (void) sizeof((void) 0, t->bitX); // not a bitfield designator in C +  (void) sizeof(t->var ? t->bitX : t->bitY); // not a bitfield designator in C +  (void) sizeof(t->var ? t->bitX : t->bitX); // not a bitfield designator in C +} diff --git a/clang/test/SemaObjCXX/references.mm b/clang/test/SemaObjCXX/references.mm index f63e17d98ef..fa552076fb9 100644 --- a/clang/test/SemaObjCXX/references.mm +++ b/clang/test/SemaObjCXX/references.mm @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -verify -emit-llvm -o - %s -// expected-no-diagnostics +// RUN: %clang_cc1 -verify -o - %s + +__attribute__((objc_root_class)) +@interface Root @end  // Test reference binding. @@ -8,7 +10,7 @@ typedef struct {    int f1;  } T; -@interface A +@interface A : Root  @property (assign) T p0;  @property (assign) T& p1;   @end @@ -61,3 +63,14 @@ void f6(baz* x) {    f5d(ToBar());    (void)((foo&)ToBar());  } + +// rdar://13794269 +@interface B : Root @end +@implementation B { +  unsigned bf : 4; // expected-note {{declared here}} +} + +- (void) foo { +  unsigned &i = bf; // expected-error {{non-const reference cannot bind to bit-field 'bf'}} +} +@end  | 

