Skip to content

Commit 549c8dd

Browse files
Merge pull request #62 from goblint/static_assert
Add support for `_Static_assert`
2 parents 395a517 + fc6cde4 commit 549c8dd

File tree

9 files changed

+60
-14
lines changed

9 files changed

+60
-14
lines changed

src/frontc/cabs.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ and definition =
185185
| TRANSFORMER of definition * definition list * cabsloc
186186
(* expression transformer: source and destination *)
187187
| EXPRTRANSFORMER of expression * expression * cabsloc
188+
| STATIC_ASSERT of expression * string * cabsloc
188189

189190

190191
(* the string is a file name, and then the list of toplevel forms *)

src/frontc/cabs2cil.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6394,7 +6394,7 @@ and doDecl (isglobal: bool) : A.definition -> chunk = function
63946394
E.s (bug "doDecl returns non-empty statement for global"))
63956395
dl;
63966396
empty
6397-
6397+
| STATIC_ASSERT _ -> empty
63986398
| _ -> E.s (error "unexpected form of declaration")
63996399

64006400
and doTypedef ((specs, nl): A.name_group) =

src/frontc/cabshelper.ml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ let getident () =
66
nextident := !nextident + 1;
77
!nextident
88

9-
let currentLoc () =
9+
let currentLoc () =
1010
let l, f, c, lc = Errormsg.getPosition () in
1111
{ lineno = l;
1212
filename = f;
@@ -17,8 +17,8 @@ let currentLoc () =
1717
endByteno = -1;
1818
endColumnno = -1;}
1919

