Use one more bit in AttributeDef to differenciate between declared function (only its prototype is known) and defined function (its body is also known). This allows to generate an error in cases like: int f(){return 0;} int f(){return 1;}
Unified · Split
| @@ -389,9 +389,10 @@ typedef struct AttributeDef { · 388 unmodified lines | |||
| 389 | func_export : 1, | 389 | func_export : 1, |
| 390 | func_import : 1, | 390 | func_import : 1, |
| 391 | func_args : 5, | 391 | func_args : 5, |
| 392 | func_proto : 1, | ||
| 392 | mode : 4, | 393 | mode : 4, |
| 393 | weak : 1, | 394 | weak : 1, |
| 394 | fill : 11; | 395 | fill : 10; |
| 395 | struct Section *section; | 396 | struct Section *section; |
| 396 | int alias_target; /* token */ | 397 | int alias_target; /* token */ |
| 397 | } AttributeDef; | 398 | } AttributeDef; |
| @@ -401,6 +402,7 @@ typedef struct AttributeDef { · 3 unmodified lines | |||
| 401 | #define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) | 402 | #define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) |
| 402 | #define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) | 403 | #define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) |
| 403 | #define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) | 404 | #define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) |
| 405 | #define FUNC_PROTO(r) (((AttributeDef*)&(r))->func_proto) | ||
| 404 | #define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) | 406 | #define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) |
| 405 | #define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) | 407 | #define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) |
| 406 | #define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) | 408 | #define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) |
| @@ -5818,6 +5818,10 @@ static int decl0(int l, int is_for_loop_init) · 5817 unmodified lines | |||
| 5818 | goto func_error1; | 5818 | goto func_error1; |
| 5819 | 5819 | ||
| 5820 | r = sym->type.ref->r; | 5820 | r = sym->type.ref->r; |
| 5821 | |||
| 5822 | if (!FUNC_PROTO(r)) | ||
| 5823 | tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); | ||
| 5824 | |||
| 5821 | /* use func_call from prototype if not defined */ | 5825 | /* use func_call from prototype if not defined */ |
| 5822 | if (FUNC_CALL(r) != FUNC_CDECL | 5826 | if (FUNC_CALL(r) != FUNC_CDECL |
| 5823 | && FUNC_CALL(type.ref->r) == FUNC_CDECL) | 5827 | && FUNC_CALL(type.ref->r) == FUNC_CDECL) |
| @@ -5836,6 +5840,7 @@ static int decl0(int l, int is_for_loop_init) · 12 unmodified lines | |||
| 5836 | tcc_error("incompatible types for redefinition of '%s'", | 5840 | tcc_error("incompatible types for redefinition of '%s'", |
| 5837 | get_tok_str(v, NULL)); | 5841 | get_tok_str(v, NULL)); |
| 5838 | } | 5842 | } |
| 5843 | FUNC_PROTO(type.ref->r) = 0; | ||
| 5839 | /* if symbol is already defined, then put complete type */ | 5844 | /* if symbol is already defined, then put complete type */ |
| 5840 | sym->type = type; | 5845 | sym->type = type; |
| 5841 | } else { | 5846 | } else { |
| @@ -5901,6 +5906,7 @@ static int decl0(int l, int is_for_loop_init) · 59 unmodified lines | |||
| 5901 | if ((type.t & VT_BTYPE) == VT_FUNC) { | 5906 | if ((type.t & VT_BTYPE) == VT_FUNC) { |
| 5902 | /* external function definition */ | 5907 | /* external function definition */ |
| 5903 | /* specific case for func_call attribute */ | 5908 | /* specific case for func_call attribute */ |
| 5909 | ad.func_proto = 1; | ||
| 5904 | type.ref->r = INT_ATTR(&ad); | 5910 | type.ref->r = INT_ATTR(&ad); |
| 5905 | } else if (!(type.t & VT_ARRAY)) { | 5911 | } else if (!(type.t & VT_ARRAY)) { |
| 5906 | /* not lvalue if array */ | 5912 | /* not lvalue if array */ |