diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 2019-02-15 10:57:54 +0100 |
---|---|---|
committer | Xavier Leroy <xavierleroy@users.noreply.github.com> | 2019-02-25 17:15:36 +0100 |
commit | 4fb8df8cd1df4552e937d02fa78fc4993af81e63 (patch) | |
tree | 512eb6f4a383243ea372b9729cc7776998851cfb | |
parent | eec6d60b5fa43fa8cf011747d6b98322dcdaaae8 (diff) | |
download | compcert-4fb8df8cd1df4552e937d02fa78fc4993af81e63.tar.gz compcert-4fb8df8cd1df4552e937d02fa78fc4993af81e63.zip |
Revised attachment of name attributes to structs, unions, enums
Consider:
```
struct s { ... } __attribute((aligned(N)));
struct t { ... }
__attribute((aligned(N))) struct t x;
```
In the first case, the aligned attribute should be attached to struct s, so that further references to struct s are aligned.
In the second case, the aligned attribute should be attached to the variable x, because if we attach it to struct t, it will be ignored and cause a warning.
This commit changes the attachment rule so that it treats both cases right.
Extend regression test for "aligned" attribute accordingly, by testing
aligned attribute applied to a name of struct type.
-rw-r--r-- | cparser/Elab.ml | 27 | ||||
-rw-r--r-- | test/regression/Results/aligned | 1 | ||||
-rw-r--r-- | test/regression/aligned.c | 7 |
3 files changed, 29 insertions, 6 deletions
diff --git a/cparser/Elab.ml b/cparser/Elab.ml index d7124663..7a0b05de 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -661,12 +661,24 @@ let rec elab_specifier ?(only = false) loc env specifier = The returned name-or-struct-related attributes are applied to the struct/union/enum being defined. The leftover attributes (e.g. object attributes) will be applied - to the variable being defined. *) - let get_definition_attrs () = + 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 -> match class_of_attribute a with - | Attr_struct | Attr_name -> true + | Attr_struct -> true + | Attr_name -> optmembers <> None | _ -> false) !attr in attr := nta; @@ -727,7 +739,8 @@ let rec elab_specifier ?(only = false) loc env specifier = | [Cabs.Tstruct_union(STRUCT, id, optmembers, a)] -> let a' = - add_attributes (get_definition_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 @@ -736,7 +749,8 @@ let rec elab_specifier ?(only = false) loc env specifier = | [Cabs.Tstruct_union(UNION, id, optmembers, a)] -> let a' = - add_attributes (get_definition_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 @@ -745,7 +759,8 @@ let rec elab_specifier ?(only = false) loc env specifier = | [Cabs.Tenum(id, optmembers, a)] -> let a' = - add_attributes (get_definition_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 diff --git a/test/regression/Results/aligned b/test/regression/Results/aligned index 7a4f7c9f..c42a5c40 100644 --- a/test/regression/Results/aligned +++ b/test/regression/Results/aligned @@ -9,3 +9,4 @@ i: size 16, offset mod 16 = 0 j: size 16, offset mod 16 = 0 T2: size 112, alignment 16 T4: size is that of a pointer, alignment is that of a pointer +t2: size 9, alignment 1 diff --git a/test/regression/aligned.c b/test/regression/aligned.c index 3b5a9374..bd16d513 100644 --- a/test/regression/aligned.c +++ b/test/regression/aligned.c @@ -3,6 +3,7 @@ #include <stdio.h> #define ALIGNED __attribute((aligned(16))) +#define ALIGNED1 __attribute((aligned(1))) typedef ALIGNED char c16; @@ -72,6 +73,10 @@ typedef T2 T3[]; typedef struct { T3 *area; } T4; /* Expected: size of a pointer, alignment of a pointer */ +struct t1 { double d; }; +struct t2 { char c; ALIGNED1 struct t1 d; }; +/* Expected: size = 1 + 8, alignment 1 */ + void check(const char * msg, void * addr, size_t sz) { printf("%s: size %zu, offset mod 16 = %lu\n", @@ -104,5 +109,7 @@ int main() sizeof(T4) == sizeof(void *) ? "is" : "IS NOT", _Alignof(T4) == _Alignof(void *) ? "is" : "IS NOT"); + printf("t2: size %zu, alignment %zu\n", + sizeof(struct t2), _Alignof(struct t2)); return 0; } |