Skip to content

Commit a7cdd03

Browse files
committed
incomplete object at file scope.
1 parent 43766d1 commit a7cdd03

9 files changed

Lines changed: 110689 additions & 110978 deletions

File tree

manual.md

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ In C99/C23, there are two related but distinct concepts:
258258
- **VM types** (`int (*p)[n]`) - any type derived from a runtime-sized array, including pointers to VLAs. **Mandatory** in C23 even when `__STDC_NO_VLA__` is defined.
259259

260260
Cake supports **VM types** and converts them to C89-compatible code.
261-
Cake does **not** support VLA objects - a diagnostic is emitted instead, pointing to the VM type alternative.
261+
Cake does **not** support VLA objects.
262262

263263
#### VM type pointer declarations
264264

@@ -278,68 +278,6 @@ int main() {
278278
```
279279
<button onclick="Try(this)">try</button>
280280

281-
The C89 output captures the dimensions into snapshot variables at declaration time,
282-
so that later mutation of `n` or `m` does not affect the allocation size or `sizeof` results:
283-
284-
```c
285-
int __v0;
286-
int __v1;
287-
int *p;
288-
__v0 = (n);
289-
__v1 = (m);
290-
p = (int *)malloc(sizeof(int) * __v0 * __v1);
291-
printf("%zu\n", (sizeof(int) * __v0 * __v1));
292-
free(p);
293-
```
294-
295-
#### VM type function parameters
296-
297-
VM pointer parameters are also rewritten to flat pointers. Subscript expressions
298-
through the pointer are linearised automatically.
299-
300-
```c
301-
#include <stdlib.h>
302-
#include <stdio.h>
303-
304-
void fill(int n, int m, int (*grid)[n][m])
305-
{
306-
int i, j;
307-
for (i = 0; i < n; i++)
308-
for (j = 0; j < m; j++)
309-
(*grid)[i][j] = i * 10 + j;
310-
}
311-
312-
int main() {
313-
int n = 3, m = 4;
314-
int (*p)[n][m] = malloc(sizeof *p);
315-
fill(n, m, p);
316-
free(p);
317-
}
318-
```
319-
<button onclick="Try(this)">try</button>
320-
321-
C89 output for `fill`:
322-
323-
```c
324-
void fill(int n, int m, int *grid)
325-
{
326-
int i, j;
327-
for (i = 0; i < n; i++)
328-
for (j = 0; j < m; j++)
329-
((int*)grid)[(i) * m + (j)] = i * 10 + j;
330-
}
331-
```
332-
333-
#### VLA objects are not supported
334-
335-
```c
336-
int main() {
337-
int n = 5;
338-
int a[n]; /* error: variable length arrays are not supported;
339-
use a pointer to a variably modified type instead
340-
(e.g. 'int (*p)[n] = malloc(sizeof *p);') */
341-
}
342-
```
343281

344282
### C99 Flexible array members
345283

src/cakeconfig.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//This was generated by running cake -autoconfig
22
//This file was generated reading the variable INCLUDE inside Visual Studio Command Prompt.
33
//echo %INCLUDE%
4-
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.44.35207/include/"
5-
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.44.35207/ATLMFC/include/"
6-
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Auxiliary/VS/include/"
4+
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/include/"
5+
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/ATLMFC/include/"
6+
#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include/"
77
#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.26100.0/ucrt/"
88
#pragma dir "C:/Program Files (x86)/Windows Kits/10//include/10.0.26100.0//um/"
99
#pragma dir "C:/Program Files (x86)/Windows Kits/10//include/10.0.26100.0//shared/"
1010
#pragma dir "C:/Program Files (x86)/Windows Kits/10//include/10.0.26100.0//winrt/"
1111
#pragma dir "C:/Program Files (x86)/Windows Kits/10//include/10.0.26100.0//cppwinrt/"
12-
#pragma dir "C:/Program Files (x86)/Windows Kits/NETFXSDK/4.8/include/um/"

src/file.c

Lines changed: 3 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,5 @@
1+
char str[]; /* incomplete type */
12

2-
#include <stdio.h>
3-
#include <stdlib.h>
4-
5-
void print2D(int n, int m, int a[n][m])
6-
{
7-
for (int i = 0; i < n; i++)
8-
{
9-
for (int j = 0; j < m; j++)
10-
{
11-
printf("%d ", a[i][j]);
12-
}
13-
printf("\n");
14-
}
15-
}
16-
17-
void print1D(int n, int a[n])
18-
{
19-
for (int i = 0; i < n; i++)
20-
{
21-
printf(" %d", a[i]);
22-
}
23-
printf("\n");
24-
}
25-
26-
void test_1d(int n)
27-
{
28-
int (*p)[n] = malloc(sizeof * p);
29-
int i;
30-
for (i = 0; i < n; i++)
31-
(*p)[i] = i + 1;
32-
for (i = 0; i < n; i++)
33-
printf("%d ", (*p)[i]);
34-
printf("\n");
35-
free(p);
36-
}
37-
38-
void test_2d(int n, int m)
39-
{
40-
int (*p)[n][m] = malloc(sizeof * p);
41-
int i, j;
42-
for (i = 0; i < n; i++)
43-
for (j = 0; j < m; j++)
44-
(*p)[i][j] = i * m + j;
45-
for (i = 0; i < n; i++)
46-
{
47-
for (j = 0; j < m; j++)
48-
printf("%3d", (*p)[i][j]);
49-
printf("\n");
50-
}
51-
free(p);
52-
}
53-
54-
void test_sizeof_stable(int n, int m)
55-
{
56-
int (*p)[n][m] = malloc(sizeof * p);
57-
size_t sz = sizeof(*p);
58-
printf("sizeof(*p) = %zu\n", sz);
59-
n = 999;
60-
m = 999;
61-
printf("sizeof(*p) after n=999,m=999 = %zu\n", sizeof(*p));
62-
printf("same? %d\n", sz == sizeof(*p));
63-
free(p);
64-
}
65-
66-
void fill(int n, int m, int (*grid)[n][m])
67-
{
68-
int i, j;
69-
for (i = 0; i < n; i++)
70-
for (j = 0; j < m; j++)
71-
(*grid)[i][j] = i * 10 + j;
72-
}
73-
74-
void print_grid(int n, int m, int (*grid)[n][m])
75-
{
76-
int i, j;
77-
for (i = 0; i < n; i++)
78-
{
79-
for (j = 0; j < m; j++)
80-
printf("%3d", (*grid)[i][j]);
81-
printf("\n");
82-
}
83-
}
84-
85-
void test_vm_param(int n, int m)
86-
{
87-
int (*p)[n][m] = malloc(sizeof * p);
88-
fill(n, m, p);
89-
print_grid(n, m, p);
90-
free(p);
91-
}
92-
93-
void test_multiple(int n, int m)
94-
{
95-
int (*a)[n] = malloc(sizeof * a);
96-
int (*b)[m] = malloc(sizeof * b);
97-
int i;
98-
for (i = 0; i < n; i++) (*a)[i] = i;
99-
for (i = 0; i < m; i++) (*b)[i] = i + 100;
100-
printf("a[0]=%d a[n-1]=%d\n", (*a)[0], (*a)[n - 1]);
101-
printf("b[0]=%d b[m-1]=%d\n", (*b)[0], (*b)[m - 1]);
102-
free(a);
103-
free(b);
104-
}
105-
106-
void test_mixed_dims(int n)
107-
{
108-
int (*p)[4][n] = malloc(sizeof * p);
109-
int i, j;
110-
for (i = 0; i < 4; i++)
111-
for (j = 0; j < n; j++)
112-
(*p)[i][j] = i * n + j;
113-
for (i = 0; i < 4; i++)
114-
{
115-
for (j = 0; j < n; j++)
116-
printf("%3d", (*p)[i][j]);
117-
printf("\n");
118-
}
119-
free(p);
120-
}
121-
122-
void test_reassign(int n)
123-
{
124-
int (*p)[n] = malloc(sizeof * p);
125-
printf("sizeof(*p) first = %zu\n", sizeof(*p));
126-
free(p);
127-
n = 2; /* n changes */
128-
p = malloc(sizeof * p); /* new allocation — but snapshot is fixed */
129-
printf("sizeof(*p) second = %zu\n", sizeof(*p));
130-
free(p);
131-
}
132-
133-
int main(void)
134-
{
135-
printf("=== 1. 1-D VM pointer ===\n");
136-
test_1d(5);
137-
138-
printf("=== 2. 2-D VM pointer ===\n");
139-
test_2d(3, 4);
140-
141-
printf("=== 3. sizeof stability ===\n");
142-
test_sizeof_stable(3, 4);
143-
144-
printf("=== 4. VM parameter ===\n");
145-
test_vm_param(3, 4);
146-
147-
printf("=== 5. Multiple VM pointers ===\n");
148-
test_multiple(4, 3);
149-
150-
printf("=== 6. Mixed constant/runtime dims ===\n");
151-
test_mixed_dims(3);
152-
153-
printf("=== 7. Reassignment ===\n");
154-
test_reassign(5);
155-
156-
return 0;
157-
}
3+
char str[] = "initializer"; /* complete type */
1584

5+
void main(void) {}

src/lib.c

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29026,7 +29026,7 @@ void defer_start_visit_declaration(struct defer_visit_ctx* ctx, struct declarati
2902629026

2902729027
//#pragma once
2902829028

29029-
#define CAKE_VERSION "0.12.86"
29029+
#define CAKE_VERSION "0.12.87"
2903029030

2903129031

2903229032

@@ -29220,7 +29220,7 @@ static void check_func_open_brace_style(struct parser_ctx* ctx, struct token* to
2922029220

2922129221
static void check_func_close_brace_style(struct parser_ctx* ctx, struct token* token)
2922229222
{
29223-
29223+
2922429224
}
2922529225

2922629226

@@ -31881,7 +31881,7 @@ struct init_declarator* _Owner _Opt init_declarator(struct parser_ctx* ctx,
3188131881
type_is_vm(&p_init_declarator->p_declarator->type))
3188231882
{
3188331883
/*
31884-
MSVC accepts this as constant expression. Cake does not.
31884+
MSVC accepts this as constant expression. Cake does not.
3188531885
static_assert(&((struct X { int i; }*) 0)->i) == 0);
3188631886

3188731887

@@ -31933,20 +31933,34 @@ struct init_declarator* _Owner _Opt init_declarator(struct parser_ctx* ctx,
3193331933
break;
3193431934

3193531935
case SIZEOF_RESULT_INCOMPLETE:
31936-
31936+
3193731937
if (p_init_declarator->p_declarator->type.storage_class_specifier_flags & STORAGE_SPECIFIER_EXTERN)
3193831938
{
3193931939
/* extern variables do not need to be complete */
3194031940
}
31941+
else if (ctx->scopes.tail->scope_level == 0)
31942+
{
31943+
/*
31944+
FILE SCOPE is diferent here,.
31945+
Incomplete objects at file scope are tentatives
31946+
(cake needs a last pass to detect this problem)
31947+
*/
31948+
/*
31949+
char str[]; //not an error
31950+
char str[] = "abc"; complete type
31951+
int main() {}
31952+
*/
31953+
}
3194131954
else
3194231955
{
3194331956
compiler_diagnostic(C_ERROR_STORAGE_SIZE,
3194431957
ctx,
3194531958
p_init_declarator->p_declarator->name_opt, NULL,
3194631959
"storage size of '%s' isn't known because the type is incomplete",
3194731960
p_init_declarator->p_declarator->name_opt->lexeme);
31961+
throw;
3194831962
}
31949-
throw;
31963+
3195031964
case SIZEOF_RESULT_FUNCTION:
3195131965
break;
3195231966
}
@@ -34776,16 +34790,16 @@ struct function_declarator* declarator_find_function_declarator(const struct dec
3477634790
{
3477734791
if (p_declarator->direct_declarator->declarator)
3477834792
return declarator_find_function_declarator(p_declarator->direct_declarator->declarator);
34779-
34793+
3478034794
if (p_declarator->direct_declarator->function_declarator)
3478134795
{
3478234796
if (p_declarator->direct_declarator->function_declarator->direct_declarator &&
3478334797
p_declarator->direct_declarator->function_declarator->direct_declarator->declarator)
3478434798
{
34785-
struct function_declarator* p =
34799+
struct function_declarator* p =
3478634800
declarator_find_function_declarator(p_declarator->direct_declarator->function_declarator->direct_declarator->declarator);
34787-
if (p)
34788-
return p;
34801+
if (p)
34802+
return p;
3478934803
}
3479034804

3479134805
return p_declarator->direct_declarator->function_declarator;
@@ -59521,22 +59535,23 @@ bool type_is_vm(const struct type* p_type)
5952159535
while (p)
5952259536
{
5952359537
switch (p->category)
59524-
{
59538+
{
5952559539
case TYPE_CATEGORY_ARRAY:
5952659540
if (p->array_num_elements > 0)
59527-
{
59541+
{
5952859542
/* constant size */
5952959543
}
5953059544
else
5953159545
{
59532-
if (p->p_array_num_elements_expression == NULL) {
59546+
if (p->p_array_num_elements_expression == NULL)
59547+
{
5953359548
/*
59534-
* size is unknown but not vm.
59549+
* size is unknown but not vm.
5953559550
* int a[]
5953659551
*/
5953759552
}
5953859553
else
59539-
return true;
59554+
return true;
5954059555
}
5954159556
break;
5954259557

@@ -59554,7 +59569,7 @@ bool type_is_vm(const struct type* p_type)
5955459569
}
5955559570
break;
5955659571

59557-
case TYPE_CATEGORY_ITSELF:
59572+
case TYPE_CATEGORY_ITSELF:
5955859573
case TYPE_CATEGORY_POINTER:
5955959574
break;
5956059575
}
@@ -60989,8 +61004,12 @@ enum sizeof_result type_get_sizeof(const struct type* p_type, size_t* size, enum
6098961004
else
6099061005
{
6099161006
if (p_type->array_num_elements <= 0)
60992-
return SIZEOF_RESULT_RUNTIME;
61007+
{
61008+
if (p_type->p_array_num_elements_expression == NULL)
61009+
return SIZEOF_RESULT_INCOMPLETE;
6099361010

61011+
return SIZEOF_RESULT_RUNTIME;
61012+
}
6099461013
unsigned long long arraysize = p_type->array_num_elements;
6099561014
struct type type = get_array_item_type(p_type);
6099661015

0 commit comments

Comments
 (0)