20-
let cabslu = {lineno = -10;
21-
filename = "cabs loc unknown";
20+
let cabslu = {lineno = -10;
21+
filename = "cabs loc unknown";
2222
byteno = -10; columnno = -10;
2323
ident = 0;
2424
endLineno = -10; endByteno = -10; endColumnno = -10;}
@@ -27,9 +27,9 @@ let string_of_loc l =
2727
Printf.sprintf "%s:%d:%d-%d:%d" l.filename l.lineno l.columnno l.endLineno l.endColumnno
2828

2929
let joinLoc l1 l2 = match l1, l2 with
30-
| l1, l2 when l1.filename = l2.filename && l1.endByteno < 0 && l2.endByteno < 0 && l1.byteno <= l2.byteno ->
30+
| l1, l2 when l1.filename = l2.filename && l1.endByteno < 0 && l2.endByteno < 0 && l1.byteno <= l2.byteno ->
3131
{l1 with endLineno = l2.lineno; endByteno = l2.byteno; endColumnno = l2.columnno}
32-
| l1, l2 when l1.filename = l2.filename && l1.endByteno = l2.endByteno && l1.byteno = l2.byteno ->
32+
| l1, l2 when l1.filename = l2.filename && l1.endByteno = l2.endByteno && l1.byteno = l2.byteno ->
3333
l1 (* alias fundefs *)
3434
| _, _ ->
3535
(* some code generators leave start and end into different files: https://github.com/goblint/cil/issues/54 *)
@@ -76,6 +76,7 @@ let get_definitionloc (d : definition) : cabsloc =
7676
| TRANSFORMER(_, _, l) -> l
7777
| EXPRTRANSFORMER(_, _, l) -> l
7878
| LINKAGE (_, l, _) -> l
79+
| STATIC_ASSERT (_,_,l) -> l
7980

8081
let get_statementloc (s : statement) : cabsloc =
8182
begin
@@ -103,23 +104,23 @@ begin
103104
end
104105

105106

106-
let explodeStringToInts (s: string) : int64 list =
107-
let rec allChars i acc =
107+
let explodeStringToInts (s: string) : int64 list =
108+
let rec allChars i acc =
108109
if i < 0 then acc
109110
else allChars (i - 1) (Int64.of_int (Char.code (String.get s i)) :: acc)
110111
in
111112
allChars (-1 + String.length s) []
112113

113114
let valueOfDigit chr =
114-
let int_value =
115+
let int_value =
115116
match chr with
116117
'0'..'9' -> (Char.code chr) - (Char.code '0')
117118
| 'a'..'z' -> (Char.code chr) - (Char.code 'a') + 10
118119
| 'A'..'Z' -> (Char.code chr) - (Char.code 'A') + 10
119120
| _ -> Errormsg.s (Errormsg.bug "not a digit") in
120121
Int64.of_int int_value
121-
122-
122+
123+
123124
open Pretty
124-
let d_cabsloc () cl =
125+
let d_cabsloc () cl =
125126
text cl.filename ++ text ":" ++ num cl.lineno

src/frontc/cabsvisit.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ and childrenDefinition vis d =
325325
| LINKAGE (n, l, dl) ->
326326
let dl' = mapNoCopyList (visitCabsDefinition vis) dl in
327327
if dl' != dl then LINKAGE (n, l, dl') else d
328-
328+
329+
| STATIC_ASSERT _ -> d
329330
| TRANSFORMER _ -> d
330331
| EXPRTRANSFORMER _ -> d
331332

src/frontc/clexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ let init_lexicon _ =
169169
("__inline", fun loc -> INLINE loc);
170170
("_inline", fun loc -> IDENT ("_inline", loc));
171171
("_Noreturn", fun loc -> NORETURN loc);
172+
("_Static_assert", fun loc -> STATIC_ASSERT loc);
172173
("__attribute__", fun loc -> ATTRIBUTE loc);
173174
("__attribute", fun loc -> ATTRIBUTE loc);
174175
(*

src/frontc/cparser.mly

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ let transformOffsetOf (speclist, dtype) member =
290290
%token<Cabs.cabsloc> IF
291291
%token ELSE
292292

293-
%token<Cabs.cabsloc> ATTRIBUTE INLINE ASM TYPEOF REAL IMAG FUNCTION__ PRETTY_FUNCTION__ CLASSIFYTYPE
293+
%token<Cabs.cabsloc> ATTRIBUTE INLINE STATIC_ASSERT ASM TYPEOF REAL IMAG FUNCTION__ PRETTY_FUNCTION__ CLASSIFYTYPE
294294
%token LABEL__
295295
%token<Cabs.cabsloc> BUILTIN_VA_ARG ATTRIBUTE_USED
296296
%token BUILTIN_VA_LIST
@@ -930,6 +930,21 @@ declaration: /* ISO 6.7.*/
930930
{ doDeclaration (joinLoc (snd $1) $3) (fst $1) $2 }
931931
| decl_spec_list SEMICOLON
932932
{ doDeclaration (joinLoc (snd $1) $2) (fst $1) [] }
933+
| static_assert_declaration { let (e, m, loc) = $1 in STATIC_ASSERT (e, m, loc) }
934+
;
935+
936+
static_assert_declaration:
937+
938+
| STATIC_ASSERT LPAREN expression RPAREN /* C23 */
939+
{
940+
(fst $3, "", $1)
941+
}
942+
| STATIC_ASSERT LPAREN expression COMMA string_constant RPAREN
943+
{
944+
(fst $3, fst $5, $1)
945+
}
946+
;
947+
933948
;
934949
init_declarator_list: /* ISO 6.7 */
935950
init_declarator { [$1] }
@@ -1051,6 +1066,15 @@ struct_decl_list: /* (* ISO 6.7.2. Except that we allow empty structs. We
10511066

10521067
| error SEMICOLON struct_decl_list
10531068
{ $3 }
1069+
/*(* C11 allows static_assert-declaration *)*/
1070+
| static_assert_declaration {
1071+
[]
1072+
}
1073+
1074+
| static_assert_declaration SEMICOLON struct_decl_list {
1075+
$3
1076+
}
1077+
10541078
;
10551079
field_decl_list: /* (* ISO 6.7.2 *) */
10561080
field_decl { [$1] }

src/frontc/cprint.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,13 @@ and print_def def =
899899
print " }";
900900
force_new_line()
901901

902+
| STATIC_ASSERT(e,str,loc) ->
903+
setLoc(loc);
904+
print "_Static_assert(";
905+
print_expression e;
906+
print ",";
907+
print_string str;
908+
print ");";
902909

903910
(* sm: print a comment if the printComments flag is set *)
904911
and comprint (str : string) : unit =

test/small1/c11-static-assert.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "testharness.h"
2+
#include <stdnoreturn.h>
3+
4+
_Static_assert (2 <= 18, "blubb");
5+
6+
7+
int main() {
8+
_Static_assert (2 <= 18, "blubb");
9+
SUCCESS;
10+
}

test/testcil.pl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ sub addToGroup {
698698
addTest("testrunc11/c11-extendedFloat");
699699
addTest("testrunc11/c11-noreturn");
700700
addTest("testrunc11/c11-atomic");
701+
addTest("testrunc11/c11-static-assert");
701702
addTest("testrunc11/gcc-c11-generic-1");
702703
# TODO: these messages are not even checked?
703704
addTestFail("testc11/gcc-c11-generic-2-1", "Multiple defaults in generic");

0 commit comments

Comments
 (0)