how to implement "statement P is followed by statement Q" matcher?

I recently had to go through a bit of manual coding in order to match
this in clang-tidy:

if (expr)
  return true;
return false;

What I really wanted was to be able to write something like this:

compoundStmt(
  isFollowedBy(
    ifStmt(
      hasThen(returnStmt(has(booleanLiteral(equals(true))))),
      unless(hasElse(anything()))),
    returnStmt(has(booleanLiteral(equals(false))))
  )
)

There are matchers that tell me if a compound statment has *any*
substatement, but there aren't any matchers that allow me to specify
the order in which related statements appear within a compound
statement.

(Aside: note the heavy-handed use of the has() matcher above on a
returnStmt. There's no way to access the return expression directly
on a returnStmt.)

In my case I really needed an "isFollowedBy" style matcher, because I
didn't want to match this:

if (expr)
  return true;
doSomethingElse();
return false;

However, I can easily see people wanting to match a compound statement
that has two related statements in a particular order, but possibly
with other statements in between.

I'm interested in hearing thoughts on such a squential matcher
"isFollowedBy" and how I would implement such a thing. So far my
forays into matchers have been really small and I haven't yet learned
the subtleties or the full vocabulary of the matcher macros.

PS: Mail filters are blocking my messages, so ignore this, its
only for them. Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Phasellus consequat ullamcorper mollis. Sed blandit semper tortor
ultricies dictum. Proin hendrerit et quam in sagittis. Maecenas vel
blandit ante, in auctor sem. Phasellus condimentum leo vel finibus
viverra. Duis fermentum sollicitudin est, ac iaculis lectus auctor vel.
Nam condimentum nulla feugiat, venenatis nibh a, elementum nulla. Nulla
vitae malesuada eros. Nulla cursus maximus ligula non hendrerit.

Curabitur lobortis nulla vel sapien posuere, id aliquam orci
bibendum. Vestibulum at vulputate risus. Proin in purus commodo,
tempus lectus vitae, faucibus nunc. Aenean congue faucibus elit, sit
amet facilisis nibh ultrices eget. Nam pulvinar leo ac nunc ultricies,
nec tincidunt nulla tincidunt. Etiam placerat felis tellus, ut ultricies
nunc ultricies quis. In placerat sapien nec ultricies mattis. Integer
sed tempor orci, ac imperdiet orci. Integer ac augue et augue convallis
faucibus.

I don’t think you’d really be able to do this with matchers without major modifications to the matcher architecture.

Your best bet would be - I believe - to only have the ifStmt(…) as your matcher, and do the “isFollowedBy” logic in the callback. You’ll also need to bind the containing CompoundStmt.

In article <1432806087.2498925.280264065.1368E918@webmail.messagingengine.com>,
    Gabor Kozar <kozargabor@fastmail.fm> writes:

I don't think you'd really be able to do this with matchers without
major modifications to the matcher architecture.

Why do you say that? All the information is available from within
CompoundStmt provided I have the other two matchers. That's what I
currently do now in the callback -- walk the CompoundStmt looking for
the two consecutive statements that match my criteria (simplified and
hard-coded for my case):

  CompoundStmt::const_body_iterator BeforeIt = Compound->body_begin();
  CompoundStmt::const_body_iterator AfterIt = Compound->body_begin();
  for (++AfterIt;
       AfterIt != Compound->body_end() && *BeforeIt != Ret;
       ++BeforeIt, ++AfterIt) {
    if (auto *If = dyn_cast<IfStmt>(*BeforeIt)) {
      if (*AfterIt == Ret) {
        // ...
      }
    }
  }

PS: Mail filters are blocking my messages, so ignore this, its
only for them. Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Phasellus consequat ullamcorper mollis. Sed blandit semper tortor
ultricies dictum. Proin hendrerit et quam in sagittis. Maecenas vel
blandit ante, in auctor sem. Phasellus condimentum leo vel finibus
viverra. Duis fermentum sollicitudin est, ac iaculis lectus auctor vel.
Nam condimentum nulla feugiat, venenatis nibh a, elementum nulla. Nulla
vitae malesuada eros. Nulla cursus maximus ligula non hendrerit.

Curabitur lobortis nulla vel sapien posuere, id aliquam orci
bibendum. Vestibulum at vulputate risus. Proin in purus commodo,
tempus lectus vitae, faucibus nunc. Aenean congue faucibus elit, sit
amet facilisis nibh ultrices eget. Nam pulvinar leo ac nunc ultricies,
nec tincidunt nulla tincidunt. Etiam placerat felis tellus, ut ultricies
nunc ultricies quis. In placerat sapien nec ultricies mattis. Integer
sed tempor orci, ac imperdiet orci. Integer ac augue et augue convallis
faucibus.

In article <1432806087.2498925.280264065.1368E918@webmail.messagingengine.com>,
Gabor Kozar <kozargabor@fastmail.fm> writes:

I don’t think you’d really be able to do this with matchers without
major modifications to the matcher architecture.

Why do you say that? All the information is available from within
CompoundStmt provided I have the other two matchers. That’s what I
currently do now in the callback – walk the CompoundStmt looking for
the two consecutive statements that match my criteria (simplified and
hard-coded for my case):

It sounds like we could implement an isnext matcher via the parent map:
hasPreviousNode(m):
parent = getParentFromParentMap()
loop over the compound statements children until we find the current node
return value of m on previous node

Patches welcome :slight_smile: