aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cfrontend/C2C.ml4
-rw-r--r--cparser/Cutil.ml131
-rw-r--r--cparser/Cutil.mli7
-rw-r--r--cparser/Elab.ml52
-rw-r--r--cparser/PackedStructs.ml44
-rw-r--r--test/regression/Results/packedstruct1-3212
-rw-r--r--test/regression/Results/packedstruct1-6412
-rw-r--r--test/regression/packedstruct1.c42
8 files changed, 202 insertions, 102 deletions
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index ce1f2c0e..ecaffbc6 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -610,9 +610,11 @@ let convertField env f =
(intern_string f.fld_name, convertTyp env f.fld_typ)
let convertCompositedef env su id attr members =
+ if Cutil.find_custom_attributes ["packed";"__packed__"] attr <> [] then
+ unsupported "packed struct (consider adding option -fpacked-structs)";
let t = match su with
| C.Struct ->
- let layout = Cutil.struct_layout env members in
+ let layout = Cutil.struct_layout env attr members in
List.iter (fun (a,b) -> Debug.set_member_offset id a b) layout;
TStruct (id,attr)
| C.Union -> TUnion (id,attr) in
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index 4d97823a..3e2dff36 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -267,6 +267,18 @@ let alignas_attribute al =
| a :: al -> alignas_attr accu al
in alignas_attr 0 al
+(* Extracting struct packing parameters from a set of attributes.
+ Assume the parameters were checked earlier, e.g. alignments are
+ either 0 or powers of two. *)
+
+let packing_parameters al =
+ match find_custom_attributes ["packed";"__packed__"] al with
+ | [[]] -> (1, 0, false)
+ | [[AInt n]] -> (Int64.to_int n, 0, false)
+ | [[AInt n; AInt p]] -> (Int64.to_int n, Int64.to_int p, false)
+ | [[AInt n; AInt p; AInt q]] -> (Int64.to_int n, Int64.to_int p, q = 1L)
+ | _ -> (0, 0, false)
+
(* Type compatibility *)
exception Incompat
@@ -461,7 +473,10 @@ let rec alignof env t =
let ci = Env.find_union env name in ci.ci_alignof
| TEnum(_, _) -> Some(alignof_ikind enum_ikind)
-(* Compute the natural alignment of a struct or union. *)
+(* Compute the natural alignment of a struct or union.
+ Not done here but in composite_info_decl: taking into account
+ the packing parameters (max-field-alignment, min-struct-alignment)
+ and the alignas attributes. *)
let alignof_struct_union env members =
let rec align_rec al = function
@@ -530,7 +545,7 @@ let rec sizeof env t =
(* Compute the size of a union.
It is the size is the max of the sizes of fields.
- Not done here but in composite_info_decl: rounding size to alignment. *)
+ Not done here but in composite_info_def: rounding size to alignment. *)
let sizeof_union env members =
let rec sizeof_rec sz = function
@@ -543,69 +558,66 @@ let sizeof_union env members =
end
in sizeof_rec 0 members
-(* Compute the size of a struct.
+(* Compute the size of a struct and the byte offset of the members.
We lay out fields consecutively, inserting padding to preserve
their alignment.
- Not done here but in composite_info_decl: rounding size to alignment. *)
-let sizeof_struct env members =
- let rec sizeof_rec ofs = function
+ The [ma] parameter is the maximal alignment for each member.
+ It is used for packed structs. If [ma = 0], it is ignored.
+ Bitfields are taken into account for the size and offset computations
+ but not given an offset.
+ Not done here but in composite_info_def: rounding size to alignment. *)
+let sizeof_layout_struct env members ma =
+ let align_offset ofs a =
+ align ofs (if ma > 0 && a > ma then ma else a) in
+ let rec sizeof_rec ofs accu = function
| [] ->
- Some ofs
+ Some (ofs, accu)
| [ { fld_typ = TArray(_, None, _) } as m ] ->
(* C99: ty[] allowed as last field *)
begin match alignof env m.fld_typ with
- | Some a -> Some (align ofs a)
+ | Some a ->
+ let ofs = align_offset ofs a in
+ Some (ofs, (m.fld_name, ofs) :: accu)
| None -> None
end
| m :: rem as ml ->
if m.fld_bitfield = None then begin
match alignof env m.fld_typ, sizeof env m.fld_typ with
- | Some a, Some s -> sizeof_rec (align ofs a + s) rem
+ | Some a, Some s ->
+ let ofs = align_offset ofs a in
+ sizeof_rec (ofs + s) ((m.fld_name, ofs) :: accu) rem
| _, _ -> None
end else begin
let (s, a, ml') = pack_bitfields ml in
- sizeof_rec (align ofs a + s) ml'
+ sizeof_rec (align_offset ofs a + s) accu ml'
end
- in sizeof_rec 0 members
+ in sizeof_rec 0 [] members
+
+let sizeof_struct env members ma =
+ match sizeof_layout_struct env members ma with
+ | None -> None
+ | Some(sz, offsets) -> Some sz
+
+(* Compute the offsets of all non-bitfield members of a struct. *)
+let struct_layout env attrs members =
+ let (ma, _, _) = packing_parameters attrs in
+ match sizeof_layout_struct env members ma with
+ | Some(sz, offsets) -> offsets
+ | None -> []
(* Compute the offset of a struct member *)
let offsetof env ty field =
- let rec sub acc name = function
- | [] -> List.rev acc
- | m::rem -> if m.fld_name = name then
- List.rev acc
- else
- sub (m::acc) name rem in
match unroll env ty with
- | TStruct (id,_) ->
+ | TStruct (id, _) ->
let str = Env.find_struct env id in
- let pre = sub [] field.fld_name str.ci_members in
- begin match sizeof_struct env pre, alignof env field.fld_typ with
- | Some s, Some a ->
- align s a
- | _ -> assert false end
- | TUnion _ -> 0
- | _ -> assert false
-
-(* Simplified version to compute offsets on structs without bitfields *)
-let struct_layout env members =
- let rec struct_layout_rec mem ofs = function
- | [] ->
- mem
- | [ { fld_typ = TArray(_, None, _) } as m ] ->
- (* C99: ty[] allowed as last field *)
- begin match alignof env m.fld_typ with
- | Some a -> ( m.fld_name,align ofs a)::mem
- | None -> []
+ let offsets = struct_layout env str.ci_attr str.ci_members in
+ begin try
+ List.assoc field.fld_name offsets
+ with Not_found ->
+ raise (Env.Error(No_member(id.C.name, "struct", field.fld_name)))
end
- | m :: rem ->
- match alignof env m.fld_typ, sizeof env m.fld_typ with
- | Some a, Some s ->
- let offset = align ofs a in
- struct_layout_rec ((m.fld_name,offset)::mem) (offset + s) rem
- | _, _ -> []
- in struct_layout_rec [] 0 members
-
+ | TUnion _ -> 0
+ | _ -> assert false
(* Determine whether a type is incomplete *)
@@ -625,12 +637,35 @@ let composite_info_decl su attr =
ci_attr = attr }
let composite_info_def env su attr m =
+ let (max_field_align, min_struct_align, swapped) = packing_parameters attr in
+ let attr_align = alignas_attribute attr in
+ let natural_align = alignof_struct_union env m in
let al =
- let a = alignas_attribute attr in
- if a > 0 then Some a else alignof_struct_union env m
- and sz =
+ (* alignas takes precedence over packing *)
+ if attr_align > 0 then Some attr_align
+ (* ignore packing on unions for compatibility with earlier versions *)
+ else if su = Union then natural_align
+ else begin
+ match natural_align with
+ | None -> None
+ | Some a ->
+ (* If max_field_align is given, reduce natural alignment a
+ to be at most max_field_align *)
+ let a =
+ if max_field_align > 0 && a > max_field_align
+ then max_field_align
+ else a in
+ (* If min_struct_align is given, increase alignment a
+ to be at least min_struct_align *)
+ let a =
+ if min_struct_align > 0 && a < min_struct_align
+ then min_struct_align
+ else a in
+ Some a
+ end in
+ let sz =
match su with
- | Struct -> sizeof_struct env m
+ | Struct -> sizeof_struct env m max_field_align
| Union -> sizeof_union env m
in
{ ci_kind = su; ci_members = m;
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index fb875b0d..5ae5dcd7 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -36,6 +36,11 @@ val incl_attributes : attributes -> attributes -> bool
val alignas_attribute : attributes -> int
(* Extract the value of the [_Alignas] attributes, if any.
Return 0 if none, a (positive) power of two alignment if some. *)
+val packing_parameters : attributes -> int * int * bool
+ (* Extract the value of the [__packed__] attributes, if any.
+ Return a triple
+ (maximum field alignment, minimum struct alignment, byte swapping).
+ Alignments of 0 mean default alignment. *)
val find_custom_attributes : string list -> attributes -> attr_arg list list
(* Extract arguments of custom [Attr] attributes whose names appear
in the given list of names. *)
@@ -127,7 +132,7 @@ val composite_info_decl:
val composite_info_def:
Env.t -> struct_or_union -> attributes -> field list -> Env.composite_info
val struct_layout:
- Env.t -> field list -> (string * int) list
+ Env.t -> attributes -> field list -> (string * int) list
val offsetof:
Env.t -> typ -> field -> int
(* Compute the offset of a struct member *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 173d3e03..5f785c04 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -495,36 +495,54 @@ let elab_gcc_attr loc env = function
let is_power_of_two n = n > 0L && Int64.logand n (Int64.pred n) = 0L
-let extract_alignas loc a =
+(* Check alignment parameter *)
+let check_alignment loc n =
+ if not (is_power_of_two n || n = 0L) then begin
+ error loc "requested alignment %Ld is not a power of 2" n; false
+ end else
+ if n <> Int64.of_int (Int64.to_int n) then begin
+ error loc "requested alignment %Ld is too large" n; false
+ end else
+ true
+
+(* Process GCC attributes that have special significance. Currently we
+ have two: "aligned" and "packed". *)
+let enter_gcc_attr loc a =
match a with
| Attr(("aligned"|"__aligned__"), args) ->
begin match args with
- | [AInt n] when is_power_of_two n || n = 0L -> AAlignas (Int64.to_int n)
- | [AInt n] -> error loc "requested alignment is not a power of 2"; a
- | [_] -> error loc "requested alignment is not an integer constant"; a
- | [] -> a (* Use the default alignment as the gcc does *)
- | _ -> error loc "'aligned' attribute takes no more than 1 argument"; a
+ | [AInt n] ->
+ if check_alignment loc n then [AAlignas (Int64.to_int n)] else []
+ | [_] -> error loc "requested alignment is not an integer constant"; []
+ | [] -> [] (* Use default alignment, like gcc does *)
+ | _ -> error loc "'aligned' attribute takes no more than 1 argument"; []
end
- | _ -> a
+ | Attr(("packed"|"__packed__"), args) ->
+ begin match args with
+ | [] -> [a]
+ | [AInt n] -> if check_alignment loc n then [a] else []
+ | [AInt n; AInt p] ->
+ if check_alignment loc n && check_alignment loc p then [a] else []
+ | [AInt n; AInt p; AInt q] ->
+ if check_alignment loc n && check_alignment loc p then [a] else []
+ | _ -> error loc "ill-formed 'packed' attribute"; []
+ end
+ | _ -> [a]
let elab_attribute env = function
| GCC_ATTR (l, loc) ->
List.fold_left add_attributes []
- (List.map (fun attr -> [attr])
- (List.map (extract_alignas loc)
- (List.flatten
- (List.map (elab_gcc_attr loc env) l))))
+ (List.map (enter_gcc_attr loc)
+ (List.flatten
+ (List.map (elab_gcc_attr loc env) l)))
| PACKED_ATTR (args, loc) ->
- [Attr("__packed__", List.map (elab_attr_arg loc env) args)]
+ enter_gcc_attr loc
+ (Attr("__packed__", List.map (elab_attr_arg loc env) args))
| ALIGNAS_ATTR ([a], loc) ->
warning loc Celeven_extension "'_Alignas' is a C11 extension";
begin match elab_attr_arg loc env a with
| AInt n ->
- if is_power_of_two n || n = 0L then
- [AAlignas (Int64.to_int n)]
- else begin
- error loc "requested alignment is not a power of 2"; []
- end
+ if check_alignment loc n then [AAlignas (Int64.to_int n)] else []
| _ -> error loc "requested alignment is not an integer constant"; []
| exception Wrong_attr_arg -> error loc "bad _Alignas value"; []
end
diff --git a/cparser/PackedStructs.ml b/cparser/PackedStructs.ml
index e1287eb8..a2c91c0a 100644
--- a/cparser/PackedStructs.ml
+++ b/cparser/PackedStructs.ml
@@ -81,47 +81,33 @@ let transf_field_decl mfa swapped loc env struct_id f =
(* Rewriting struct declarations *)
let transf_struct_decl mfa msa swapped loc env struct_id attrs ml =
+ let attrs' =
+ remove_custom_attributes ["packed";"__packed__"] attrs in
let ml' =
List.map (transf_field_decl mfa swapped loc env struct_id) ml in
- if msa = 0 then (attrs, ml') else begin
- let al' = (* natural alignment of the transformed struct *)
- List.fold_left
- (fun a f' -> max a (safe_alignof loc env f'.fld_typ))
- 1 ml' in
- (set_alignas_attr (max msa al') attrs, ml')
+ if msa = 0 then (attrs', ml') else begin
+ (* [Cutil.composite_info_def] takes packing parameters into account.
+ Hence the alignment it returns is the correct alignment for
+ the transformed struct. *)
+ let ci = Cutil.composite_info_def env Struct attrs ml in
+ match ci.ci_alignof with
+ | None -> error loc "incomplete struct"; (attrs', ml')
+ | Some al -> (set_alignas_attr al attrs', ml')
end
(* Rewriting composite declarations *)
-let is_pow2 n = n > 0 && n land (n - 1) = 0
-
-let packed_param_value loc n =
- let m = Int64.to_int n in
- if n <> Int64.of_int m then
- (error loc "__packed__ parameter `%Ld' is too large" n; 0)
- else if m = 0 || is_pow2 m then
- m
- else
- (error loc "__packed__ parameter `%Ld' must be a power of 2" n; 0)
-
let transf_composite loc env su id attrs ml =
match su with
| Union -> (attrs, ml)
| Struct ->
let (mfa, msa, swapped) =
match find_custom_attributes ["packed";"__packed__"] attrs with
- | [] -> (0L, 0L, false)
- | [[]] -> (1L, 0L, false)
- | [[AInt n]] -> (n, 0L, false)
- | [[AInt n; AInt p]] -> (n, p, false)
- | [[AInt n; AInt p; AInt q]] -> (n, p, q <> 0L)
- | _ ->
- error loc "ill-formed or ambiguous __packed__ attribute";
- (0L, 0L, false) in
- let mfa = packed_param_value loc mfa in
- let msa = packed_param_value loc msa in
- let attrs' = remove_custom_attributes ["packed";"__packed__"] attrs in
- transf_struct_decl mfa msa swapped loc env id attrs' ml
+ | [] -> (0, 0, false)
+ | [_] -> Cutil.packing_parameters attrs
+ | _ -> error loc "multiple __packed__ attributes";
+ (0, 0, false) in
+ transf_struct_decl mfa msa swapped loc env id attrs ml
(* Accessor functions *)
diff --git a/test/regression/Results/packedstruct1-32 b/test/regression/Results/packedstruct1-32
index e4bca769..e7d1c296 100644
--- a/test/regression/Results/packedstruct1-32
+++ b/test/regression/Results/packedstruct1-32
@@ -1,25 +1,37 @@
sizeof(struct s1) = 14
+precomputed sizeof(struct s1) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s1 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s2) = 16
+precomputed sizeof(struct s2) = 16
&s2 mod 16 = 0
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s2 = {x = 57, y = -456, z = 3.14159}
sizeof(struct s3) = 31
+precomputed sizeof(struct s3) = 31
offsetof(s) = 29
+precomputed offsetof(s) = 29
s3 = {x = 123, y = 45678, z = 2147483649, v = -456, w = -1234567, p is ok, t = {111,222,333}, s = {'o','k'}}
sizeof(struct s4) = 16
+precomputed sizeof(struct s4) = 16
offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8
+precomputed offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8
s4 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s5) = 14
+precomputed sizeof(struct s5) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s5 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s6) = 14
+precomputed sizeof(struct s6) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s62 = {x = 123, y = -456, z = 3.14159}
diff --git a/test/regression/Results/packedstruct1-64 b/test/regression/Results/packedstruct1-64
index c2a8bcd2..d255595f 100644
--- a/test/regression/Results/packedstruct1-64
+++ b/test/regression/Results/packedstruct1-64
@@ -1,25 +1,37 @@
sizeof(struct s1) = 14
+precomputed sizeof(struct s1) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s1 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s2) = 16
+precomputed sizeof(struct s2) = 16
&s2 mod 16 = 0
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s2 = {x = 57, y = -456, z = 3.14159}
sizeof(struct s3) = 35
+precomputed sizeof(struct s3) = 35
offsetof(s) = 33
+precomputed offsetof(s) = 33
s3 = {x = 123, y = 45678, z = 2147483649, v = -456, w = -1234567, p is ok, t = {111,222,333}, s = {'o','k'}}
sizeof(struct s4) = 16
+precomputed sizeof(struct s4) = 16
offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8
+precomputed offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8
s4 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s5) = 14
+precomputed sizeof(struct s5) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s5 = {x = 123, y = -456, z = 3.14159}
sizeof(struct s6) = 14
+precomputed sizeof(struct s6) = 14
offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
+precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6
s62 = {x = 123, y = -456, z = 3.14159}
diff --git a/test/regression/packedstruct1.c b/test/regression/packedstruct1.c
index 8b138dd4..5d3e7124 100644
--- a/test/regression/packedstruct1.c
+++ b/test/regression/packedstruct1.c
@@ -2,8 +2,18 @@
#include <stdio.h>
+/* offsetof is the offset computed by the verified front-end (cfrontend/) */
#define offsetof(s,f) (int)&(((struct s *)0)->f)
+/* boffsetof is the offset computed by the elaborator (cparser/) */
+#define boffsetof(s,f) (int)__builtin_offsetof(struct s, f)
+
+/* szof is the size computed by the verified front-end (cfrontend/) */
+#define szof(s) (int) sizeof(struct s)
+
+/* bszof is the size computed by the elaborator (cparser/) */
+#define bszof(s) (int) sizeof(char [sizeof(struct s)])
+
/* Simple packing */
struct __packed__(1) s1 { unsigned short x; int y; double z; };
@@ -11,9 +21,12 @@ struct __packed__(1) s1 { unsigned short x; int y; double z; };
void test1(void)
{
struct s1 s1;
- printf("sizeof(struct s1) = %d\n", sizeof(struct s1));
+ printf("sizeof(struct s1) = %d\n", szof(s1));
+ printf("precomputed sizeof(struct s1) = %d\n", bszof(s1));
printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetof(s1,x), offsetof(s1,y), offsetof(s1,z));
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
+ boffsetof(s1,x), boffsetof(s1,y), boffsetof(s1,z));
s1.x = 123; s1.y = -456; s1.z = 3.14159;
printf("s1 = {x = %d, y = %d, z = %.5f}\n\n", s1.x, s1.y, s1.z);
}
@@ -28,10 +41,13 @@ struct s2 s2;
void test2(void)
{
- printf("sizeof(struct s2) = %d\n", sizeof(struct s2));
+ printf("sizeof(struct s2) = %d\n", szof(s2));
+ printf("precomputed sizeof(struct s2) = %d\n", bszof(s2));
printf("&s2 mod 16 = %d\n", ((int) &s2) & 0xF);
printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetof(s2,x), offsetof(s2,y), offsetof(s2,z));
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
+ boffsetof(s2,x), boffsetof(s2,y), boffsetof(s2,z));
s2.x = 12345; s2.y = -456; s2.z = 3.14159;
printf("s2 = {x = %d, y = %d, z = %.5f}\n\n", s2.x, s2.y, s2.z);
}
@@ -55,8 +71,10 @@ void test3(void)
{
char xx;
- printf("sizeof(struct s3) = %d\n", sizeof(struct s3));
+ printf("sizeof(struct s3) = %d\n", szof(s3));
+ printf("precomputed sizeof(struct s3) = %d\n", bszof(s3));
printf("offsetof(s) = %d\n", offsetof(s3,s));
+ printf("precomputed offsetof(s) = %d\n", boffsetof(s3,s));
s3.x = 123;
s3.y = 45678;
s3.z = 0x80000001U;
@@ -82,9 +100,13 @@ struct s4 { unsigned short x; int y; double z; };
void test4(void)
{
struct s4 s4;
- printf("sizeof(struct s4) = %d\n", sizeof(struct s4));
+
+ printf("sizeof(struct s4) = %d\n", szof(s4));
+ printf("precomputed sizeof(struct s4) = %d\n", bszof(s4));
printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetof(s4,x), offsetof(s4,y), offsetof(s4,z));
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
+ boffsetof(s4,x), boffsetof(s4,y), boffsetof(s4,z));
s4.x = 123; s4.y = -456; s4.z = 3.14159;
printf("s4 = {x = %d, y = %d, z = %.5f}\n\n", s4.x, s4.y, s4.z);
}
@@ -96,9 +118,13 @@ struct __attribute((packed)) s5 { unsigned short x; int y; double z; };
void test5(void)
{
struct s5 s5;
- printf("sizeof(struct s5) = %d\n", sizeof(struct s5));
+
+ printf("sizeof(struct s5) = %d\n", szof(s5));
+ printf("precomputed sizeof(struct s5) = %d\n", bszof(s5));
printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetof(s5,x), offsetof(s5,y), offsetof(s5,z));
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
+ boffsetof(s5,x), boffsetof(s5,y), boffsetof(s5,z));
s5.x = 123; s5.y = -456; s5.z = 3.14159;
printf("s5 = {x = %d, y = %d, z = %.5f}\n\n", s5.x, s5.y, s5.z);
}
@@ -110,9 +136,13 @@ struct s6 { unsigned short x; int y; double z; } __attribute((packed)) const s6
void test6(void)
{
struct s6 s62;
- printf("sizeof(struct s6) = %d\n", sizeof(struct s6));
+
+ printf("sizeof(struct s6) = %d\n", szof(s6));
+ printf("precomputed sizeof(struct s6) = %d\n", bszof(s6));
printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
offsetof(s6,x), offsetof(s6,y), offsetof(s6,z));
+ printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n",
+ boffsetof(s6,x), boffsetof(s6,y), boffsetof(s6,z));
s62.x = 123; s62.y = -456; s62.z = 3.14159;
printf("s62 = {x = %d, y = %d, z = %.5f}\n\n", s62.x, s62.y, s62.z);
}