https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100785
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P4 |P2 --- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- With: --- gcc/cfgexpand.c.jj 2021-05-20 09:03:54.147700369 +0200 +++ gcc/cfgexpand.c 2021-05-31 20:48:28.078548261 +0200 @@ -3082,6 +3082,7 @@ expand_asm_stmt (gasm *stmt) unsigned ninputs = gimple_asm_ninputs (stmt); unsigned nlabels = gimple_asm_nlabels (stmt); unsigned i; + bool error_seen = false; /* ??? Diagnose during gimplification? */ if (ninputs + noutputs + nlabels > MAX_RECOG_OPERANDS) @@ -3140,6 +3141,7 @@ expand_asm_stmt (gasm *stmt) { /* ??? Diagnose during gimplification? */ error ("unknown register name %qs in %<asm%>", regname); + error_seen = true; } else if (j == -4) { @@ -3202,7 +3204,10 @@ expand_asm_stmt (gasm *stmt) && REG_P (DECL_RTL (output_tvec[j])) && HARD_REGISTER_P (DECL_RTL (output_tvec[j])) && output_hregno == REGNO (DECL_RTL (output_tvec[j]))) - error ("invalid hard register usage between output operands"); + { + error ("invalid hard register usage between output operands"); + error_seen = true; + } /* Verify matching constraint operands use the same hard register and that the non-matching constraint operands do not use the same @@ -3225,13 +3230,19 @@ expand_asm_stmt (gasm *stmt) } if (i == match && output_hregno != input_hregno) - error ("invalid hard register usage between output operand " - "and matching constraint operand"); + { + error ("invalid hard register usage between output " + "operand and matching constraint operand"); + error_seen = true; + } else if (early_clobber_p && i != match && output_hregno == input_hregno) - error ("invalid hard register usage between earlyclobber " - "operand and input operand"); + { + error ("invalid hard register usage between " + "earlyclobber operand and input operand"); + error_seen = true; + } } } @@ -3307,7 +3318,10 @@ expand_asm_stmt (gasm *stmt) op = validize_mem (op); if (! allows_reg && !MEM_P (op)) - error ("output number %d not directly addressable", i); + { + error ("output number %d not directly addressable", i); + error_seen = true; + } if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode) || GET_CODE (op) == CONCAT) { @@ -3347,6 +3361,19 @@ expand_asm_stmt (gasm *stmt) inout_opnum.safe_push (i); } + const char *str = gimple_asm_string (stmt); + if (error_seen) + { + ninputs = 0; + noutputs = 0; + inout_opnum.truncate (0); + output_rvec.truncate (0); + clobber_rvec.truncate (0); + constraints.truncate (0); + CLEAR_HARD_REG_SET (clobbered_regs); + str = ""; + } + auto_vec<rtx, MAX_RECOG_OPERANDS> input_rvec; auto_vec<machine_mode, MAX_RECOG_OPERANDS> input_mode; @@ -3405,7 +3432,7 @@ expand_asm_stmt (gasm *stmt) } /* For in-out operands, copy output rtx to input rtx. */ - unsigned ninout = inout_opnum.length(); + unsigned ninout = inout_opnum.length (); for (i = 0; i < ninout; i++) { int j = inout_opnum[i]; @@ -3459,7 +3486,7 @@ expand_asm_stmt (gasm *stmt) rtx body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode : GET_MODE (output_rvec[0])), - ggc_strdup (gimple_asm_string (stmt)), + ggc_strdup (str), "", 0, argvec, constraintvec, labelvec, locus); MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt); ICEs on: /* PR inline-asm/100785 */ struct S { int a : 1; }; void foo (struct S *x) { __asm__ ("" : "+m" (x->a)); /* { dg-error "not directly addressable" } */ } void bar (struct S *x) { __asm__ ("" : "=m" (x->a)); /* { dg-error "not directly addressable" } */ } void baz (struct S *x) { __asm__ ("" : : "m" (x->a)); /* { dg-error "not directly addressable" } */ } in foo and bar are fixed, but baz is actually not diagnosed at all and just ICEs. So bumping priority to P2, as this isn't error-recovery in the baz case anymore.