Skip to content

Commit cc7f915

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.c#L5553 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 5e145e4 commit cc7f915

File tree

12 files changed

+124
-54
lines changed

12 files changed

+124
-54
lines changed

regression/ansi-c/label1/main.c

Lines changed: 14 additions & 0 deletions
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

Lines changed: 15 additions & 0 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 4 additions & 4 deletions
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;
Lines changed: 4 additions & 3 deletions
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

Lines changed: 4 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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/safe-dereferences/main.c

Lines changed: 2 additions & 2 deletions
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

Lines changed: 34 additions & 6 deletions
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
@@ -291,7 +292,8 @@ grammar:
291292
/*** Token with values **************************************************/
292293

293294
identifier:
294-
TOK_IDENTIFIER
295+
TOK_GCC_IDENTIFIER
296+
| TOK_MSC_IDENTIFIER
295297
| TOK_CPROVER_ID TOK_STRING
296298
{
297299
$$=$1;
@@ -1377,7 +1379,7 @@ atomic_type_specifier:
13771379
;
13781380

13791381
msc_decl_identifier:
1380-
TOK_IDENTIFIER
1382+
TOK_MSC_IDENTIFIER
13811383
{
13821384
parser_stack($$).id(parser_stack($$).get(ID_identifier));
13831385
}
@@ -2300,9 +2302,14 @@ designator:
23002302
/*** Statements *********************************************************/
23012303

23022304
statement:
2305+
declaration_statement
2306+
| statement_attribute
2307+
| stmt_not_decl_or_attr
2308+
;
2309+
2310+
stmt_not_decl_or_attr:
23032311
labeled_statement
23042312
| compound_statement
2305-
| declaration_statement
23062313
| expression_statement
23072314
| selection_statement
23082315
| iteration_statement
@@ -2312,7 +2319,6 @@ statement:
23122319
| msc_asm_statement
23132320
| msc_seh_statement
23142321
| cprover_exception_statement
2315-
| statement_attribute
23162322
;
23172323

23182324
declaration_statement:
@@ -2324,8 +2330,30 @@ declaration_statement:
23242330
}
23252331
;
23262332

2333+
gcc_attribute_specifier_opt:
2334+
/* empty */
2335+
{
2336+
init($$);
2337+
}
2338+
| gcc_attribute_specifier
2339+
;
2340+
2341+
msc_label_identifier:
2342+
TOK_MSC_IDENTIFIER
2343+
| TOK_TYPEDEFNAME
2344+
;
2345+
23272346
labeled_statement:
2328-
identifier_or_typedef_name ':' statement
2347+
TOK_GCC_IDENTIFIER ':' gcc_attribute_specifier_opt stmt_not_decl_or_attr
2348+
{
2349+
// we ignore the GCC attribute
2350+
$$=$2;
2351+
statement($$, ID_label);
2352+
irep_idt identifier=PARSER.lookup_label(parser_stack($1).get(ID_C_base_name));
2353+
parser_stack($$).set(ID_label, identifier);
2354+
mto($$, $4);
2355+
}
2356+
| msc_label_identifier ':' statement
23292357
{
23302358
$$=$2;
23312359
statement($$, ID_label);

0 commit comments

Comments
 (0)