]> granicus.if.org Git - clang/commitdiff
Widen AST bitfields too small to represent all enumerators
authorReid Kleckner <rnk@google.com>
Mon, 13 Mar 2017 22:33:04 +0000 (22:33 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 13 Mar 2017 22:33:04 +0000 (22:33 +0000)
All of these were found by a new warning that I am prototyping,
-Wbitfield-enum-conversion.

Stmt::ExprBits::ObjectKind - This was not wide enough to represent
OK_ObjSubscript, so this was a real, true positive bug.

ObjCDeclSpec::objCDeclQualifier - On Windows, setting DQ_CSNullability
would cause the bitfield to become negative because enum types are
always implicitly 'int' there. This would probably never be noticed
because this is a flag-style enum, so we only ever test one bit at a
time. Switching to 'unsigned' also makes this type pack smaller on
Windows.

FunctionDecl::SClass - Technically, we only need two bits for all valid
function storage classes. Functions can never have automatic or register
storage class. This seems a bit too clever, and we have a bit to spare,
so widening the bitfield seems like the best way to pacify the warning.
You could classify this as a false positive, but widening the bitfield
defends us from invalid ASTs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@297680 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/Expr.h
include/clang/AST/Stmt.h
include/clang/Sema/DeclSpec.h

index cd6b8f7421853d2eca6bb0276b09c3b53191ec63..d1c77f5e080c5e1e58c53d959f78d8f71d56cd44 100644 (file)
@@ -1605,7 +1605,7 @@ private:
 
   // FIXME: This can be packed into the bitfields in DeclContext.
   // NOTE: VC++ packs bitfields poorly if the types differ.
-  unsigned SClass : 2;
+  unsigned SClass : 3;
   unsigned IsInline : 1;
   unsigned IsInlineSpecified : 1;
 protected:
index 56b99ccd89717282601250de767a86b7d6a079ce..a7ca03ff9e0ad0bfd108aa87ddc05d8b7b34cf69 100644 (file)
@@ -115,6 +115,7 @@ protected:
     ExprBits.InstantiationDependent = ID;
     ExprBits.ValueKind = VK;
     ExprBits.ObjectKind = OK;
+    assert(ExprBits.ObjectKind == OK && "truncated kind");
     ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
     setType(T);
   }
index 21043266f8be9df37d670315268c5c9e95634a04..c210bd1cec2e3cccfce9dd71da79bae183ab9fce 100644 (file)
@@ -127,13 +127,13 @@ protected:
     unsigned : NumStmtBits;
 
     unsigned ValueKind : 2;
-    unsigned ObjectKind : 2;
+    unsigned ObjectKind : 3;
     unsigned TypeDependent : 1;
     unsigned ValueDependent : 1;
     unsigned InstantiationDependent : 1;
     unsigned ContainsUnexpandedParameterPack : 1;
   };
-  enum { NumExprBits = 16 };
+  enum { NumExprBits = 17 };
 
   class CharacterLiteralBitfields {
     friend class CharacterLiteral;
@@ -350,6 +350,8 @@ protected:
 
 public:
   Stmt(StmtClass SC) {
+    static_assert(sizeof(*this) == sizeof(void *),
+                  "changing bitfields changed sizeof(Stmt)");
     static_assert(sizeof(*this) % alignof(void *) == 0,
                   "Insufficient alignment!");
     StmtBits.sClass = SC;
index 8303371598dad9669913f14efd9be19c393ee6d3..82f04a584b84de298f42b9eb086918596850ca11 100644 (file)
@@ -819,7 +819,9 @@ public:
     : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
       Nullability(0), GetterName(nullptr), SetterName(nullptr) { }
 
-  ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
+  ObjCDeclQualifier getObjCDeclQualifier() const {
+    return (ObjCDeclQualifier)objcDeclQualifier;
+  }
   void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
     objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
   }
@@ -869,7 +871,7 @@ private:
   // FIXME: These two are unrelated and mutually exclusive. So perhaps
   // we can put them in a union to reflect their mutual exclusivity
   // (space saving is negligible).
-  ObjCDeclQualifier objcDeclQualifier : 7;
+  unsigned objcDeclQualifier : 7;
 
   // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
   unsigned PropertyAttributes : 15;