aboutsummaryrefslogtreecommitdiffstats
path: root/cparser
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 /cparser
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.
Diffstat (limited to 'cparser')
-rw-r--r--cparser/Cutil.ml7
-rw-r--r--cparser/Cutil.mli5
-rw-r--r--cparser/Elab.ml20
3 files changed, 21 insertions, 11 deletions
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