]> granicus.if.org Git - clang/commitdiff
refactor C++ bitfield checking a bit (haha)
authorChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 23:01:03 +0000 (23:01 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 23:01:03 +0000 (23:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66213 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/class.cpp

index 579a10fe35240c0cb67781dec38105a2ef250f65..beefc02ef586c6a5d754e447657799093c2763e7 100644 (file)
@@ -244,10 +244,10 @@ DIAG(err_mutable_nonmember, ERROR,
      "'mutable' can only be applied to member variables")
 DIAG(err_virtual_non_function, ERROR,
      "'virtual' can only appear on non-static member functions")
-DIAG(err_not_bitfield_type, ERROR,
-     "cannot declare %0 to be a bit-field type")
 DIAG(err_static_not_bitfield, ERROR,
      "static member %0 cannot be a bit-field")
+DIAG(err_typedef_not_bitfield, ERROR,
+     "typedef member %0 cannot be a bit-field")
 DIAG(err_not_integral_type_bitfield, ERROR,
      "bit-field %0 has non-integral type")
 DIAG(err_member_initialization, ERROR,
index f9c1691e853a56c5bead5a244ffb2f191ca93ca9..953e39f92d62a23173087adc1f357647d28eeadd 100644 (file)
@@ -3152,12 +3152,14 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
 bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, 
                           QualType FieldTy, const Expr *BitWidth) {
   // C99 6.7.2.1p4 - verify the field type.
-
+  // C++ 9.6p3: A bit-field shall have integral or enumeration type.
   if (!FieldTy->isIntegralType()) {
     // Handle incomplete types with specific error.
     if (FieldTy->isIncompleteType())
-      return Diag(FieldLoc, diag::err_field_incomplete) << FieldTy;
-    return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName;
+      return Diag(FieldLoc, diag::err_field_incomplete)
+        << FieldTy << BitWidth->getSourceRange();
+    return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
+      << FieldName << BitWidth->getSourceRange();
   }
   
   llvm::APSInt Value;
index 0e5adc46a2dcfac6fb51c26bff6273d3c17eca7a..178853e5ccf89039a6613b9dacd3d9262f43b2e1 100644 (file)
@@ -545,8 +545,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                       !isFunc);
 
   Decl *Member;
-  bool InvalidDecl = false;
-
   if (isInstField) {
     FieldDecl *FD = 
       HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth);
@@ -555,6 +553,31 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
     Member = FD;
   } else {
     Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
+
+    // Non-instance-fields can't have a bitfield.
+    if (BitWidth) {
+      if (Member->isInvalidDecl()) {
+        // don't emit another diagnostic.
+      } else if (isa<CXXClassVarDecl>(Member)) {
+        // C++ 9.6p3: A bit-field shall not be a static member.
+        // "static member 'A' cannot be a bit-field"
+        Diag(Loc, diag::err_static_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else if (isa<TypedefDecl>(Member)) {
+        // "typedef member 'x' cannot be a bit-field"
+        Diag(Loc, diag::err_typedef_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else {
+        // A function typedef ("typedef int f(); f a;").
+        // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+        Diag(Loc, diag::err_not_integral_type_bitfield)
+          << Name << BitWidth->getSourceRange();
+      }
+      
+      DeleteExpr(BitWidth);
+      BitWidth = 0;
+      Member->setInvalidDecl();
+    }
   }
 
   if (!Member) return LastInGroup;
@@ -579,7 +602,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   if (DS.isVirtualSpecified()) {
     if (!isFunc || DS.getStorageClassSpec() == DeclSpec::SCS_static) {
       Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function);
-      InvalidDecl = true;
+      Member->setInvalidDecl();
     } else {
       cast<CXXMethodDecl>(Member)->setVirtual();
       CXXRecordDecl *CurClass = cast<CXXRecordDecl>(CurContext);
@@ -593,50 +616,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   // also virtual if it overrides an already virtual function. This is important
   // to do here because it decides the validity of a pure specifier.
 
-  if (BitWidth) {
-    // C++ 9.6p2: Only when declaring an unnamed bit-field may the
-    // constant-expression be a value equal to zero.
-    // FIXME: Check this.
-
-    if (D.isFunctionDeclarator()) {
-      // FIXME: Emit diagnostic about only constructors taking base initializers
-      // or something similar, when constructor support is in place.
-      Diag(Loc, diag::err_not_bitfield_type)
-        << Name << BitWidth->getSourceRange();
-      InvalidDecl = true;
-
-    } else if (isInstField) {
-      // C++ 9.6p3: A bit-field shall have integral or enumeration type.
-      if (!cast<FieldDecl>(Member)->getType()->isIntegralType()) {
-        Diag(Loc, diag::err_not_integral_type_bitfield)
-          << Name << BitWidth->getSourceRange();
-        InvalidDecl = true;
-      }
-
-    } else if (isa<FunctionDecl>(Member)) {
-      // A function typedef ("typedef int f(); f a;").
-      // C++ 9.6p3: A bit-field shall have integral or enumeration type.
-      Diag(Loc, diag::err_not_integral_type_bitfield)
-        << Name << BitWidth->getSourceRange();
-      InvalidDecl = true;
-
-    } else if (isa<TypedefDecl>(Member)) {
-      // "cannot declare 'A' to be a bit-field type"
-      Diag(Loc, diag::err_not_bitfield_type)
-        << Name << BitWidth->getSourceRange();
-      InvalidDecl = true;
-
-    } else {
-      assert(isa<CXXClassVarDecl>(Member) &&
-             "Didn't we cover all member kinds?");
-      // C++ 9.6p3: A bit-field shall not be a static member.
-      // "static member 'A' cannot be a bit-field"
-      Diag(Loc, diag::err_static_not_bitfield)
-        << Name << BitWidth->getSourceRange();
-      InvalidDecl = true;
-    }
-  }
-
   if (Init) {
     // C++ 9.2p4: A member-declarator can contain a constant-initializer only
     // if it declares a static member of const integral or const enumeration
@@ -649,13 +628,13 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
           CVD->getType()->isIntegralType()) {
         // constant-initializer
         if (CheckForConstantInitializer(Init, CVD->getType()))
-          InvalidDecl = true;
+          Member->setInvalidDecl();
 
       } else {
         // not const integral.
         Diag(Loc, diag::err_member_initialization)
           << Name << Init->getSourceRange();
-        InvalidDecl = true;
+        Member->setInvalidDecl();
       }
 
     } else {
@@ -672,24 +651,21 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
           else {
             Diag(Loc, diag::err_non_virtual_pure)
               << Name << Init->getSourceRange();
-            InvalidDecl = true;
+            Member->setInvalidDecl();
           }
         } else {
           Diag(Loc, diag::err_member_function_initialization)
             << Name << Init->getSourceRange();
-          InvalidDecl = true;
+          Member->setInvalidDecl();
         }
       } else {
         Diag(Loc, diag::err_member_initialization)
           << Name << Init->getSourceRange();
-        InvalidDecl = true;
+        Member->setInvalidDecl();
       }
     }
   }
 
-  if (InvalidDecl)
-    Member->setInvalidDecl();
-
   if (isInstField) {
     FieldCollector->Add(cast<FieldDecl>(Member));
     return LastInGroup;
index 08391c9ba1a30df190a0f6010f034298828d27db..44ec70f07c211d9e57d4cd467ad16e44b0a7ee77 100644 (file)
@@ -20,7 +20,7 @@ public:
 
   int b : 1, w : 2;
   int : 1, : 2;
-  typedef int E : 1; // expected-error {{error: cannot declare 'E' to be a bit-field type}}
+  typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}}
   static int sb : 1; // expected-error {{error: static member 'sb' cannot be a bit-field}}
   static int vs;