]> granicus.if.org Git - clang/commitdiff
Diagnose __builtin_offsetof expressions that refer to bit-fields
authorDouglas Gregor <dgregor@apple.com>
Wed, 28 Apr 2010 22:36:06 +0000 (22:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 28 Apr 2010 22:36:06 +0000 (22:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102548 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/offsetof.c
test/SemaCXX/offsetof.cpp

index fdd602bb7a242604c6bcd2012212fe192e10d7ed..5c5e2c8ebf01214023d6560573eea9bb81063193 100644 (file)
@@ -1817,6 +1817,7 @@ def ext_offsetof_extended_field_designator : Extension<
   "using extended field designator is an extension">;
 def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
   InGroup<InvalidOffsetof>;
+def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
 
 def warn_floatingpoint_eq : Warning<
   "comparing floating point with == or != is unsafe">,
index 6d5749b0e8d3e195ebd76b1d52794a4db415c5ff..a23f32afa04c9f48bb66f51234f45ac9ef65613d 100644 (file)
@@ -6718,10 +6718,20 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
                        << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, 
                                                               OC.LocEnd));
     
-    // FIXME: C99 Verify that MemberDecl isn't a bitfield.
-    
+    // C99 7.17p3:
+    //   (If the specified member is a bit-field, the behavior is undefined.)
+    //
+    // We diagnose this as an error.
+    if (MemberDecl->getBitWidth()) {
+      Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+        << MemberDecl->getDeclName()
+        << SourceRange(BuiltinLoc, RParenLoc);
+      Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+      return ExprError();
+    }
+      
     if (cast<RecordDecl>(MemberDecl->getDeclContext())->
-        isAnonymousStructOrUnion()) {
+                                                isAnonymousStructOrUnion()) {
       llvm::SmallVector<FieldDecl*, 4> Path;
       BuildAnonymousStructUnionMemberPath(MemberDecl, Path);
       unsigned n = Path.size();
@@ -6854,6 +6864,18 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
         return ExprError(Diag(BuiltinLoc, diag::err_no_member)
                          << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
       
+      // C99 7.17p3:
+      //   (If the specified member is a bit-field, the behavior is undefined.)
+      //
+      // We diagnose this as an error.
+      if (MemberDecl->getBitWidth()) {
+        Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+          << MemberDecl->getDeclName()
+          << SourceRange(BuiltinLoc, RPLoc);
+        Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+        return ExprError();
+      }
+      
       // FIXME: C++: Verify that MemberDecl isn't a static field.
       // FIXME: Verify that MemberDecl isn't a bitfield.
       if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
index 49d4eb43e42363fb52fccbe04a4481eef1ed1679..cf88465e535d0ea6ceb4438bd6d3bee9ff455cbf 100644 (file)
@@ -53,4 +53,12 @@ int x[__builtin_offsetof(union x, x)];
 struct incomplete; // expected-note 2 {{forward declaration of 'struct incomplete'}}
 int test1[__builtin_offsetof(struct incomplete, foo)]; // expected-error {{offsetof of incomplete type 'struct incomplete'}}
 
-int test1[__builtin_offsetof(struct incomplete[10], [4].foo)]; // expected-error {{array has incomplete element type 'struct incomplete'}}
+int test2[__builtin_offsetof(struct incomplete[10], [4].foo)]; // expected-error {{array has incomplete element type 'struct incomplete'}}
+
+// Bitfields
+struct has_bitfields {
+  int i : 7;
+  int j : 12; // expected-note{{bit-field is declared here}}
+};
+
+int test3 = __builtin_offsetof(struct has_bitfields, j); // expected-error{{cannot compute offset of bit-field 'j'}}
index a1d907ab360a877b8416cedd4b45c8c002016629..4be97a948f66f74c218ee094c781db0d0e4873c4 100644 (file)
@@ -28,3 +28,11 @@ void test_ice(int i) {
   int array0[__builtin_offsetof(HasArray, array[5])];
   int array1[__builtin_offsetof(HasArray, array[i])]; // expected-error{{variable length arrays are not permitted in C++}}
 }
+
+// Bitfields
+struct has_bitfields {
+  int i : 7;
+  int j : 12; // expected-note{{bit-field is declared here}}
+};
+
+int test3 = __builtin_offsetof(struct has_bitfields, j); // expected-error{{cannot compute offset of bit-field 'j'}}