On Sat, Jan 24, 2026 at 04:34:20PM +0000, Richard Sandiford wrote:
> It might be worth expanding the comment to say that the possibility of
> regexp errors means that a binary search wouldn't work.  It would then
> be more obvious that the linear search is used for correctness,
> rather than just simplicity.

Done.

> Minor, but since $up_functions($name) is now used multiple times,
> it might be worth storing it in a "body" variable:
> 
>     set body $up_functions($name)
> 
> and replacing existing uses.  Then the catch above could be written:
> 
>     if { ![catch { regexp "^$short_regexp" $body } res] && $res } {
>         break
>     }
> 
> without the need for match_found.

Agreed.  I hadn't previously understood how to use the resultVarName argument
for catch.

> 
> > +   set ok_index [string last "\n" $body_regexp $ok_index-1]
> > +      }
> > +      set head [string range $body_regexp 0 $ok_index]
> > +      set tail [string range $body_regexp $ok_index+1 end]
> > +      verbose -log "initial matched regexp:\n$head"
> > +      verbose -log "mismatch in remaining regexp:\n$tail"
> > +      verbose -log "against:\n$up_functions($name)"
> 
> I suppose there are two cases in which one of these regexps could
> be empty:
> 
> (a) $head could be empty when even the smallest valid slice of
>     $body_regexp doesn't match.  The original message might then
>     be clearer, but maybe not.
> 
> (b) $tail could be empty when the whole of $body_regexp matches,
>     so that it's the final "$" that causes the mismatch.  It might
>     then be clearer to say that the regexp matches but is incomplete.

I've added separate output for those two cases.  I also adjusted the wording
for the compared output.

> 
> OK with the comment and catch changes, and with whatever you feel is
> best for the new messages (including keeping the ones in the patch).
> 
> Thanks,
> Richard

I've committed the below version.  As before, I retested this by taking working
tests and deleting a line from the start, end, or middle of the regexp,
including a line from the middle of a group of alternative sequences.  I also
checked the output for an empty regexp.

Thanks,
Alice

---

When a check-function-bodies test fails, it can sometimes be hard to
identify which part of a large function regexp is causing the failure.
To aid debugging these failures, find the largest initial set of lines
that matches the function, and log this separately from the remainder of
the regexp.

Additionally, add a newline before logging the function bodies, so that
the first line has the same indentation as the rest of that function.


gcc/testsuite/ChangeLog:

        * lib/scanasm.exp (check_function_body): Log matching portion
        of body_regexp separately.


diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 
bcd22c2d7e4ef95c3d918438ffd7c0c2505c74d9..b0df0c6ba28c4dd92494a25a5a896cc40f36fd2a
 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -981,10 +981,38 @@ proc check_function_body { functions name body_regexp } {
     if { ![info exists up_functions($name)] } {
        return 0
     }
-    set fn_res [regexp "^$body_regexp\$" $up_functions($name)]
+    set body $up_functions($name)
+    set fn_res [regexp "^$body_regexp\$" $body]
     if { !$fn_res } {
-      verbose -log "expected: $body_regexp"
-      verbose -log "found: $up_functions($name)"
+      # Find the longest initial set of lines in body_regexp that matches the
+      # function.  We can't just use a binary search here, because adding more
+      # lines to a broken regexp might make it start to match.
+      # Unfortunately this makes runtime quadratic in the number of lines, but
+      # failures in large check-function-body regexps are hopefully rare.
+      set ok_index [string length $body_regexp]
+      incr ok_index -1
+      while { $ok_index >= 0 } {
+       set short_regexp [string range $body_regexp 0 $ok_index]
+       set match_found 0
+       # Not all initial sets of lines are valid.  Ignore any broken regexps.
+       if { ![catch { regexp "^$short_regexp" $body } res] && $res } {
+         break
+       }
+       set ok_index [string last "\n" $body_regexp $ok_index-1]
+      }
+      set head [string range $body_regexp 0 $ok_index]
+      set tail [string range $body_regexp $ok_index+1 end]
+      if { $ok_index == -1 } {
+       verbose -log "no initial matching lines"
+      } else {
+       verbose -log "initial matched regexp:\n$head"
+      }
+      if { [string length $tail] == 0 } {
+       verbose -log "excess lines found after matching regexp\n"
+      } else {
+       verbose -log "mismatch in remaining regexp:\n$tail"
+      }
+      verbose -log "compared against output:\n$body"
     }
     return $fn_res
 }

Reply via email to