Skip to content

Commit 52ba8d0

Browse files
committed
Check _Static_assert in struct (closes #65)
1 parent 32e7c43 commit 52ba8d0

6 files changed

Lines changed: 65 additions & 14 deletions

File tree

src/frontc/cabs.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ type typeSpecifier = (* Merge all specifiers into one type *)
8383
a forward declaration or simple reference to the type); they
8484
also have a list of __attribute__s that appeared between the
8585
keyword and the type name (definitions only) *)
86-
| Tstruct of string * field_group list option * attribute list
87-
| Tunion of string * field_group list option * attribute list
86+
| Tstruct of string * struct_decl list option * attribute list
87+
| Tunion of string * struct_decl list option * attribute list
8888
| Tenum of string * enum_item list option * attribute list
8989
| TtypeofE of expression (* GCC __typeof__ *)
9090
| TtypeofT of specifier * decl_type (* GCC __typeof__ *)
@@ -150,6 +150,10 @@ and name_group = specifier * name list
150150
(* The optional expression is the bitfield *)
151151
and field_group = specifier * (name * expression option) list
152152

153+
and struct_decl =
154+
| FIELD_GROUP of field_group
155+
| FIELD_STATIC_ASSERT of expression * string option * cabsloc
156+
153157
(* like name_group, except the declared variables are allowed to have initializers *)
154158
(* e.g.: int x=1, y=2; *)
155159
and init_name_group = specifier * init_name list

src/frontc/cabs2cil.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
26672667
if n = "" then E.s (error "Missing struct tag on incomplete struct");
26682668
findCompType "struct" n []
26692669
| [A.Tstruct (n, Some nglist, extraAttrs)] -> (* A definition of a struct *)
2670+
let nglist = doStructDecls nglist in
26702671
let (specs, names) = List.split nglist in
26712672
let n' =
26722673
if n <> "" then n else anonStructName "struct" suggestedAnonName specs in
@@ -2678,6 +2679,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
26782679
if n = "" then E.s (error "Missing union tag on incomplete union");
26792680
findCompType "union" n []
26802681
| [A.Tunion (n, Some nglist, extraAttrs)] -> (* A definition of a union *)
2682+
let nglist = doStructDecls nglist in
26812683
let (specs, names) = List.split nglist in
26822684
let n' =
26832685
if n <> "" then n else anonStructName "union" suggestedAnonName specs in
@@ -2827,6 +2829,23 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
28272829
in
28282830
bt,!storage,!isinline,List.rev (!attrs @ (convertCVtoAttr !cvattrs))
28292831

2832+
2833+
and doStructDecls (struct_decls: struct_decl list): field_group list =
2834+
List.filter_map (function
2835+
| FIELD_GROUP fg -> Some fg
2836+
| FIELD_STATIC_ASSERT (e, str, loc) ->
2837+
let loc = convLoc loc in
2838+
let d_message () = function
2839+
| None -> nil
2840+
| Some str -> dprintf ": %s" str
2841+
in
2842+
begin match isIntegerConstant e with
2843+
| Some 0 -> E.s (error "Static assert failed at %a%a" d_loc loc d_message str)
2844+
| Some _ -> None
2845+
| None -> E.s (error "Static assert with a non-constant at %a%a" d_loc loc d_message str)
2846+
end
2847+
) struct_decls
2848+
28302849
(* given some cv attributes, convert them into named attributes for
28312850
uniform processing *)
28322851
and convertCVtoAttr (src: A.cvspec list) : A.attribute list =

src/frontc/cabsvisit.ml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,22 @@ and childrenTypeSpecifier vis ts =
189189
let nel' = mapNoCopy doOneField nel in
190190
if s' != s || nel' != nel then (s', nel') else input
191191
in
192+
let childrenStructDecl input =
193+
match input with
194+
| FIELD_GROUP fg ->
195+
let fg' = childrenFieldGroup fg in
196+
if fg' != fg then FIELD_GROUP fg' else input
197+
| FIELD_STATIC_ASSERT (e, str, l) ->
198+
let e' = visitCabsExpression vis e in
199+
if e' != e then FIELD_STATIC_ASSERT (e', str, l) else input
200+
in
192201
match ts with
193202
Tstruct (n, Some fg, extraAttrs) ->
194203
(*(trace "sm" (dprintf "visiting struct %s\n" n));*)
195-
let fg' = mapNoCopy childrenFieldGroup fg in
204+
let fg' = mapNoCopy childrenStructDecl fg in
196205
if fg' != fg then Tstruct( n, Some fg', extraAttrs) else ts
197206
| Tunion (n, Some fg, extraAttrs) ->
198-
let fg' = mapNoCopy childrenFieldGroup fg in
207+
let fg' = mapNoCopy childrenStructDecl fg in
199208
if fg' != fg then Tunion( n, Some fg', extraAttrs) else ts
200209
| Tenum (n, Some ei, extraAttrs) ->
201210
let doOneEnumItem ((s, attrs, e, loc) as ei) =

