aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@college-de-france.fr>2019-02-12 11:49:23 +0100
committerXavier Leroy <xavierleroy@users.noreply.github.com>2019-02-25 17:15:36 +0100
commitd7dfc21c20f55b705e3e749c2c7b31f9a4611c39 (patch)
treeee0b6e0ad06941260244deba916e553d68f882e5
parent0616171c89d3db651b6842338fdf2da9da885aa1 (diff)
downloadcompcert-d7dfc21c20f55b705e3e749c2c7b31f9a4611c39.tar.gz
compcert-d7dfc21c20f55b705e3e749c2c7b31f9a4611c39.zip
Distinguish object-related and name-related attributes
This is a second step towards mimicking GCC/Clang's handling of attributes. This commit introduces a distinction between - Object-related attributes, such as "section", which apply to the object (function, variable) being defined; - Name-related attributes, such as "aligned", which apply to the name (object, struct/union member, struct/union/enum tag) being defined. In particular, "aligned" is now attached to "struct" and "union" definitions, while it used to be "floated up" before. The C11 _Alignas modifier is treated like an object-related attribute, so that ``` struct s { ... }; _Alignas(64) struct s x; ``` correctly associates the alignment with "x" and not with "struct s", where it would be ignored because it was not part of the original definition of s.
-rw-r--r--cfrontend/C2C.ml5
-rw-r--r--cparser/Cutil.ml7
-rw-r--r--cparser/Cutil.mli5
-rw-r--r--cparser/Elab.ml20
4 files changed, 24 insertions, 13 deletions
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index d6bf76f3..d70c4dad 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -315,8 +315,9 @@ let attributes = [
("noinline",Cutil.Attr_function);
(* name-related *)
("aligned", Cutil.Attr_name);
- ("section", Cutil.Attr_name);
- ("unused", Cutil.Attr_name)
+ (* object-related *)
+ ("section", Cutil.Attr_object);
+ ("unused", Cutil.Attr_object)
]
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index b926e84a..25329694 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,7 +114,7 @@ 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
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index a99bf3af..400a6319 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -64,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 *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 8f42fe0a..46bc63a9 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -656,15 +656,19 @@ 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
+ The leftover attributes (e.g. object attributes) will be applied
to the variable being defined. *)
- let get_struct_attrs () =
+ let get_definition_attrs () =
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 | Attr_name -> true
+ | _ -> false)
+ !attr in
attr := nta;
ta in
@@ -723,7 +727,7 @@ 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()) (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
@@ -732,7 +736,7 @@ 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()) (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
@@ -741,7 +745,7 @@ 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()) (elab_attributes env a) in
let (id', env') =
elab_enum only loc id optmembers a' env in
let ty = TEnum (id', !attr) in