]> granicus.if.org Git - clang/commitdiff
Add diagnostics for bitfields.
authorAnders Carlsson <andersca@mac.com>
Sat, 6 Dec 2008 20:33:04 +0000 (20:33 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 6 Dec 2008 20:33:04 +0000 (20:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60628 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/Sema/bitfield.c [new file with mode: 0644]

index 0fcc4d9385b947d42dcbefe1d19a20e6f1734679..933993be56f7eaffa4bee412df32fbdf61f8e0eb 100644 (file)
@@ -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'")
index b396e1c185b3e967a4804071d42325e06a061d89..a9ad257e41b4b8a41707f0d237bbc2229db7edcf 100644 (file)
@@ -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:
index e581b100dcc884560555c8321d8f3362825a419f..0738f55ff2bd5224876f1d96845ba2888cdd71f4 100644 (file)
@@ -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 (file)
index 0000000..9b0d6a1
--- /dev/null
@@ -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); 
+};