Skip to content

Commit c9272d1

Browse files
committed
C front-end: labelled declarations are only supported by Visual Studio
In order to support GCC's label attributes even when the semicolon is omitted, distinguish GCC and Visual Studio modes when parsing labelled statements. See https://github.com/gcc-mirror/gcc/blob/master/gcc/c/c-parser.cc#L6070 for GCC's limitation, which we now mimic. (We already supported attributes followed by a semicolon, which GCC's documentation mandates, but the Linux kernel doesn't always follow this rule.) Fixed regression tests that had declarations immediately following a label.
1 parent 1911a2e commit c9272d1

File tree

13 files changed

+126
-55
lines changed

13 files changed

+126
-55
lines changed

regression/ansi-c/label1/main.c

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
extern void foo(int *, unsigned int);
2+
3+
int main()
4+
{
5+
#ifdef _MSC_VER
6+
label:
7+
int x;
8+
#elif defined(__GNUC__)
9+
int *p;
10+
unsigned int u;
11+
label:
12+
__attribute__((unused)) foo(p, u);
13+
#endif
14+
}

regression/ansi-c/label1/test.desc

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
9+
--
10+
GCC does not permit labelling declarations as they are not considered
11+
statements, and would result in ambiguity in case of label attributes. We used
12+
to run into this problem, treating the function call in this test as a KnR
13+
function declaration.
14+
15+
Visual Studio, on the other hand, happily accepts labelled declarations.