src/frontc/cparser.mly

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ let transformOffsetOf (speclist, dtype) member =
370370

371371
%type <spec_elem list * cabsloc> decl_spec_list
372372
%type <typeSpecifier * cabsloc> type_spec
373-
%type <Cabs.field_group list> struct_decl_list
373+
%type <Cabs.struct_decl list> struct_decl_list
374374

375375

376376
%type <Cabs.name> old_proto_decl
@@ -1148,13 +1148,13 @@ struct_decl_list: /* (* ISO 6.7.2. Except that we allow empty structs. We
11481148
*/
11491149
/* empty */ { [] }
11501150
| decl_spec_list SEMICOLON struct_decl_list
1151-
{ (fst $1,
1151+
{ FIELD_GROUP (fst $1,
11521152
[(missingFieldDecl, None)]) :: $3 }
11531153
/*(* GCC allows extra semicolons *)*/
11541154
| SEMICOLON struct_decl_list
11551155
{ $2 }
11561156
| decl_spec_list field_decl_list SEMICOLON struct_decl_list
1157-
{ (fst $1, $2)
1157+
{ FIELD_GROUP (fst $1, $2)
11581158
:: $4 }
11591159
/*(* MSVC allows pragmas in strange places *)*/
11601160
| pragma struct_decl_list { $2 }
@@ -1163,11 +1163,13 @@ struct_decl_list: /* (* ISO 6.7.2. Except that we allow empty structs. We
11631163
{ $3 }
11641164
/*(* C11 allows static_assert-declaration *)*/
11651165
| static_assert_declaration {
1166-
[]
1166+
let (e, m, loc) = $1 in
1167+
[FIELD_STATIC_ASSERT (e, m, loc)]
11671168
}
11681169

11691170
| static_assert_declaration SEMICOLON struct_decl_list {
1170-
$3
1171+
let (e, m, loc) = $1 in
1172+
FIELD_STATIC_ASSERT (e, m, loc) :: $3
11711173
}
11721174

11731175
;

src/frontc/cprint.ml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,25 @@ and print_decl (n: string) = function
244244
comprint ")"
245245

246246

247-
and print_fields (flds : field_group list) =
247+
and print_fields (flds : struct_decl list) =
248248
if flds = [] then print " { } "
249249
else begin
250250
print " {";
251251
indent ();
252252
List.iter
253-
(fun fld -> print_field_group fld; print ";"; new_line ())
253+
(function
254+
| FIELD_GROUP fld -> print_field_group fld; print ";"; new_line ()
255+
| FIELD_STATIC_ASSERT (e, str, loc) ->
256+
print "_Static_assert(";
257+
print_expression e;
258+
begin match str with
259+
| Some str ->
260+
print ",";
261+
print_string str;
262+
| None -> ()
263+
end;
264+
print ");";
265+
)
254266
flds;
255267
unindent ();
256268
print "} "

src/frontc/patch.ml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -558,12 +558,17 @@ begin
558558
)
559559
end
560560

561-
and unifyField (pat : field_group) (tgt : field_group) : binding list =
561+
and unifyField (pat : struct_decl) (tgt : struct_decl) : binding list =
562562
begin
563-
match pat,tgt with (spec1, list1), (spec2, list2) -> (
563+
match pat, tgt with
564+
| FIELD_GROUP (spec1, list1), FIELD_GROUP (spec2, list2) ->
564565
(unifySpecifiers spec1 spec2) @
565566
(unifyList list1 list2 unifyNameExprOpt)
566-
)
567+
| FIELD_STATIC_ASSERT (exp1, str1, l1), FIELD_STATIC_ASSERT (exp2, str2, l2) ->
568+
(unifyExpr exp1 exp2)
569+
| _, _ ->
570+
if verbose then (trace "patchDebug" (dprintf "mismatching struct_decl-s\n"));
571+
raise NoMatch
567572
end
568573

569574
and unifyNameExprOpt (pat : name * expression option)

0 commit comments

Comments
 (0)