From: Anders Carlsson Date: Sat, 6 Dec 2008 20:33:04 +0000 (+0000) Subject: Add diagnostics for bitfields. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f1e5727e36481d830e566ff5a016fda726838e4;p=clang Add diagnostics for bitfields. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60628 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 0fcc4d9385..933993be56 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1042,6 +1042,10 @@ DIAG(err_illegal_initializer_type, ERROR, "illegal initializer type %0") DIAG(err_implicit_empty_initializer, ERROR, "initializer for aggregate with no elements requires explicit braces") +DIAG(err_bitfield_has_negative_width, ERROR, + "bit-field %0 has negative width") +DIAG(err_bitfield_width_exceeds_type_size, ERROR, + "size of bit-field %0 exceeds size of its type (%1 bits)") DIAG(err_redefinition_of_label, ERROR, "redefinition of label '%0'") diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b396e1c185..a9ad257e41 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1384,8 +1384,14 @@ public: /// VerifyIntegerConstantExpression - verifies that an expression is an ICE, /// and reports the appropriate diagnostics. Returns false on success. /// Can optionally return the value of the expression. - bool VerifyIntegerConstantExpression(const Expr*E, llvm::APSInt *Result = 0); + bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0); + /// VerifyBitField - verifies that a bit field expression is an ICE and has + /// the correct width, and that the field type is valid. + /// Returns false on success. + bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, const Expr *BitWidth); + //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system private: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e581b100dc..0738f55ff2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2599,6 +2599,31 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, return QualType(); } +bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, const Expr *BitWidth) +{ + // FIXME: 6.7.2.1p4 - verify the field type. + + llvm::APSInt Value; + if (VerifyIntegerConstantExpression(BitWidth, &Value)) + return true; + + if (Value.isNegative()) { + Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName; + return true; + } + + uint64_t TypeSize = Context.getTypeSize(FieldTy); + // FIXME: We won't need the 0 size once we check that the field type is valid. + if (TypeSize && Value.getZExtValue() > TypeSize) { + Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) << + FieldName << (unsigned)TypeSize; + return true; + } + + return false; +} + /// ActOnField - Each field of a struct/union/class is passed into this in order /// to create a FieldDecl object for it. Sema::DeclTy *Sema::ActOnField(Scope *S, @@ -2611,25 +2636,11 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, // FIXME: Unnamed fields can be handled in various different ways, for // example, unnamed unions inject all members into the struct namespace! - - if (BitWidth) { - // TODO: Validate. - //printf("WARNING: BITFIELDS IGNORED!\n"); - - // 6.7.2.1p3 - // 6.7.2.1p4 - - } else { - // Not a bitfield. - // validate II. - - } - QualType T = GetTypeForDeclarator(D, S); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); bool InvalidDecl = false; - + // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (T->isVariablyModifiedType()) { @@ -2643,6 +2654,17 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, InvalidDecl = true; } } + + if (BitWidth) { + if (VerifyBitField(Loc, II, T, BitWidth)) + InvalidDecl = true; + } else { + // Not a bitfield. + + // validate II. + + } + // FIXME: Chain fielddecls together. FieldDecl *NewFD; @@ -2692,6 +2714,9 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S, // FIXME: Unnamed fields can be handled in various different ways, for // example, unnamed unions inject all members into the struct namespace! + QualType T = GetTypeForDeclarator(D, S); + assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + bool InvalidDecl = false; if (BitWidth) { // TODO: Validate. @@ -2707,10 +2732,6 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S, } - QualType T = GetTypeForDeclarator(D, S); - assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); - bool InvalidDecl = false; - // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (T->isVariablyModifiedType()) { diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c new file mode 100644 index 0000000000..9b0d6a1fbd --- /dev/null +++ b/test/Sema/bitfield.c @@ -0,0 +1,8 @@ +// RUN: clang %s -fsyntax-only -verify + +struct a { + int a : -1; // expected-error{{bit-field 'a' has negative width}} + int b : 33; // expected-error{{size of bit-field 'b' exceeds size of its type (32 bits)}} + int c : (1 + 0.25); // expected-error{{expression is not an integer constant expression}} + int d : (int)(1 + 0.25); +};