aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Schommer <bschommer@users.noreply.github.com>2018-09-10 15:43:20 +0200
committerXavier Leroy <xavierleroy@users.noreply.github.com>2018-09-10 15:43:20 +0200
commit45ca9fe8fcc6a67036369624f57576be22ac7bbd (patch)
tree7f4e1e79a1abd7fccfdf965f872e9ae6b4437c52
parent49ecf8a3e5b5a4449f4bcbc1d6d4f55c8b5888be (diff)
downloadcompcert-45ca9fe8fcc6a67036369624f57576be22ac7bbd.tar.gz
compcert-45ca9fe8fcc6a67036369624f57576be22ac7bbd.zip
Attach _Alignas to names and refactor _Alignas checks (#133)
* Refactor common code of alignas. Instead of working on attributes the function now works directly on the type since the check always performed an extraction of attributes from a type. Bug 23393 * Attach _Alignas to the name. Bug 23393 * Attach "aligned" attributes to names So that __attribute((aligned(N))) remains consistent with _Alignas(N). gcc and clang apply "aligned" attributes to names, with a special case for typedefs: typedef __attribute((aligned(16))) int int_al_16; int_al_16 * p; __attribute((aligned(16))) int * q; For gcc, p is naturally-aligned pointer to 16-aligned int and q is 16-aligned pointer to naturally-aligned int. For CompCert with this commit, both p and q are 16-aligned pointers to naturally-aligned int. * Resurrect the alignment test involving typedef The test was removed because it involved an _Alignas in a typedef, which is no longer supported. However the same effect can be achieved with an "aligned" attribute, which is still supported in typedef.
-rw-r--r--cfrontend/C2C.ml4
-rw-r--r--cparser/Cutil.ml7
-rw-r--r--cparser/Cutil.mli4
-rw-r--r--cparser/Elab.ml17
-rw-r--r--test/regression/Results/alignas1
-rw-r--r--test/regression/alignas.c9
6 files changed, 22 insertions, 20 deletions
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index ecaffbc6..1bbcb146 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -307,14 +307,14 @@ let builtins =
(** ** The known attributes *)
let attributes = [
- (* type-related *)
- ("aligned", Cutil.Attr_type);
+ (* type-related -- currently none *)
(* struct-related *)
("packed", Cutil.Attr_struct);
(* function-related *)
("noreturn", Cutil.Attr_function);
("noinline",Cutil.Attr_function);
(* name-related *)
+ ("aligned", Cutil.Attr_name);
("section", Cutil.Attr_name);
("unused", Cutil.Attr_name)
]
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index a0a2cf56..ea9713d5 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -110,7 +110,8 @@ let declare_attributes l =
List.iter (fun (n,c) -> declare_attribute n c) l
let class_of_attribute = function
- | AConst | AVolatile | ARestrict | AAlignas _ -> Attr_type
+ | AConst | AVolatile | ARestrict -> Attr_type
+ | AAlignas _ -> Attr_name
| Attr(name, args) ->
try Hashtbl.find attr_class (normalize_attrname name)
with Not_found -> Attr_unknown
@@ -258,8 +259,8 @@ let strip_last_attribute typ =
l,TEnum(n,r)
(* Check whether the attributes contain _Alignas attribute *)
-let has_std_alignas attr =
- List.exists (function | AAlignas _ -> true | _ -> false) attr
+let has_std_alignas env typ =
+ List.exists (function | AAlignas _ -> true | _ -> false) (attributes_of_type env typ)
(* Extracting alignment value from a set of attributes. Return 0 if none. *)
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index 3f8d8dcd..dc9dc0cc 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -58,8 +58,8 @@ val erase_attributes_type : Env.t -> typ -> typ
(* Erase the attributes of the given type. *)
val change_attributes_type : Env.t -> (attributes -> attributes) -> typ -> typ
(* Apply the given function to the top-level attributes of the given type *)
-val has_std_alignas : attributes -> bool
- (* Do the attributes contain the C11 _Alignas attribute *)
+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 *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 146cab2e..27569ff5 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -871,7 +871,7 @@ and elab_parameter env (PARAM (spec, id, decl, attr, loc)) =
let ty1 = argument_conversion env1 ty in
if is_qualified_array ty1 then
error loc "type qualifier used in non-outermost array type derivation";
- if has_std_alignas (attributes_of_type env ty) then begin
+ if has_std_alignas env ty then begin
if id <> "" then
error loc "alignment specified for parameter '%s'" id
else
@@ -928,15 +928,18 @@ and elab_init_name_group loc env (spec, namelist) =
let ((ty, _), env1) =
elab_type_declarator loc env bty decl in
let a = elab_attributes env attr in
- if inl && not (is_function_type env ty) then
+ let has_fun_typ = is_function_type env ty in
+ if inl && not has_fun_typ then
error loc "'inline' can only appear on functions";
let a' =
if noret then begin
warning loc Celeven_extension "_Noreturn functions are a C11 extension";
- if not (is_function_type env ty) then
+ if not has_fun_typ then
error loc "'_Noreturn' can only appear on functions";
add_attributes [Attr("noreturn",[])] a
end else a in
+ if has_std_alignas env ty && has_fun_typ then
+ error loc "alignment specified for function '%s'" id;
((id, add_attributes_type a' ty, init), env1) in
(mmap elab_one_name env' namelist, sto, tydef)
@@ -973,7 +976,7 @@ and elab_field_group env (Field_group (spec, fieldlist, loc)) =
error loc
"the type of bit-field '%a' must be an integer type no bigger than 'int'" pp_field id;
None,env
- end else if has_std_alignas (attributes_of_type env' ty) then begin
+ end else if has_std_alignas env' ty then begin
error loc "alignment specified for bit-field '%a'" pp_field id;
None, env
end else begin
@@ -2354,7 +2357,7 @@ let enter_typedefs loc env sto dl =
List.fold_left (fun env (s, ty, init) ->
if init <> NO_INIT then
error loc "initializer in typedef";
- if has_std_alignas (attributes_of_type env ty) then
+ if has_std_alignas env ty then
error loc "alignment specified for typedef '%s'" s;
match previous_def Env.lookup_typedef env s with
| Some (s',ty') when Env.in_current_scope env s' ->
@@ -2383,7 +2386,7 @@ let enter_decdefs local nonstatic_inline loc env sto dl =
warning loc Missing_declarations "declaration does not declare anything";
let enter_decdef (decls, env) (s, ty, init) =
let isfun = is_function_type env ty in
- if sto = Storage_register && has_std_alignas (attributes_of_type env ty) then
+ if sto = Storage_register && has_std_alignas env ty then
error loc "alignment specified for 'register' object '%s'" s;
if sto = Storage_extern && init <> NO_INIT then
error loc "'extern' declaration variable has an initializer";
@@ -2599,7 +2602,7 @@ let elab_fundef genv spec name defs body loc =
let (ty_ret, params, vararg, attr) =
match ty with
| TFun(ty_ret, Some params, vararg, attr) ->
- if has_std_alignas (attr @ (attributes_of_type genv ty_ret)) then
+ if has_std_alignas genv ty then
error loc "alignment specified for function '%s'" s;
if wrap incomplete_type loc genv ty_ret && not (is_void_type genv ty_ret) then
fatal_error loc "incomplete result type %a in function definition"
diff --git a/test/regression/Results/alignas b/test/regression/Results/alignas
index 9372096a..620b5e76 100644
--- a/test/regression/Results/alignas
+++ b/test/regression/Results/alignas
@@ -1,6 +1,7 @@
a: size = 4, address mod 16 = 0
b: size = 12, address mod 16 = 0
bb: size = 12, address mod 16 = 0
+bbb: size = 12, address mod 16 = 0
c: size = 32, address mod 16 = 0
d: size = 32, address mod 64 = 0
e: size = 16, address mod 16 = 0
diff --git a/test/regression/alignas.c b/test/regression/alignas.c
index 23966b59..777c13a5 100644
--- a/test/regression/alignas.c
+++ b/test/regression/alignas.c
@@ -7,7 +7,7 @@
#endif
#if __STDC_VERSION__ < 201100 && defined(__GNUC__)
-#define _Alignas(x) __attribute__((aligned(x)))
+#define _Alignas(x) __attribute((aligned(x)))
#endif
/* Base type */
@@ -20,10 +20,9 @@ _Alignas(16) int b[3];
typedef int int3[3];
_Alignas(16) int3 bb;
-#if 0
-typedef _Alignas(16) int int16;
+/* _Alignas is not allowed in typedefs but the "aligned" attribute is */
+typedef __attribute((aligned(16))) int int16;
int16 bbb[3];
-#endif
char filler2;
@@ -74,10 +73,8 @@ int main()
(unsigned) sizeof(b), ((unsigned) &b) & 0xF);
printf("bb: size = %u, address mod 16 = %u\n",
(unsigned) sizeof(bb), ((unsigned) &bb) & 0xF);
-#if 0
printf("bbb: size = %u, address mod 16 = %u\n",
(unsigned) sizeof(bbb), ((unsigned) &bbb) & 0xF);
-#endif
printf("c: size = %u, address mod 16 = %u\n",
(unsigned) sizeof(c), ((unsigned) &c) & 0xF);
printf("d: size = %u, address mod 64 = %u\n",