Diagnose __builtin_offsetof expressions that refer to bit-fields

llvm-svn: 102548
This commit is contained in:
Douglas Gregor 2010-04-28 22:36:06 +00:00
parent 669064a772
commit 10982ea3f9
4 changed files with 43 additions and 4 deletions

View 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">,

View 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()) {

View 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'}}

View 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'}}