From d9ec17d33427fce6f73c5b5bb9646d3b077bb4e4 Mon Sep 17 00:00:00 2001 From: DFP Date: Fri, 14 Nov 2025 08:55:55 +0100 Subject: [PATCH] Relaxed the 'incompatible pointer type' warning a bit Do not emit that warning when the source struct (recursively) contains destination struct as the first member. For example, in this case the warning would have been emitted before, and is not anymore: 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. --- tccgen.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tccgen.c b/tccgen.c index 587c1892..f8e81b81 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3591,7 +3591,8 @@ static void cast_error(CType *st, CType *dt) static void verify_assign_cast(CType *dt) { CType *st, *type1, *type2; - int dbt, sbt, qualwarn, lvl; + Sym *sym; + int dbt, sbt, qualwarn, lvl, compat; st = &vtop->type; /* source type */ dbt = dt->t & VT_BTYPE; @@ -3645,8 +3646,29 @@ static void verify_assign_cast(CType *dt) base types, though, in particular for unsigned enums and signed int targets. */ } else { - tcc_warning("assignment from incompatible pointer type"); - break; + compat = 0; + /* Don't warn if the source struct (recursively) contains + destination struct as the first member. */ + if (dbt == VT_STRUCT && sbt == VT_STRUCT + && !IS_UNION(type2->t) + ) { + sym = type2->ref->next; + while (sym != NULL && (sym->type.t & VT_BTYPE) == VT_STRUCT + ) { + if (is_compatible_unqualified_types(type1, &sym->type) + ) { + compat = 1; + break; + } + if (IS_UNION(sym->type.t)) + break; + sym = sym->type.ref->next; + } + } + if( !compat ) { + tcc_warning("assignment from incompatible pointer type"); + break; + } } } if (qualwarn)