<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/83559>83559</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Pre-order on AST not preserved in `MatchFinder`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          jirislaby
      </td>
    </tr>
</table>

<pre>
    The docs of `MatchFinder` states:

> The order of matches is guaranteed to be equivalent to doing a pre-order traversal on the AST, and applying the matchers in the order in which they were added to the MatchFinder.

But if I run this checker:
```c++
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::ento;

namespace {
class MyChecker final : public Checker<check::EndOfTranslationUnit> {
public:
  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
                                 AnalysisManager &A, BugReporter &BR) const;
};

class MatchCallback : public MatchFinder::MatchCallback {
public:
        MatchCallback() {}

        void run(const MatchFinder::MatchResult &res);
};
}

void MatchCallback::run(const MatchFinder::MatchResult &res)
{
        if (auto RD = res.Nodes.getNodeAs<RecordDecl>("RD")) {
                llvm::errs() << "RD:\n";
                RD->dumpColor();
        }
        if (auto ME = res.Nodes.getNodeAs<MemberExpr>("ME")) {
                llvm::errs() << "ME:\n";
                ME->dumpColor();
        }
        if (auto ME = res.Nodes.getNodeAs<MemberExpr>("MESTORE")) {
                llvm::errs() << "MESTORE:\n";
                ME->dumpColor();
        }
}

void MyChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
                                          AnalysisManager &A,
                                          BugReporter &BR) const
{
        TU->dumpColor();

        MatchFinder F;
        MatchCallback CB;
        F.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, recordDecl(isStruct()).bind("RD")),
                 &CB);
        F.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, memberExpr().bind("ME")),
                 &CB);
        F.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource,
                         binaryOperator(isAssignmentOperator(),
                                         hasLHS(memberExpr().bind("MESTORE")))),
                 &CB);

        F.matchAST(A.getASTContext());
}

extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
 registry.addChecker<MyChecker>("jirislaby.PoBug", "XXX", "");
}

extern "C" const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;
```
by:
```
clang -cc1 -analyze -load ./po-bug.so -analyzer-checker jirislaby.PoBug x.c
```
on this C file:
```
void put(unsigned short val, void *p)
{
 struct {
                unsigned short x;
        } *pp = p;
 pp->x = val;
}
```
I see:
```
TranslationUnitDecl 0x5619382fb8b8 <<invalid sloc>> <invalid sloc>
|...
`-FunctionDecl 0x56193835e5b8 <x.c:1:1, line:7:1> line:1:6 put 'void (unsigned short, void *)'
  |-ParmVarDecl 0x56193835e460 <col:10, col:25> col:25 used val 'unsigned short'
  |-ParmVarDecl 0x56193835e4e0 <col:30, col:36> col:36 used p 'void *'
  `-CompoundStmt 0x56193835ea38 <line:2:1, line:7:1>
 |-DeclStmt 0x56193835e960 <line:3:2, line:5:11>
    | |-RecordDecl 0x56193835e6b8 <line:3:2, line:5:2> line:3:2 struct definition
    | | `-FieldDecl 0x56193835e778 <line:4:3, col:18> col:18 referenced x 'unsigned short'
    | `-VarDecl 0x56193835e890 <line:3:2, line:5:10> col:5 used pp 'struct (unnamed struct at x.c:3:2) *' cinit
    |   `-ImplicitCastExpr 0x56193835e930 <col:10> 'struct (unnamed struct at x.c:3:2) *' <BitCast>
 |     `-ImplicitCastExpr 0x56193835e918 <col:10> 'void *' <LValueToRValue>
    |       `-DeclRefExpr 0x56193835e8f8 <col:10> 'void *' lvalue ParmVar 0x56193835e4e0 'p' 'void *'
    `-BinaryOperator 0x56193835ea18 <line:6:2, col:10> 'unsigned short' '='
      |-MemberExpr 0x56193835e9b0 <col:2, col:6> 'unsigned short' lvalue ->x 0x56193835e778
 | `-ImplicitCastExpr 0x56193835e998 <col:2> 'struct (unnamed struct at x.c:3:2) *' <LValueToRValue>
      |   `-DeclRefExpr 0x56193835e978 <col:2> 'struct (unnamed struct at x.c:3:2) *' lvalue Var 0x56193835e890 'pp' 'struct (unnamed struct at x.c:3:2) *'
      `-ImplicitCastExpr 0x56193835ea00 <col:10> 'unsigned short' <LValueToRValue>
 `-DeclRefExpr 0x56193835e9e0 <col:10> 'unsigned short' lvalue ParmVar 0x56193835e460 'val' 'unsigned short'
MESTORE:
MemberExpr 0x56193835e9b0 'unsigned short' lvalue ->x 0x56193835e778
`-ImplicitCastExpr 0x56193835e998 'struct (unnamed struct at x.c:3:2) *' <LValueToRValue>
  `-DeclRefExpr 0x56193835e978 'struct (unnamed struct at x.c:3:2) *' lvalue Var 0x56193835e890 'pp' 'struct (unnamed struct at x.c:3:2) *'
RD:
RecordDecl 0x56193835e6b8 <x.c:3:2, line:5:2> line:3:2 struct definition
`-FieldDecl 0x56193835e778 <line:4:3, col:18> col:18 referenced x 'unsigned short'
ME:
MemberExpr 0x56193835e9b0 'unsigned short' lvalue ->x 0x56193835e778
`-ImplicitCastExpr 0x56193835e998 'struct (unnamed struct at x.c:3:2) *' <LValueToRValue>
  `-DeclRefExpr 0x56193835e978 'struct (unnamed struct at x.c:3:2) *' lvalue Var 0x56193835e890 'pp' 'struct (unnamed struct at x.c:3:2) *'
