[llvm-dev] [RFC] Formalizing FileCheck Features

via llvm-dev llvm-dev at lists.llvm.org
Fri May 25 07:40:46 PDT 2018


Thanks Joel and Chris, comments inline.

>> CHECK: Scans the search range for a pattern match. Fails if no match
>> is found.  The end of the match range becomes the start of the search
>> range for subsequent directives.
>>
>> CHECK-SAME: Like CHECK, plus there must be zero newlines prior to the
>> start of the match range.
>
> ... within the search range.

Yes, thanks.

> Should it be possible for CHECK-SAME match range to include newlines?
 
It is possible to write a regex that matches newlines.  Doing that in
CHECK-SAME seems a bit odd but I don't think it's worth trying to forbid
it.

>> CHECK-NEXT: Like CHECK, plus there must be exactly one newline prior
>> to the start of the match range.
>
> ... within the search range.

Again yes.

> Your choice to talk about the match range rather than the search range
> for CHECK-SAME and CHECK-NEXT implies you like the current behavior
> that extends the search range beyond these match range restrictions and
> then complains if the match range restrictions aren't met.  For example,
> CHECK-SAME searches past the newline and then complains if the match
> range starts after the newline.  Is that what you prefer?
>
> I'd note that, in the case of CHECK-NEXT, that choice can restrict what
> CHECK-NEXT can match.  That is, it will complain about a match on the
> previous line rather than skip it and look on the next line.

Ah, so we could define CHECK-NEXT as: move the start of the search
range past the first newline, then behaves as CHECK-SAME?

But, appending {{.*$}} to the previous pattern should have the same
effect if you have a CHECK-NEXT that runs into that problem.  And I
do think it's valuable for SAME and NEXT to tell you they found
matches but not on the line you asked for.  So I'd prefer to leave
these defined as they are.

>> CHECK-NOT: A sequence of NOT directives forms a NOT Group. The group
>> is not executed immediately; instead the next non-NOT directive is
>> executed first, and the start of that directive's match range becomes
>> the end of the NOT Group's search range.
>
> Based on the following, that wording is not quite right when a DAG
> group follows, so there should probably be some note about that here.

So, "the next non-NOT directive or DAG group is executed ... the start
of that directive or group's match range ..." ?
 
>>  (If the next directive is
>> LABEL, it has already executed and has a match range, which is already
>> the end of the search range.)  After the NOT Group's search range is
>> defined, each NOT directive scans the range for a match, and fails if
>> a match is found.
>>
>> CHECK-DAG: A sequence of DAG directives forms a DAG Group. The group
>> is not executed immediately; instead the next non-DAG directive is
>> executed first, and the start of that directive's match range becomes
>> the end of the DAG Group's search range.
>
> That's definitely a change from the current behavior.  Currently, the
> DAG group finds its own end based on the farthest match.

Oh good catch.  Copy-thinko from the NOT description.  NOT is the only
kind of directive that has deferred execution.
 
>>  If the next directive is
>> CHECK-NOT, the end of the DAG Group's search range is
>> unaffected.
>
> Unaffected means that it's as if there's no following directive?  So
> next CHECK-LABEL (possibly the implicit one at EOF)?  What if there's
> a CHECK, CHECK-NEXT, or CHECK-SAME after all the DAGs and NOTs?

If DAG doesn't have deferred execution then the end of the search range
is the next (explicit or implicit) CHECK-LABEL point, end of story.
 
>>  After all DAG directives run, the
>> match range for the entire DAG Group extends from the start of the
>> earliest match to the end of the latest match.  The end of that match
>> range becomes the start of the search range for subsequent directives.
>
> That last sentence contradicts the first few sentences: the subsequent
> directive has already been matched.

Right, fixing the previous bug means this sentence says the right thing.

> One point not addressed here is the start of the DAG group's search
> range.  Currently, if the DAG group is preceded by a NOT group
> preceded by a DAG group, the last DAG group's search range starts at
> the start of the first DAG group's match range.  Any matches in the
> first DAG group's match range produces a reordering error.  This is
> somewhat similar to the CHECK-SAME and CHECK-NEXT behavior I mentioned
> earlier: the search ranges permit invalid match ranges and then
> complain about them in an effort to diagnose mistakes.  However, that
> restricts what can be matched.
>
> I'm not claiming that either behavior is best.  It's not clear to me.
> The best use of DAG-NOT-DAG is very confusing to me.  An effort to
> prescribe the right semantics to it needs to be informed by real use
> cases, in my opinion.

I did some email archaeology, and found this exchange on llvm-dev between
myself and Michael Liao (original DAG implementor) 13 Mar 2016:

pr> Commentary in FileCheck itself can easily be interpreted to mean the
pr> intent was that –NOT would scan the region between the points defined
pr> by the last match of the preceding DAG group (which the code gets
pr> right) and the first match of the following DAG group (which the code
pr> does not get right). But the commentary is not really that clear.

ml> That's the intention of the original design. CHECK-NOT never occurs
ml> before we find the start point (the start of file by default) and end
ml> point (the end of file by default.) All other points are through other
ml> CHECKs, including CHECK-DAG but excluding CHECK-NOT.  So that, if you
ml> use CHECK-NOT, you need to be aware of how that range is defined. As
ml> CHECK-DAG pattern matches a group of pattern in any order, the match
ml> point of that group of CHECK-DAG (a consecutive CHECK-DAGs without any
ml> other CHECKs interleaved) is always the point where one of that pgroup
ml> is matched. If one CHECK-DAG is separated by any other CHECKs
ml> (including CHECK-NOT) from preceding CHECK-DAGs, it is not in the
ml> preceding group of CHECK-DAG. That's way how we could check the order
ml> where a group of patterns should never occur before another group of
ml> patterns.

So, I believe my specification for the interaction between DAG and NOT
does match the original intent.  Regarding the diagnostic aid, it does
make some sequences really hard to match, and I don't have a general
idea how to fix that (versus {{.*$}} for the similar NEXT situation).
It's also a reasonable continuation of the behavior of plain CHECK, in 
that a second CHECK doesn't search the prior text to complain about 
ordering issues.

SAME and NEXT are, I think, a different category; that has to do with
line-breaks that are not explicitly described by user-written patterns,
and my own experience is that it's helpful to be told that something
matches but isn't on the line I expected.

So, I don't have a definitive answer for changing DAG-NOT-DAG, but
intuitively the spec makes sense to me and my inclination is to think
the diagnostic isn't hugely valuable.

>> Putting CHECK-SAME and CHECK-NEXT after CHECK-DAG now has defined
>> behavior, but it's unlikely to be useful.
>
> I believe they had predictable behavior before (their search ranges
> started at the end of the match range for the entire CHECK-DAG), but
> it's different with the above description (they define the end of the
> search range for the preceding CHECK-DAG group).

You're right, it was predictable before, and I am fixing the bug where
the directive after DAG gets executed first so the range isn't affected.

Taking Chris Lattner's point into consideration, we might want to say
SAME or NEXT after a DAG should be an error.  But we could also leave
that for a later round.

--paulr

P.S. I am away next week but expect to keep an eye on the lists.



More information about the llvm-dev mailing list