From: Reid Kleckner Date: Mon, 13 Mar 2017 22:33:04 +0000 (+0000) Subject: Widen AST bitfields too small to represent all enumerators X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45f9ba4c344ade4f485f72f32c20d84bff648192;p=clang Widen AST bitfields too small to represent all enumerators 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 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index cd6b8f7421..d1c77f5e08 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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: diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 56b99ccd89..a7ca03ff9e 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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); } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 21043266f8..c210bd1cec 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -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; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 8303371598..82f04a584b 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -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;