aboutsummaryrefslogtreecommitdiffstats
path: root/cparser
diff options
context:
space:
mode:
authorCyril SIX <cyril.six@kalray.eu>2019-03-13 13:07:24 +0100
committerCyril SIX <cyril.six@kalray.eu>2019-03-13 13:07:24 +0100
commit41c895850f75e3084fc8efdb7c9b1f7c8ec4fa5d (patch)
tree3126fa4af7ba97dbc4f4f841a81820c95a2e35a3 /cparser
parent8f972659841ad38f6f548161b5ca3cfcbdd135cb (diff)
parent72ba1c282e2a8bfd0e826352a251fa71bfb71e05 (diff)
downloadcompcert-kvx-41c895850f75e3084fc8efdb7c9b1f7c8ec4fa5d.tar.gz
compcert-kvx-41c895850f75e3084fc8efdb7c9b1f7c8ec4fa5d.zip
Merge branch 'master' into mppa_postpass
Conflicts: .gitignore runtime/include/stdbool.h
Diffstat (limited to 'cparser')
-rw-r--r--cparser/Checks.ml9
-rw-r--r--cparser/Cutil.ml38
-rw-r--r--cparser/Cutil.mli9
-rw-r--r--cparser/Elab.ml51
-rw-r--r--cparser/PackedStructs.ml8
5 files changed, 88 insertions, 27 deletions
diff --git a/cparser/Checks.ml b/cparser/Checks.ml
index 62d85c1b..a30cde7d 100644
--- a/cparser/Checks.ml
+++ b/cparser/Checks.ml
@@ -18,19 +18,12 @@ open Diagnostics
open Cutil
open Env
-let attribute_string = function
- | AConst -> "const"
- | AVolatile -> "volatile"
- | ARestrict -> "restrict"
- | AAlignas n -> "_Alignas"
- | Attr(name, _) -> name
-
let unknown_attrs loc attrs =
let unknown attr =
let attr_class = class_of_attribute attr in
if attr_class = Attr_unknown then
warning loc Unknown_attribute
- "unknown attribute '%s' ignored" (attribute_string attr) in
+ "unknown attribute '%s' ignored" (name_of_attribute attr) in
List.iter unknown attrs
let unknown_attrs_typ env loc ty =
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index ea9713d5..cf67015a 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -95,7 +95,10 @@ let rec remove_custom_attributes (names: string list) (al: attributes) =
(* Classification of attributes *)
type attribute_class =
- | Attr_name (* Attribute applies to the names being declared *)
+ | Attr_object (* Attribute applies to the object being declared
+ (function, global variable, local variable) *)
+ | Attr_name (* Attribute applies to the name being declared
+ (object, struct/union member, struct/union/enum tag *)
| Attr_type (* Attribute applies to types *)
| Attr_struct (* Attribute applies to struct, union and enum *)
| Attr_function (* Attribute applies to function types and decls *)
@@ -111,11 +114,20 @@ let declare_attributes l =
let class_of_attribute = function
| AConst | AVolatile | ARestrict -> Attr_type
- | AAlignas _ -> Attr_name
+ | AAlignas _ -> Attr_object
| Attr(name, args) ->
try Hashtbl.find attr_class (normalize_attrname name)
with Not_found -> Attr_unknown
+(* Name for printing an attribute *)
+
+let name_of_attribute = function
+ | AConst -> "const"
+ | AVolatile -> "volatile"
+ | ARestrict -> "restrict"
+ | AAlignas n -> "_Alignas"
+ | Attr(name, _) -> name
+
(* Is an attribute a ISO C standard attribute? *)
let attr_is_standard = function
@@ -163,7 +175,10 @@ let rec unroll env t =
unroll env (add_attributes_type attr ty)
| _ -> t
-(* Extracting the attributes of a type *)
+(* Extracting the attributes of a type, including the attributes
+ attached to typedefs, structs and unions. In other words,
+ typedefs are unrolled and composite definitions expanded
+ before extracting the attributes. *)
let rec attributes_of_type env t =
match t with
@@ -190,6 +205,23 @@ let rec attributes_of_type env t =
| exception Env.Error(Env.Unbound_tag _) -> a
end
+(* Extracting the attributes of a type, excluding the attributes
+ attached to typedefs, structs and unions. In other words,
+ typedefs are not unrolled and composite definitions are not expanded. *)
+
+let rec attributes_of_type_no_expand t =
+ match t with
+ | TVoid a -> a
+ | TInt(ik, a) -> a
+ | TFloat(fk, a) -> a
+ | TPtr(ty, a) -> a
+ | TArray(ty, sz, a) -> add_attributes a (attributes_of_type_no_expand ty)
+ | TFun(ty, params, vararg, a) -> a
+ | TNamed(s, a) -> a
+ | TStruct(s, a) -> a
+ | TUnion(s, a) -> a
+ | TEnum(s, a) -> a
+
(* Changing the attributes of a type (at top-level) *)
(* Same hack as above for array types. *)
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index dc9dc0cc..5a1e9af3 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -50,6 +50,8 @@ val remove_custom_attributes : string list -> attributes -> attributes
in the given list of names. *)
val attributes_of_type : Env.t -> typ -> attributes
(* Return the attributes of the given type, expanding typedefs if needed. *)
+val attributes_of_type_no_expand : typ -> attributes
+ (* Return the attributes of the given type, without expanding typedefs. *)
val add_attributes_type : attributes -> typ -> typ
(* Add the given set of attributes to those of the given type. *)
val remove_attributes_type : Env.t -> attributes -> typ -> typ
@@ -62,7 +64,10 @@ val has_std_alignas : Env.t -> typ -> bool
(* Do the attributes of the type contain the C11 _Alignas attribute *)
type attribute_class =
- | Attr_name (* Attribute applies to the names being declared *)
+ | Attr_object (* Attribute applies to the object being declared
+ (function, global variable, local variable) *)
+ | Attr_name (* Attribute applies to the name being declared
+ (object, struct/union member, struct/union/enum tag *)
| Attr_type (* Attribute applies to types *)
| Attr_struct (* Attribute applies to struct, union and enum *)
| Attr_function (* Attribute applies to function types and decls *)
@@ -76,6 +81,8 @@ val class_of_attribute: attribute -> attribute_class
have class [Attr_type]. Custom attributes have the class that
was given to them using [declare_attribute], or [Attr_unknown]
if not declared. *)
+val name_of_attribute: attribute -> string
+ (* Name for printing an attribute *)
val attr_inherited_by_members: attribute -> bool
(* Is an attribute of a composite inherited by members of the composite? *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 718261b4..7a0b05de 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -535,8 +535,11 @@ let elab_attribute env = function
(List.flatten
(List.map (elab_gcc_attr loc env) l)))
| PACKED_ATTR (args, loc) ->
- enter_gcc_attr loc
+ begin try
+ enter_gcc_attr loc
(Attr("__packed__", List.map (elab_attr_arg loc env) args))
+ with Wrong_attr_arg -> error loc "ill-formed 'packed' attribute"; []
+ end
| ALIGNAS_ATTR ([a], loc) ->
warning loc Celeven_extension "'_Alignas' is a C11 extension";
begin match elab_attr_arg loc env a with
@@ -595,7 +598,7 @@ let get_nontype_attrs env ty =
| Attr_type -> false
| Attr_function -> not (is_function_type env ty)
| _ -> true in
- let nta = List.filter to_be_removed (attributes_of_type env ty) in
+ let nta = List.filter to_be_removed (attributes_of_type_no_expand ty) in
(remove_attributes_type env nta ty, nta)
(* Elaboration of a type specifier. Returns 6-tuple:
@@ -653,15 +656,31 @@ let rec elab_specifier ?(only = false) loc env specifier =
restrict_check ty;
(!sto, !inline, !noreturn ,!typedef, add_attributes_type !attr ty, env) in
- (* As done in CIL, partition !attr into struct-related attributes,
+ (* Partition !attr into name- and struct-related attributes,
which are returned, and other attributes, which are left in !attr.
- The returned struct-related attributes are applied to the
+ The returned name-or-struct-related attributes are applied to the
struct/union/enum being defined.
- The leftover non-struct-related attributes will be applied
- to the variable being defined. *)
- let get_struct_attrs () =
+ The leftover attributes (e.g. object attributes) will be applied
+ to the variable being defined.
+ If [optmembers] is [None], name-related attributes are not returned
+ but left in !attr. This corresponds to two use cases:
+ - A use of an already-defined struct/union/enum. In this case
+ the name-related attributes should go to the name being declared.
+ Sending them to the struct/union/enum would cause them to be ignored,
+ with a warning. The struct-related attributes go to the
+ struct/union/enum, are ignored, and cause a warning.
+ - An incomplete declaration of a struct/union. In this case
+ the name- and struct-related attributes are just ignored,
+ like GCC does.
+ *)
+ let get_definition_attrs optmembers =
let (ta, nta) =
- List.partition (fun a -> class_of_attribute a = Attr_struct) !attr in
+ List.partition
+ (fun a -> match class_of_attribute a with
+ | Attr_struct -> true
+ | Attr_name -> optmembers <> None
+ | _ -> false)
+ !attr in
attr := nta;
ta in
@@ -720,7 +739,8 @@ let rec elab_specifier ?(only = false) loc env specifier =
| [Cabs.Tstruct_union(STRUCT, id, optmembers, a)] ->
let a' =
- add_attributes (get_struct_attrs()) (elab_attributes env a) in
+ add_attributes (get_definition_attrs optmembers)
+ (elab_attributes env a) in
let (id', env') =
elab_struct_or_union only Struct loc id optmembers a' env in
let ty = TStruct(id', !attr) in
@@ -729,7 +749,8 @@ let rec elab_specifier ?(only = false) loc env specifier =
| [Cabs.Tstruct_union(UNION, id, optmembers, a)] ->
let a' =
- add_attributes (get_struct_attrs()) (elab_attributes env a) in
+ add_attributes (get_definition_attrs optmembers)
+ (elab_attributes env a) in
let (id', env') =
elab_struct_or_union only Union loc id optmembers a' env in
let ty = TUnion(id', !attr) in
@@ -738,7 +759,8 @@ let rec elab_specifier ?(only = false) loc env specifier =
| [Cabs.Tenum(id, optmembers, a)] ->
let a' =
- add_attributes (get_struct_attrs()) (elab_attributes env a) in
+ add_attributes (get_definition_attrs optmembers)
+ (elab_attributes env a) in
let (id', env') =
elab_enum only loc id optmembers a' env in
let ty = TEnum (id', !attr) in
@@ -2359,6 +2381,13 @@ let enter_typedefs loc env sto dl =
error loc "initializer in typedef";
if has_std_alignas env ty then
error loc "alignment specified for typedef '%s'" s;
+ List.iter
+ (fun a -> match class_of_attribute a with
+ | Attr_object | Attr_struct ->
+ error loc "attribute '%s' not allowed in 'typedef'"
+ (name_of_attribute a)
+ | _ -> ())
+ (attributes_of_type_no_expand ty);
match previous_def Env.lookup_typedef env s with
| Some (s',ty') when Env.in_current_scope env s' ->
if equal_types env ty ty' then begin
diff --git a/cparser/PackedStructs.ml b/cparser/PackedStructs.ml
index a2c91c0a..3c27f3a9 100644
--- a/cparser/PackedStructs.ml
+++ b/cparser/PackedStructs.ml
@@ -36,7 +36,7 @@ let byteswapped_fields : (ident * string, unit) Hashtbl.t
let rec can_byte_swap env ty =
match unroll env ty with
- | TInt(ik, _) -> (sizeof_ikind ik <= !config.sizeof_ptr (*FIXME*), sizeof_ikind ik > 1)
+ | TInt(ik, _) -> (sizeof_ikind ik <= !config.sizeof_intreg, sizeof_ikind ik > 1)
| TEnum(_, _) -> (true, sizeof_ikind enum_ikind > 1)
| TPtr(_, _) -> (true, true) (* tolerance? *)
| TArray(ty_elt, _, _) -> can_byte_swap env ty_elt
@@ -66,7 +66,7 @@ let transf_field_decl mfa swapped loc env struct_id f =
if swapped then begin
let (can_swap, must_swap) = can_byte_swap env f.fld_typ in
if not can_swap then
- error loc "cannot byte-swap field of type '%a'"
+ fatal_error loc "cannot byte-swap field of type '%a'"
Cprint.typ f.fld_typ;
if must_swap then
Hashtbl.add byteswapped_fields (struct_id, f.fld_name) ()
@@ -141,7 +141,7 @@ let use_reversed = ref false
let bswap_read loc env lval =
let ty = lval.etyp in
let (bsize, aty) = accessor_type loc env ty in
- assert (bsize = 16 || bsize = 32 || (bsize = 64 && !config.sizeof_ptr = 8));
+ assert (bsize = 16 || bsize = 32 || (bsize = 64 && !config.sizeof_intreg = 8));
try
if !use_reversed then begin
let (id, fty) =
@@ -168,7 +168,7 @@ let bswap_write loc env lhs rhs =
let ty = lhs.etyp in
let (bsize, aty) =
accessor_type loc env ty in
- assert (bsize = 16 || bsize = 32 || (bsize = 64 && !config.sizeof_ptr = 8));
+ assert (bsize = 16 || bsize = 32 || (bsize = 64 && !config.sizeof_intreg = 8));
try
if !use_reversed then begin
let (id, fty) =