From eec6d60b5fa43fa8cf011747d6b98322dcdaaae8 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Wed, 13 Feb 2019 16:04:27 +0100 Subject: Reject object-related and struct-related attributes on typedefs This commit adds a check to reject type definitions such as ``` typedef __attribute((section "foo")) int fooint; ``` GCC and Clang also reject this as an error. Without the check, the behavior is somewhat surprising: ``` fooint x; // placed in section "foo" fooint * x; // placed in default section, attribute "foo" is ignored ``` Note that the following must be accepted: ``` typedef struct { ... } __attribute((packed)) t; ``` The "packed" attribute is correctly attached to the struct type and should not be checked. This is achieved by using `attribute_of_type_no_expand` to get the attributes of the typedef-ed type, excluding the attributes carried by a struct/union or another typedef. --- cparser/Checks.ml | 9 +-------- cparser/Cutil.ml | 9 +++++++++ cparser/Cutil.mli | 2 ++ cparser/Elab.ml | 7 +++++++ 4 files changed, 19 insertions(+), 8 deletions(-) (limited to 'cparser') diff --git a/cparser/Checks.ml b/cparser/Checks.ml index 62d85c1b..a30cde7d 100644 --- a/cparser/Checks.ml +++ b/cparser/Checks.ml @@ -18,19 +18,12 @@ open Diagnostics open Cutil open Env -let attribute_string = function - | AConst -> "const" - | AVolatile -> "volatile" - | ARestrict -> "restrict" - | AAlignas n -> "_Alignas" - | Attr(name, _) -> name - let unknown_attrs loc attrs = let unknown attr = let attr_class = class_of_attribute attr in if attr_class = Attr_unknown then warning loc Unknown_attribute - "unknown attribute '%s' ignored" (attribute_string attr) in + "unknown attribute '%s' ignored" (name_of_attribute attr) in List.iter unknown attrs let unknown_attrs_typ env loc ty = diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml index 25329694..cf67015a 100644 --- a/cparser/Cutil.ml +++ b/cparser/Cutil.ml @@ -119,6 +119,15 @@ let class_of_attribute = function try Hashtbl.find attr_class (normalize_attrname name) with Not_found -> Attr_unknown +(* Name for printing an attribute *) + +let name_of_attribute = function + | AConst -> "const" + | AVolatile -> "volatile" + | ARestrict -> "restrict" + | AAlignas n -> "_Alignas" + | Attr(name, _) -> name + (* Is an attribute a ISO C standard attribute? *) let attr_is_standard = function diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli index 400a6319..5a1e9af3 100644 --- a/cparser/Cutil.mli +++ b/cparser/Cutil.mli @@ -81,6 +81,8 @@ val class_of_attribute: attribute -> attribute_class have class [Attr_type]. Custom attributes have the class that was given to them using [declare_attribute], or [Attr_unknown] if not declared. *) +val name_of_attribute: attribute -> string + (* Name for printing an attribute *) val attr_inherited_by_members: attribute -> bool (* Is an attribute of a composite inherited by members of the composite? *) diff --git a/cparser/Elab.ml b/cparser/Elab.ml index 46bc63a9..d7124663 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -2366,6 +2366,13 @@ let enter_typedefs loc env sto dl = error loc "initializer in typedef"; if has_std_alignas env ty then error loc "alignment specified for typedef '%s'" s; + List.iter + (fun a -> match class_of_attribute a with + | Attr_object | Attr_struct -> + error loc "attribute '%s' not allowed in 'typedef'" + (name_of_attribute a) + | _ -> ()) + (attributes_of_type_no_expand ty); match previous_def Env.lookup_typedef env s with | Some (s',ty') when Env.in_current_scope env s' -> if equal_types env ty ty' then begin -- cgit