aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2019-02-15 10:57:54 +0100
committerXavier Leroy <xavierleroy@users.noreply.github.com>2019-02-25 17:15:36 +0100
commit4fb8df8cd1df4552e937d02fa78fc4993af81e63 (patch)
tree512eb6f4a383243ea372b9729cc7776998851cfb
parenteec6d60b5fa43fa8cf011747d6b98322dcdaaae8 (diff)
downloadcompcert-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.ml27
-rw-r--r--test/regression/Results/aligned1
-rw-r--r--test/regression/aligned.c7
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;
}