diff options
author | Bernhard Schommer <bernhardschommer@gmail.com> | 2017-01-20 10:55:26 +0100 |
---|---|---|
committer | Bernhard Schommer <bernhardschommer@gmail.com> | 2017-01-20 10:55:26 +0100 |
commit | 55937c177f90ecf0dea40c318d2f8d52fa69b55d (patch) | |
tree | 493a207959cd64f6b3419dc109d246df35b01e54 /cparser/Elab.ml | |
parent | efaf1cf1c47370ab23db190fc4c2c1f3ad05323e (diff) | |
download | compcert-55937c177f90ecf0dea40c318d2f8d52fa69b55d.tar.gz compcert-55937c177f90ecf0dea40c318d2f8d52fa69b55d.zip |
Implement offsetof via builtin.
The implementation of offsetof as macro in the form
((size_t) &((ty*) NULL)->member) has the problem that it cannot be
used everywhere were an integer constant expression is allowed,
for example in initiliazers of global variables and there is also
no check for the case that member is of bitifield type.
The new implementation adds a builtin function for this which is
replaced by an integer constant during elaboration.
Bug 20765
Diffstat (limited to 'cparser/Elab.ml')
-rw-r--r-- | cparser/Elab.ml | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/cparser/Elab.ml b/cparser/Elab.ml index 1bfc2d11..d8d1d7d2 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -1642,6 +1642,22 @@ let elab_expr vararg loc env a = error "invalid application of 'alignof' to an incomplete type %a" (print_typ env) ty; { edesc = EAlignof ty; etyp = TInt(size_t_ikind(), []) },env' + | BUILTIN_OFFSETOF ((spec,dcl), mem) -> + let (ty,env) = elab_type loc env spec dcl in + let offset = + match unroll env ty with + | TStruct(id, attrs) -> + if Cutil.incomplete_type env ty then + error "offsetof of incomplete type %a" (print_typ env) ty; + let fld = (wrap Env.find_struct_member loc env (id,mem)) in + if List.exists (fun fld -> fld.fld_bitfield <> None) fld then + error "cannot compute the offset of bitfield '%s" mem; + Cutil.offsetof env ty fld + | _ -> + error "request offsetof for member '%s' in something not a structure" mem in + let offsetof_const = EConst (CInt(Int64.of_int offset,size_t_ikind (),"")) in + { edesc = offsetof_const; etyp = TInt(size_t_ikind(), []) },env + | UNARY(PLUS, a1) -> let b1,env = elab env a1 in if not (is_arith_type env b1.etyp) then |