]> granicus.if.org Git - clang/commitdiff
fix PR3607 and a fixme, by checking bitfield constraints
authorChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 22:45:59 +0000 (22:45 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 22:45:59 +0000 (22:45 +0000)
more consistently.

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

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

index 4d711f72133c9a3fc8616fef28d580b4c7824bd7..579a10fe35240c0cb67781dec38105a2ef250f65 100644 (file)
@@ -249,7 +249,7 @@ DIAG(err_not_bitfield_type, ERROR,
 DIAG(err_static_not_bitfield, ERROR,
      "static member %0 cannot be a bit-field")
 DIAG(err_not_integral_type_bitfield, ERROR,
-     "bit-field %0 with non-integral type")
+     "bit-field %0 has non-integral type")
 DIAG(err_member_initialization, ERROR,
     "%0 can only be initialized if it is a static const integral data member")
 DIAG(err_member_function_initialization, ERROR,
index d7d80638d19228d4102d99aef809474a04a35022..92bc0bc750e89974b6d513926f175ba0e314a9f7 100644 (file)
@@ -361,6 +361,10 @@ public:
                          llvm::SmallVectorImpl<DeclTy*> &Decls);
   virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
                              Declarator &D, ExprTy *BitfieldWidth);
+
+  FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
+                         Declarator &D, Expr *BitfieldWidth);
+
   
   virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
                             Declarator &D, ExprTy *BitfieldWidth,
index 97002ef02f0bd1e235a64edc46cc54764b92127f..f9c1691e853a56c5bead5a244ffb2f191ca93ca9 100644 (file)
@@ -2575,7 +2575,8 @@ void Sema::RecursiveCalcJumpScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
       }
     }
     if (isa<DeclStmt>(*i)) continue;
-    RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, ScopeStack, *i);
+    RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap,
+                            ScopeStack, *i);
   }
 
   while (ScopeStack.size() && PopScopeMap[ScopeStack.back()] == CurStmt) {
@@ -3150,7 +3151,14 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
 
 bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, 
                           QualType FieldTy, const Expr *BitWidth) {
-  // FIXME: 6.7.2.1p4 - verify the field type.
+  // C99 6.7.2.1p4 - verify the field 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;
+  }
   
   llvm::APSInt Value;
   if (VerifyIntegerConstantExpression(BitWidth, &Value))
@@ -3177,15 +3185,19 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
 Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
                                SourceLocation DeclStart, 
                                Declarator &D, ExprTy *BitfieldWidth) {
+  return HandleField(S, static_cast<RecordDecl*>(TagD), DeclStart, D,
+                     static_cast<Expr*>(BitfieldWidth));
+}
+
+/// HandleField - Analyze a field of a C struct or a C++ data member.
+///
+FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
+                             SourceLocation DeclStart,
+                             Declarator &D, Expr *BitWidth) {
   IdentifierInfo *II = D.getIdentifier();
-  Expr *BitWidth = (Expr*)BitfieldWidth;
   SourceLocation Loc = DeclStart;
-  RecordDecl *Record = (RecordDecl *)TagD;
   if (II) Loc = D.getIdentifierLoc();
   
-  // 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;
@@ -3210,8 +3222,11 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
   }
   
   if (BitWidth) {
-    if (VerifyBitField(Loc, II, T, BitWidth))
+    if (VerifyBitField(Loc, II, T, BitWidth)) {
       InvalidDecl = true;
+      DeleteExpr(BitWidth);
+      BitWidth = 0;
+    }
   } else {
     // Not a bitfield.
 
@@ -3290,8 +3305,11 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S,
   
   if (BitWidth) {
     // 6.7.2.1p3, 6.7.2.1p4
-    if (VerifyBitField(Loc, II, T, BitWidth))
+    if (VerifyBitField(Loc, II, T, BitWidth)) {
       InvalidDecl = true;
+      DeleteExpr(BitWidth);
+      BitWidth = 0;
+    }
   } else {
     // Not a bitfield.
     
@@ -3373,6 +3391,11 @@ void Sema::ActOnFields(Scope* S,
       // Remember all fields written by the user.
       RecFields.push_back(FD);
     }
+    
+    // If the field is already invalid for some reason, don't emit more
+    // diagnostics about it.
+    if (FD->isInvalidDecl())
+      continue;
       
     // C99 6.7.2.1p2 - A field may not be a function type.
     if (FDTy->isFunctionType()) {
@@ -3466,7 +3489,8 @@ void Sema::ActOnFields(Scope* S,
              IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
           ObjCIvarDecl* Ivar = (*IVI);
           IdentifierInfo *II = Ivar->getIdentifier();
-          ObjCIvarDecl* prevIvar = ID->getSuperClass()->lookupInstanceVariable(II);
+          ObjCIvarDecl* prevIvar =
+            ID->getSuperClass()->lookupInstanceVariable(II);
           if (prevIvar) {
             Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
             Diag(prevIvar->getLocation(), diag::note_previous_declaration);
index 3e8ee5ed1f706e5d72a4f3cc2551843e7e199a25..0e5adc46a2dcfac6fb51c26bff6273d3c17eca7a 100644 (file)
@@ -547,11 +547,15 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
   Decl *Member;
   bool InvalidDecl = false;
 
-  if (isInstField)
-    Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext), 
-                                           Loc, D, BitWidth));
-  else
+  if (isInstField) {
+    FieldDecl *FD = 
+      HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth);
+    // Refresh our notion of bitwidth.
+    BitWidth = FD->getBitWidth();
+    Member = FD;
+  } else {
     Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
+  }
 
   if (!Member) return LastInGroup;
 
index f3b285b12ed69222be9c753f931777bf84caece3..2e4df4765031ae08797be233d2c62e6551022de8 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: clang %s -fsyntax-only -verify 
+enum e0;
 
 struct a {
   int a : -1; // expected-error{{bit-field 'a' has negative width}}
@@ -11,4 +12,10 @@ struct a {
 
   // rdar://6138816
   int e : 0;  // expected-error {{bit-field 'e' has zero width}}
+
+  float xx : 4;  // expected-error {{bit-field 'xx' has non-integral type}}
+
+  // PR3607
+  enum e0 f : 1; // expected-error {{field has incomplete type 'enum e0'}}
 };
+
index 02608faa0f641d5de445397c9bc3f35756d2b5ec..08391c9ba1a30df190a0f6010f034298828d27db 100644 (file)
@@ -27,8 +27,8 @@ public:
   typedef int func();
   func tm;
   func *ptm;
-  func btm : 1; // expected-error {{error: bit-field 'btm' with non-integral type}}
-  NestedC bc : 1; // expected-error {{error: bit-field 'bc' with non-integral type}}
+  func btm : 1; // expected-error {{error: bit-field 'btm' has non-integral type}}
+  NestedC bc : 1; // expected-error {{error: bit-field 'bc' has non-integral type}}
 
   enum E1 { en1, en2 };