From 8b178cf0b7e9dcc823ad164a6856032627b3bc6f Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Tue, 31 Jan 2017 16:13:03 +0100 Subject: Revised elaboration of attributes The treatment of attributes in the current CompCert is often surprising. For example, attribute(xxx) char * x; is parsed as "x is a pointer to a (char modified by attribute "xxx")", while for most attributes (e.g. section attributes) the expected meaning is "x, modified by attribute "xxx", has type pointer to char". CompCert's current treatment comes from the fact that attributes are processed very much like the standard type modifiers `const` and `volatile`, i.e. const char * x; is really "x is a pointer to a const char", not "x is a const pointer to char". This experiment introduces a distinction between type-related attributes (which include the standard modifiers `const` and `volatile`) and other attributes. The other, non-type-related attributes are "floated up" during elaboration so that they apply to the variable or function being declared or defined. In the examples above, attribute(xxx) char * x; // "attribute(xxx)" applies to "x" const char * x; // "const" applies to "char" This may be a step in the right direction but is not the final story. In particular, the `packed` attribute is special-cased when applied to `struct`, like it was before, and future attributes concerning calling conventions would need to be floated up to function types but not higher than that. --- cparser/Cutil.ml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cparser/Cutil.ml') diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml index f5d5c425..21e6f71e 100644 --- a/cparser/Cutil.ml +++ b/cparser/Cutil.ml @@ -92,6 +92,12 @@ let attr_is_standard = function (* Is an attribute type-related (true) or variable-related (false)? *) let attr_is_type_related = function + | AConst | AVolatile | ARestrict | AAlignas _ -> true + | Attr(_, _) -> false + +(* Is an attribute related to structs, unions and enum (true) or not (false)? *) + +let attr_is_struct_related = function | Attr(("packed" | "__packed__"), _) -> true | _ -> false -- cgit From 3babd253e1d194549294c282e1b0c60097b26b07 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Fri, 3 Feb 2017 14:12:32 +0100 Subject: Refactor the classification of attributes Introduce Cutil.class_of_attribute to return the class of the given attribute: one among Attr_type attribute related to types (e.g. "aligned") Attr_struct attribute related to struct/union/enum types (e.g. "packed") Attr_function attribute related to function types (e.g. "noreturn") Attr_name attribute related to variable and function declarations (e.g. "section") Attr_unknown attribute was not declared Cutil.declare_attribute is used to associate a class to a custom attribute. Standard attributes (const, volatile, _Alignas, etc) are Attr_type. cfronted/C2C.ml: declare the few attributes that CompCert honors currently. cparser/GCC.ml: a bigger list of attributes taken from GCC, for reference only. --- cparser/Cutil.ml | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'cparser/Cutil.ml') diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml index 21e6f71e..44d16ea1 100644 --- a/cparser/Cutil.ml +++ b/cparser/Cutil.ml @@ -37,6 +37,15 @@ module IdentMap = Map.Make(Ident) (* Operations on attributes *) +(* Normalize the name of an attribute, removing starting and trailing '__' *) + +let re_normalize_attrname = Str.regexp "^__\\(.*\\)__$" + +let normalize_attrname a = + if Str.string_match re_normalize_attrname a 0 + then Str.matched_group 1 a + else a + (* Lists of attributes are kept sorted in increasing order *) let rec add_attributes (al1: attributes) (al2: attributes) = @@ -83,23 +92,34 @@ let rec remove_custom_attributes (names: string list) (al: attributes) = | a :: tl -> a :: remove_custom_attributes names tl -(* Is an attribute a ISO C standard attribute? *) +(* Classification of attributes *) -let attr_is_standard = function - | AConst | AVolatile | ARestrict -> true - | AAlignas _ | Attr _ -> false +type attribute_class = + | Attr_name (* Attribute applies to the names being declared *) + | Attr_type (* Attribute applies to types *) + | Attr_struct (* Attribute applies to struct, union and enum *) + | Attr_function (* Attribute applies to function types and decls *) + | Attr_unknown (* Unknown attribute *) + +let attr_class : (string, attribute_class) Hashtbl.t = Hashtbl.create 32 -(* Is an attribute type-related (true) or variable-related (false)? *) +let declare_attribute name cls = + Hashtbl.replace attr_class (normalize_attrname name) cls -let attr_is_type_related = function - | AConst | AVolatile | ARestrict | AAlignas _ -> true - | Attr(_, _) -> false +let declare_attributes l = + List.iter (fun (n,c) -> declare_attribute n c) l -(* Is an attribute related to structs, unions and enum (true) or not (false)? *) +let class_of_attribute = function + | AConst | AVolatile | ARestrict | AAlignas _ -> Attr_type + | Attr(name, args) -> + try Hashtbl.find attr_class (normalize_attrname name) + with Not_found -> Attr_unknown -let attr_is_struct_related = function - | Attr(("packed" | "__packed__"), _) -> true - | _ -> false +(* Is an attribute a ISO C standard attribute? *) + +let attr_is_standard = function + | AConst | AVolatile | ARestrict -> true + | AAlignas _ | Attr _ -> false (* Is an attribute applicable to a whole array (true) or only to array elements (false)? *) -- cgit