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

    <tr>
        <th>Summary</th>
        <td>
            [AST-Matchers] Inconsistency between the dynamic AST matchers used via clang-query and the C++ AST matchers used via clang-tidy
        </td>
    </tr>

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

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

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

<pre>
    As per https://clang.llvm.org/extra/clang-tidy/Contributing.html, clang-query is used for interactive prototyping of AST matchers that will eventually be used via clang-tidy. However, there are differences between two matchers such that a matcher that works in clang-query will not work as intended or doesn't compile in clang-tidy.

See the following discussions for examples/code-samples of this issue cropping up:
https://discourse.llvm.org/t/matcher-working-in-clang-query-but-not-in-libtooling/56947 (clang-query matcher works, clang-tidy doesn't compile)
https://discourse.llvm.org/t/inconsistency-between-hasdescendant-in-clang-query-and-clang-libtooling-matchers/80799 (matcher compiles but doesn't work as intended)

Code samples (extracted from the first discussion, tested to be present at least up to clang 17.0.6):

```
//clang-query, will work
match cxxRecordDecl(has(unless(cxxRecordDecl())))
```

```
#include “clang/ASTMatchers/ASTMatchers.h”

using namespace clang::ast_matchers;

int main(int argc, char** argv){
auto m = cxxRecordDecl(has(unless(cxxRecordDecl())));
return 0;

}
```

```
../src/clang/Example.cpp:6:24: error: no matching function for call to object of type 'const internal::ArgumentAdaptingMatcherFunc<clang::ast_matchers::internal::HasMatcher>'
    6 | auto m = cxxRecordDecl(has(unless(cxxRecordDecl())));
      |                        ^~~
/usr/include/clang/ASTMatchers/ASTMatchersInternal.h:1491:3: note: candidate template ignored: could not match 'Matcher' against 'VariadicOperatorMatcher'
 1491 |   operator()(const Matcher<T> &InnerMatcher) const {
      |   ^
/usr/include/clang/ASTMatchers/ASTMatchersInternal.h:1498:3: note: candidate template ignored: could not match 'MapAnyOfHelper' against 'VariadicOperatorMatcher'
 1498 |   operator()(const MapAnyOfHelper<T...> &InnerMatcher) const {
      |   ^
1 error generated.
```

The way to make the same behaviour as clang-query's matcher is to add a has in the middle:
```
#include “clang/ASTMatchers/ASTMatchers.h”

using namespace clang::ast_matchers;

int main(int argc, char** argv){
auto m = cxxRecordDecl(has(decl(unless(cxxRecordDecl()))));
return 0;

}
```

Of course, this probably isn't ideal.

As it stands the quickest way to make people be at least aware of this difference is to edit the Contributing guide.

Ideally the differences can be resolved or reduced by refining the dynamic matchers (https://github.com/llvm/llvm-project/blob/main/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp, https://github.com/llvm/llvm-project/blob/main/clang/lib/ASTMatchers/Dynamic/Parser.cpp), and the AST matchers (https://github.com/llvm/llvm-project/blob/main/clang/lib/ASTMatchers/ASTMatchersInternal.cpp, https://github.com/llvm/llvm-project/blob/main/clang/include/clang/ASTMatchers/ASTMatchersInternal.h).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkV0lv4zoS_jX0pWDBoWxLOvig2DE6h0YPJsFcBxRZtviaIvVIyokv77cPSMpbepleMnN5hmFrIWv5vqpiFXNO7jXiiizuyWIzYYNvjV19lLxFpXC9-WPQTAo5aYw4rmoHPVpove8dyWtCt4RuuWJ6nyl16DJj94Ru8dVbdnox9VIcCd2ujfZWNoOXep-1vlOEriGt-HNAewTpYHAoYGcsSO3RMu7lAaG3xht_7KXeg9lB_fQMHfO8RevAt8zDi1QK8IDaD0ypIzSYBB0kg4sJGXwwL3hAG_T6Fi0CswhC7nZoUXN00KB_QdTgX8xFhRt4m_Sw08NRrbGfHUh940S0RZv0FpiLnmiBAowFYdBpQgsP3HS9VHjZHS0ksw2Z1en3CTFYCTujlHkJvgvp-OCcNNpFjPCVdb1CF4A2Aqcu3QaMfCsdSOcGBG5NH6Eb-kBYlH1LX5BrBuvwmkJP6Hb0dhpckXo_lXp65eq0GfxUGx8eK9l4Y5TUYetiWc0LILS8xuWEXATtwnxw-0tYCK1-ylCpudFOOo-aH6cji9OWOYGOoxZM-7fGMy3G-4vt0xPnhG7LWVFVwYmT4aNpDprBX1n8luaz6el3bQTCiRhCy5gZ3Icot6ZLBEvr_BW5MTzRhTXehFjuLTrUHpgHhcx5GPrwJloPd0U2y5ZB64nc8Xc5G7_p9pKoCYCgJcZqcCCtiZ4Cf339J3JjxQa5IrRsmSO0HLRCFy7evg6az9-vav66ObnUXA0CgTxQUs5ItY7GEbqtn54_Xni4usva09rNtejBhejWrEPXM44Jl4BGXjPn_33mNL-_3iW1h45JTWgZLpnd8xiVLbOE1oTW4dEhOFWM-9jgDXRA8s1vYXQyw6IfrIbZG7tIsflxGLOM0K2z_EQtoduHVBQy3od0X5K8pnOS14DWGhsu9FjaAmi7QXMvjY7lhDOlQlyZ5g_kPlaRY49AaBGSy6eSrJlK0NZ2P3SofS1YHyr6SNJ20Jzk629yEJ7cCvrA3LiX5A-EFskzAIAlkGIN7ww7xE8Q_I0PWTz89dc5aQZnU30JsXoF8zeD9HF0LmtJXt_NqzuS13nC3WP450wLKZhH8Nj1KlzIvTYWRXxrBiXi-ZGykdDihA4tgO2ZDFQQWvyLWcmE5J96tMwbe1k1-hl0j36acc0JkzIReoZ9_UzyByB0-ag1XiRVkNadM-AaO7J4eD-QyncAqa_18dPuA6r-l7Aq_xtWN_Lz9XOWZb-B2l1KSNijDvpQZN_J-ucW4YUdQ3J27HNqCxzrEBps2UGawYYT6Ka4F-584koXNjIhgEEbT6oooJNCKLycGn-DAi3SzY8VjN8t1Z92kJqV1G5KF_rYhjUqNLqpd5ACmbpp-moH0oPzTAsXWfpzkPwzOn_Df4-mV4H9S0vAXkIve-r8Lj3tyD4K6aO86yYc9oMUeKP_MVikjnHpdWPMmQ7qLDqjDqmXtSgGjgKaI1jcSR0Exm1HzTrJL_1zgP-mjdtL3w5Nxk1H6DZ0cuPftLcmHD2EbhtlmtiABv7P9UTJ5ovw2yR1hG4_MutaplQIxHD60TX8X_T-g1mHNqmsglamRUTiZlD536Lwtdr6vhj8WnWnVTYRq1xUecUmuLor6Lwqy3xeTNrVYoGUIquEmC9RLOhds0TKsKnyRUnLspnIFZ3R-azMZ7OcLuZFxnm5W3KxK6p8Xs3Ejsxn2DGpzuPAJI48q7vZcrlYThRrULnTXGtX0c9m2DsynynpvLvs89KrOAHXT8_Ts1eLDTxeTxaX-fAqzm9YfjN2ptHnFA9rQu8Jvf_ujjAPTQarVj9NW3Q9MDF6f1jR_wQAAP__6ysSTA">