regression/cbmc/destructors/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ int main(int argc, char **argv) {
66

77
const float *pc = (const float []){1e0, 1e1, 1e2};
88

9-
start:
9+
start:;
1010
test newAlloc0 = {0};
1111
if(argv[0])
1212
{
@@ -20,7 +20,7 @@ int main(int argc, char **argv) {
2020
if (argv[2])
2121
{
2222
test newAlloc3 = {3};
23-
nested_if:
23+
nested_if:;
2424
test newAlloc5 = {5};
2525
if (argv[3])
2626
{

regression/cbmc/symex_should_exclude_null_pointers/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ int main(int argc, char **argv) {
3838
int *ptr4 = maybe_null;
3939
goto check;
4040

41-
deref:
41+
deref:;
4242
int deref4 = *ptr4;
4343
goto end_test4;
4444

4545
check:
4646
__CPROVER_assume(ptr4 != 0);
4747
goto deref;
4848

49-
end_test4:
49+
end_test4:;
5050

5151
// Should be judged unsafe by LSPA and safe by value-set filtering
5252
// (guarded by confluence):

regression/cbmc/symex_should_filter_value_sets/main.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,28 +61,28 @@ int main(int argc, char **argv)
6161
int *p7 = ptr_to_a_or_b;
6262
goto check7;
6363

64-
divide7:
64+
divide7:;
6565
int c7 = *p7;
6666
goto end_test7;
6767

6868
check7:
6969
__CPROVER_assume(p7 != &a);
7070
goto divide7;
7171

72-
end_test7:
72+
end_test7:;
7373

7474
int *p8 = ptr_to_a_or_b;
7575
goto check8;
7676

77-
divide8:
77+
divide8:;
7878
int c8 = *p8;
7979
goto end_test8;
8080

8181
check8:
8282
__CPROVER_assume(*p8 != 2);
8383
goto divide8;
8484

85-
end_test8:
85+
end_test8:;
8686

8787
// Should work (value-set filtered by confluence of if and else):
8888
int *p9 = ptr_to_a_or_b;
+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
int main()
22
{
33
l2: goto l1;
4-
l1: int x=5;
5-
goto l2;
4+
l1:;
5+
int x = 5;
6+
goto l2;
67

7-
return 0;
8+
return 0;
89
}

regression/cbmc/unwind_counters3/main.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ int main()
22
{
33
int i=0;
44
l2: if(i==1) int y=0;
5-
l1: int x=5;
6-
goto l2;
5+
l1:;
6+
int x = 5;
7+
goto l2;
78

8-
return 0;
9+
return 0;
910
}

regression/cbmc/unwind_counters4/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ int main()
88
y = 10;
99
goto label;
1010
x = 1; // dead code, makes sure the above goto is not removed
11-
label:
11+
label:;
1212
_Bool nondet;
1313
if(nondet)
1414
__CPROVER_assert(y != 10, "violated via first loop");

regression/goto-instrument/labels1/main.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ int main()
2424
x = 42;
2525
label_four:
2626
assert(foo() == 1);
27+
fptr_t fp;
2728
label_five:
28-
fptr_t fp = foo;
29+
fp = foo;
2930
assert(fp() == 1);
3031
label_six:
3132
return *p;

regression/goto-instrument/safe-dereferences/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ int main(int argc, char **argv) {
3030
int *ptr4 = &x;
3131
goto check;
3232

33-
deref:
33+
deref:;
3434
int deref4 = *ptr4;
3535
goto end_test4;
3636

3737
check:
3838
__CPROVER_assume(ptr4 != 0);
3939
goto deref;
4040

41-
end_test4:
41+
end_test4:;
4242

4343
// Shouldn't work yet despite being safe (guarded by confluence):
4444
int *ptr5 = &x;

src/ansi-c/parser.y

+34-6
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ extern char *yyansi_ctext;
118118

119119
/*** scanner parsed tokens (these have a value!) ***/
120120

121-
%token TOK_IDENTIFIER
121+
%token TOK_GCC_IDENTIFIER
122+
%token TOK_MSC_IDENTIFIER
122123
%token TOK_TYPEDEFNAME
123124
%token TOK_INTEGER
124125
%token TOK_FLOATING
@@ -293,7 +294,8 @@ grammar:
293294
/*** Token with values **************************************************/
294295

295296
identifier:
296-
TOK_IDENTIFIER
297+
TOK_GCC_IDENTIFIER
298+
| TOK_MSC_IDENTIFIER
297299
| TOK_CPROVER_ID TOK_STRING
298300
{
299301
// construct an identifier from a string that would otherwise not be a
@@ -1362,7 +1364,7 @@ atomic_type_specifier:
13621364
;
13631365

13641366
msc_decl_identifier:
1365-
TOK_IDENTIFIER
1367+
TOK_MSC_IDENTIFIER
13661368
{
13671369
parser_stack($$).id(parser_stack($$).get(ID_identifier));
13681370
}
@@ -2285,9 +2287,14 @@ designator:
22852287
/*** Statements *********************************************************/
22862288

22872289
statement:
2290+
declaration_statement
2291+
| statement_attribute
2292+
| stmt_not_decl_or_attr
2293+
;
2294+
2295+
stmt_not_decl_or_attr:
22882296
labeled_statement
22892297
| compound_statement
2290-
| declaration_statement
22912298
| expression_statement
22922299
| selection_statement
22932300
| iteration_statement
@@ -2297,7 +2304,6 @@ statement:
22972304
| msc_asm_statement
22982305
| msc_seh_statement
22992306
| cprover_exception_statement
2300-
| statement_attribute
23012307
;
23022308

23032309
declaration_statement:
@@ -2309,8 +2315,30 @@ declaration_statement:
23092315
}
23102316
;
23112317

2318+
gcc_attribute_specifier_opt:
2319+
/* empty */
2320+
{
2321+
init($$);
2322+
}
2323+
| gcc_attribute_specifier
2324+
;
2325+
2326+
msc_label_identifier:
2327+
TOK_MSC_IDENTIFIER
2328+
| TOK_TYPEDEFNAME
2329+
;
2330+
23122331
labeled_statement:
2313-
identifier_or_typedef_name ':' statement
2332+
TOK_GCC_IDENTIFIER ':' gcc_attribute_specifier_opt stmt_not_decl_or_attr
2333+
{
2334+
// we ignore the GCC attribute
2335+
$$=$2;
2336+
statement($$, ID_label);
2337+
irep_idt identifier=PARSER.lookup_label(parser_stack($1).get(ID_C_base_name));
2338+
parser_stack($$).set(ID_label, identifier);
2339+
mto($$, $4);
2340+
}
2341+
| msc_label_identifier ':' statement
23142342
{
23152343
$$=$2;
23162344
statement($$, ID_label);

src/ansi-c/scanner.l

+4-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ int make_identifier()
8686
{
8787
parser_stack(yyansi_clval).id(ID_symbol);
8888
parser_stack(yyansi_clval).set(ID_C_base_name, final_base_name);
89-
return TOK_IDENTIFIER;
89+
return PARSER.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO ?
90+
TOK_MSC_IDENTIFIER : TOK_GCC_IDENTIFIER;
9091
}
9192
else
9293
{
@@ -112,7 +113,8 @@ int make_identifier()
112113
else
113114
{
114115
parser_stack(yyansi_clval).id(ID_symbol);
115-
return TOK_IDENTIFIER;
116+
return PARSER.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO ?
117+
TOK_MSC_IDENTIFIER : TOK_GCC_IDENTIFIER;
116118
}
117119
}
118120
}

0 commit comments

Comments
 (0)