struct base { int a; }; struct derived { struct base base; int b; }; struct derived derived; struct base *base = &derived; I personally use that pattern in my code (in a bit more elaborate form) and so this change removes the warnings for those use cases, while still retaining it for everything else. Feel free to CC me on the mailing list if you have questions, suggestions or complaints.
Unified · Split
| @@ -3591,7 +3591,8 @@ static void cast_error(CType *st, CType *dt) · 3590 unmodified lines | |||
| 3591 | static void verify_assign_cast(CType *dt) | 3591 | static void verify_assign_cast(CType *dt) |
| 3592 | { | 3592 | { |
| 3593 | CType *st, *type1, *type2; | 3593 | CType *st, *type1, *type2; |
| 3594 | int dbt, sbt, qualwarn, lvl; | 3594 | Sym *sym; |
| 3595 | int dbt, sbt, qualwarn, lvl, compat; | ||
| 3595 | 3596 | ||
| 3596 | st = &vtop->type; /* source type */ | 3597 | st = &vtop->type; /* source type */ |
| 3597 | dbt = dt->t & VT_BTYPE; | 3598 | dbt = dt->t & VT_BTYPE; |
| @@ -3645,8 +3646,29 @@ static void verify_assign_cast(CType *dt) · 47 unmodified lines | |||
| 3645 | base types, though, in particular for unsigned enums | 3646 | base types, though, in particular for unsigned enums |
| 3646 | and signed int targets. */ | 3647 | and signed int targets. */ |
| 3647 | } else { | 3648 | } else { |
| 3648 | tcc_warning("assignment from incompatible pointer type"); | 3649 | compat = 0; |
| 3649 | break; | 3650 | /* Don't warn if the source struct (recursively) contains |
| 3651 | destination struct as the first member. */ | ||
| 3652 | if (dbt == VT_STRUCT && sbt == VT_STRUCT | ||
| 3653 | && !IS_UNION(type2->t) | ||
| 3654 | ) { | ||
| 3655 | sym = type2->ref->next; | ||
| 3656 | while (sym != NULL && (sym->type.t & VT_BTYPE) == VT_STRUCT | ||
| 3657 | ) { | ||
| 3658 | if (is_compatible_unqualified_types(type1, &sym->type) | ||
| 3659 | ) { | ||
| 3660 | compat = 1; | ||
| 3661 | break; | ||
| 3662 | } | ||
| 3663 | if (IS_UNION(sym->type.t)) | ||
| 3664 | break; | ||
| 3665 | sym = sym->type.ref->next; | ||
| 3666 | } | ||
| 3667 | } | ||
| 3668 | if( !compat ) { | ||
| 3669 | tcc_warning("assignment from incompatible pointer type"); | ||
| 3670 | break; | ||
| 3671 | } | ||
| 3650 | } | 3672 | } |
| 3651 | } | 3673 | } |
| 3652 | if (qualwarn) | 3674 | if (qualwarn) |