c++clang

In clang-query, how to match a reference variable by the qualifiers of its object?


For example, how to match the reference to const here:

// references_match.cpp
int main() {
    const int   a = 5;
    int         b = 5;
    const auto& b_ref1 = b;  // <-- this one
    auto&       b_ref2 = b;
}

Then, if I match varDecl() and look at their types, only a will pass isConstQualified():

$ clang-query ./references_match.cpp
clang-query> set output dump
clang-query> match varDecl( )

Match #1:
Binding for "root":
VarDecl 0x5bd04b2fa390 <.../references_match.cpp:3:2, col:18> col:14 a 'const int' cinit
`-IntegerLiteral 0x5bd04b2fa3f8 <col:18> 'int' 5

...
Match #3:

Binding for "root":
VarDecl 0x5bd04b2fa5c0 <.../references_match.cpp:5:2, col:23> col:14 b_ref1 'const int &' cinit
`-ImplicitCastExpr 0x5bd04b2fa820 <col:23> 'const int' lvalue <NoOp>
  `-DeclRefExpr 0x5bd04b2fa628 <col:23> 'int' lvalue Var 0x5bd04b2fa4a0 'b' 'int'

...

clang-query> match varDecl( hasType(isConstQualified()) )

Match #1:

Binding for "root":
VarDecl 0x5bd04b2fa390 <.../references_match.cpp:3:2, col:18> col:14 a 'const int' cinit
`-IntegerLiteral 0x5bd04b2fa3f8 <col:18> 'int' 5

1 match.

I.e. varDecl() dump gets this string 'const int &' with the const in the referred type: b_ref1 'const int &' cinit. But, I guess, b_ref1 does not pass isConstQualified() because const qualifies the object, not the reference. Which matcher would match the object of the reference then? Can it be done on varDecl() node itself or the descendants should be matched, like ImplicitCastExpr?


Solution

  • The isConstQualified matcher checks for const applied at the top level of the type only. The type of b_ref1 is "reference to constant auto", where the auto is inferred to mean int. For isConstQualified to match, it would have to be "constant reference to ..." (which, incidentally, is not allowed in C++).

    To match based on what the reference refers to, one must use the pointee matcher to dig down one level. (The term "pointee" originates from the close relationship between pointers and references.)

    For example, this matcher:

     varDecl(                    # Match a variable declaration
      hasType(                   # whose type
       referenceType(            # is a reference
        pointee(                 # to
         isConstQualified()      # something that is const-qualified.
        )
       )
      )
     )
    

    when used with clang-query on your example reports:

    Match #1:
    
    $PWD\test.cc:7:5: note: "root"
          binds here
        7 |     const auto& b_ref1 = b;  // <-- this one
          |     ^~~~~~~~~~~~~~~~~~~~~~
    1 match.