From 45ca9fe8fcc6a67036369624f57576be22ac7bbd Mon Sep 17 00:00:00 2001 From: Bernhard Schommer Date: Mon, 10 Sep 2018 15:43:20 +0200 Subject: 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. --- cfrontend/C2C.ml | 4 ++-- cparser/Cutil.ml | 7 ++++--- cparser/Cutil.mli | 4 ++-- cparser/Elab.ml | 17 ++++++++++------- test/regression/Results/alignas | 1 + test/regression/alignas.c | 9 +++------ 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", -- cgit