```

That is `MemberExpr` (bound to `MESTORE`) is reported **before** `RecordDecl`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWVtz4jgW_jXKiwrKyODLAw_GwGxqO-kU0F2z-5KSbQGaEZJXkjPJ_votSQZfuCSb7p3dh-1Kg63LuXznO0fHGCtFd5yQKZjMwGR-hyu9F3L6G5VUMZy93WWieJtu9gQWIldQbCEIvAes8_2S8oJIEHhQaayJAn4CvDnwjp_-ApptQhZEmn0Hs4koSBXcVVhirgkpoBYwI5D8o6IvmBGuzUAhKN9BDEtJBm67lviFSIUZFBzqPYHJegNQCjEvIC5L9mY2mHGnRCpI3Tq3nXL4x57mezP0Bv8gkkBcFE67WdXyZ9j2YVZpSLfwHsrKiKMK5nuS_05k42vgub8coJn5c6PIpzxnVUEgQChnmO8AWibrzUNtXuuuVrsHCN3avNZY0zzhmL39k0iAlqmQxHw5gz69_wnr_ZpwRTV9Mfd2haLqAXO8-4zcpRRcE140tq3Ijiot39qy7GelTNg4PhBV4pxAJ9Of3ZxNgJ9gpZ-Pkf7IesK1OK1zn806ENYTOcNKwYe32my4pRwzCPwEllXGaA7TY_BTSwMne8GLr9uNxFwxrKng3zjVhvsnsW7ziTEQvghaOCJd3IuiXHClYW98TnIGAUo23wBKj57Epz_YCxwEKEhMisyq3YqUQmo3NlsBFEOroUEknPfQqaEwEKeYsQznv7eBaOe_BaG38orrwIs7CwGKjDFmeTjv1A4vtiDJip_guKxzRVTFtHFMEgVQfNmnrnQrumuIFfgJbbX4E3Yx3UKAIlxpAVdzCPw5lEQNH0VB1HBHtLlIFPDTFcmFLExMgb-wOKDV3KQHio-QtELM2MuhZrI0xcPB5qfAT6Hb6SdgknIjwO_sXM0HwF8U1aFMBRPSbe2sabBpG_-wuGH8AzlkRC5eS3ky_mHxWeMfFleNf1j8WcavN19XP-CB2_4T3LhE1Le0OXP85GfXDVM6rtWOK6tvVJSzfNh8u-17uyy4dIPLNjTdwpLO2nPLIS6K-kQFKKp7BAJQtPnr8_2OC0m-cUaUWpeEMVLc87WoZE5MVZRN_qGIqrWWVa5r61A8zKg5wHpZ2UPE-J7OeqH8EZsODTOtIS0rWun1H7aiF3OYUY7l29eSSKxt_KhKbMt4IFy3hs8ta2TssfrylzVA0U0Puzn4YWdPLtuGwPaFUWIyPllvUtOKvDZxvXYikFdNJDe5nAKE6gPatA_P0vYuRNY5aJK_19W408Bdd2oHPI6aYDStQyuf6_Jz6rWHT2JW7SwEtrD8-uuvzU2NzMc8cJUg32NZ-4HrBi15uv9OpKKCr7WkfOe6flsu0y_J4y_PyWPy5W9_X6yek6f75--L1fr-6-PzerO6f_yl0X1set1t9nbeDp_aCL6DgzwfwUFtARwwgQs4BGhZikFW7YZKnCbloO6vYQ8T-DrML2oQdV-ewi1l5JodNqBlZYhQcfu8U0C1F1LDF8wMvnYBQEl5fqhDZWtDK669fz2JryeYjgtAOLeySwtz2cyXpSmOr3bYGHIe264b91CRqz5eKvve6yQYxX6EtlmURfWRRfkLZrSAionccND0quejtSHpcDg8qRssK54bBR3h_oRMnHATJD8Z2f8ohYxyY23oxhbHezMfmGhAgMIa-F5Y2iGxmRseEQVhOnjC8vAdy74R48AzRuSCGSWekeGu0cRoP17DSpHCwG3U99V-SA9p6fFbevyg0eMHTk_ZcjJpyw-8QSoOpah4sdYH3VaAfYtmDRe6AmctyRhqLOwLiR0a9SbfCmqETIyQlhTL0tQKazrTtrggi94Rh1ohtvPHxCnIlnJqaHOmzMKwpISd6QvDtr6xlXkCehQ1QI8iKMmWSMJzUsDXm0GFJ50XwhrF7wLmNWprGpU2vscKYWhsniuLo-tYQ5cTtbi4ZgHMDSJdsxwn7g8loznVKVbanJOdkPpdgpvE_Yxy4Kczp6FDI1er3rNhFF2woUVwM_vlO2YV2YiV_T5jGTxpMjFYkW1fSbR9Twl7MZJhnaFn2YnC0ppyMfWc6lmnr-mk36hNveBIhJ41ZyQzg8CfdxS5OtI8cXSQzFrRbGkIriqonXZnRjdXWlF8N4Jx1Nb7AyS6EeY2pa8EOQ5_ih01KD0W2GRGYXmkwb8tt-PKO4hi71JeXiDIdchu4UQ-Jv1GSgQWDNvqhDcKZOs51t1f5-2n6PkhZv5sLr7HwP85zrkfc9zlraO4I-JzJ_Gfefo-_J9X_11e9R4X6oeGPdaQKvtOp3k2t_UiykxvCrWwk3VpCDwjlioo3Q9A9dmaZGRrXyeYa7O-9fNm4A3viqlfxH6M78h0FHoxiscBGt_tpyOvyPNJnHt-HI49bzIZkzAOx36wjbce9sM7OkUeGnu-Nxohzx-Ph6NtHMT-NotRkIXFOAdjjxwwZUPGXg5DIXd3VKmKTCN_MonvGM4IU8dXW3JqFplnTgXGHqNKq2abppqR6dPpjZPgMFlvIBcalpIoIl9IASk_f_t1V0k23Wtd2hdgaAnQckf1vsqGuTgAtLQ_HrqvQSnFbyTXAC2tlQqgpTX0XwEAAP___2bgwQ">