From 9d5d60ff8d7991234abcc6a9fe9903db930be0a1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 28 Apr 2010 22:36:06 +0000 Subject: [PATCH] Diagnose __builtin_offsetof expressions that refer to bit-fields git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102548 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 1 + lib/Sema/SemaExpr.cpp | 28 +++++++++++++++++++--- test/Sema/offsetof.c | 10 +++++++- test/SemaCXX/offsetof.cpp | 8 +++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index fdd602bb7a..5c5e2c8ebf 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; +def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">; def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6d5749b0e8..a23f32afa0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(MemberDecl->getDeclContext())-> - isAnonymousStructOrUnion()) { + isAnonymousStructOrUnion()) { llvm::SmallVector 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(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) { diff --git a/test/Sema/offsetof.c b/test/Sema/offsetof.c index 49d4eb43e4..cf88465e53 100644 --- a/test/Sema/offsetof.c +++ b/test/Sema/offsetof.c @@ -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'}} diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp index a1d907ab36..4be97a948f 100644 --- a/test/SemaCXX/offsetof.cpp +++ b/test/SemaCXX/offsetof.cpp @@ -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'}} -- 2.40.0