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)