[Clang-tidy] Detecting if a catch was done by const ref

Hi all,

I’m trying to check that all my catch are done by const ref. I copied the current check throw/catch and modified it to add the const check on the type: https://github.com/mbrucher/clang-tools-extra/commit/2374bfd3d41fa7d55bc597d06a59414c7cef78e1#diff-0a677ae6cda57ad182883b1344b29d9bR51
Unfortunately, it seems that none of the checks I try detect the const part. I tried isConstQualified, isLocalConstQualified, is there another way of checking that the exception is const (on top of ref-qualified)?

Regards,

Matthieu

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article <CAHCaCk+Big1HB=O+JHeSRdqV-DE9y_MuHAaageOTvP1nzLvZ_w@mail.gmail.com>,
    Matthieu Brucher via cfe-dev <cfe-dev@lists.llvm.org> writes:

Unfortunately, it seems that none of the checks I try detect the const
part. I tried isConstQualified, isLocalConstQualified, is there another way
of checking that the exception is const (on top of ref-qualified)?

Have you tried prototyping with clang-query?

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article <CAHCaCk+Big1HB=O+JHeSRdqV-DE9y_MuHAaageOTvP1nzLvZ_w@
mail.gmail.com>,
    Matthieu Brucher via cfe-dev <cfe-dev@lists.llvm.org> writes:

> Unfortunately, it seems that none of the checks I try detect the const
> part. I tried isConstQualified, isLocalConstQualified, is there another
way
> of checking that the exception is const (on top of ref-qualified)?

Have you tried prototyping with clang-query?

I know how to use it to create the query, but that's it. And even then, I
can only do basic query, as I don't know where to find documentation on the
specifics.
It's possible to use for "dematching"? The ideal would be to select all
catch statements that are not const&, but there are no example anywhere on
that kind of selection.

Regards,

Matthieu Brucher

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article <CAHCaCkKdVLA-Mvg6i8BLAURRAeFfq5_GSGc6NmY3bEjRPpXq3Q@mail.gmail.com>,
    Matthieu Brucher via cfe-dev <cfe-dev@lists.llvm.org> writes:

> Have you tried prototyping with clang-query?
>

I know how to use it to create the query, but that's it. And even then, I
can only do basic query, as I don't know where to find documentation on the
specifics.
It's possible to use for "dematching"? The ideal would be to select all
catch statements that are not const&, but there are no example anywhere on
that kind of selection.

I confess that I find the type related matchers confusing and I'm
never quite sure how to use them. If you look at the matcher
reference <http://clang.llvm.org/docs/LibASTMatchersReference.html>
you'll see a matcher for isExceptionVariable which is how you match
variable declarations in a catch statement. (Maybe the matcher name
here isn't the best.)

  c:\tmp
  > copy con: tmp.cpp
  #include <stdexcept>

  void f()
  {
    try {
    g();
    } catch (std::exception &e) {
    throw;
    }
  }
  ^Z
      1 file(s) copied.

  c:\tmp
  > clang-query tmp.cpp --
  clang-query> match varDecl(isExceptionVariable())

  Match #1:

  c:\tmp\tmp.cpp:9:12: note: "root" binds here
    } catch (std::exception &e) {
         ^~~~~~~~~~~~~~~~~
  1 match.
  clang-query>

The part that always confuses me about the matchers is how to modify
matchers that find statements or declarations to qualify the matches
by aspects of the associated type.

Here we want to narrow the varDecl() so that the type of the variable
is reference but not reference to const. Frankly, I have never
figured out how to do that in clang-query and I'd love for someone to
enlighten me :slight_smile:

I believe the matcher you're looking for is:
varDecl(hasType(references(qualType(isConstQualified()))))

For example, given:

void f1() {
  try {
  } catch (int &e) {
  }
}

void f2() {
  try {
  } catch (const int &e) {
  }
}

produces:

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

Match #1:

C:\Users\Aaron\Desktop\test.cpp:9:12: note: "root" binds here
  } catch (const int &e) {
           ^~~~~~~~~~~~
1 match.

~Aaron

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article <CAAt6xTvjSPEg7OVPWVbtqWdsDp5zja9_TfLTkdzoNoksmEr=KQ@mail.gmail.com>,
    Aaron Ballman via cfe-dev <cfe-dev@lists.llvm.org> writes:

I believe the matcher you're looking for is:
varDecl(hasType(references(qualType(isConstQualified()))))

For example, given:

void f1() {
  try {
  } catch (int &e) {
  }
}

void f2() {
  try {
  } catch (const int &e) {
  }
}

produces:

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

Match #1:

C:\Users\Aaron\Desktop\test.cpp:9:12: note: "root" binds here
  } catch (const int &e) {
           ^~~~~~~~~~~~
1 match.

I think they want to match the catches that aren't const qualified, so
it might be (untested):

varDecl(hasType(references(qualType(not(isConstQualified())))))

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article <CAAt6xTvjSPEg7OVPWVbtqWdsDp5zja9_TfLTkdzoNoksmEr=KQ@mail.gmail.com>,
    Aaron Ballman via cfe-dev <cfe-dev@lists.llvm.org> writes:

I believe the matcher you're looking for is:
varDecl(hasType(references(qualType(isConstQualified()))))

For example, given:

void f1() {
  try {
  } catch (int &e) {
  }
}

void f2() {
  try {
  } catch (const int &e) {
  }
}

produces:

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

Match #1:

C:\Users\Aaron\Desktop\test.cpp:9:12: note: "root" binds here
  } catch (const int &e) {
           ^~~~~~~~~~~~
1 match.

I think they want to match the catches that aren't const qualified, so
it might be (untested):

varDecl(hasType(references(qualType(not(isConstQualified())))))

Ah, oops, I didn't see that I had the predicate reversed. Your matcher
is close, but instead of not(), you use unless().

~Aaron

Excellent! I thought I had to use the catch statement, but this is indeed
far better.
I guess you have to know the AST matcher expressions... Are there tutorials
on top of the doxygen doc? Or perhaps even books?

Regards,

Matthieu

2018-03-12 19:39 GMT+00:00 Aaron Ballman via cfe-dev
<cfe-dev@lists.llvm.org>:

> [Please reply *only* to the list and do not include my email directly
> in the To: or Cc: of your reply; otherwise I will not see your reply.
> Thanks.]
>
> In article
> <CAAt6xTvjSPEg7OVPWVbtqWdsDp5zja9_TfLTkdzoNoksmEr=KQ@mail.gmail.com>,
> Aaron Ballman via cfe-dev <cfe-dev@lists.llvm.org> writes:
>
>> I believe the matcher you're looking for is:
>> varDecl(hasType(references(qualType(isConstQualified()))))
>>
>> For example, given:
>>
>> void f1() {
>> try {
>> } catch (int &e) {
>> }
>> }
>>
>> void f2() {
>> try {
>> } catch (const int &e) {
>> }
>> }
>>
>> produces:
>>
>> clang-query> match
>> varDecl(hasType(references(qualType(isConstQualified()))))
>>
>> Match #1:
>>
>> C:\Users\Aaron\Desktop\test.cpp:9:12: note: "root" binds here
>> } catch (const int &e) {
>> ^~~~~~~~~~~~
>> 1 match.
>
> I think they want to match the catches that aren't const qualified, so
> it might be (untested):
>
> varDecl(hasType(references(qualType(not(isConstQualified())))))

Ah, oops, I didn't see that I had the predicate reversed. Your matcher
is close, but instead of not(), you use unless().

~Aaron

> --
> "The Direct3D Graphics Pipeline" free book
> <http://tinyurl.com/d3d-pipeline>
> The Terminals Wiki <http://terminals-wiki.org>
> The Computer Graphics Museum <http://ComputerGraphicsMuseum.org>
> Legalize Adulthood! (my blog) <http://LegalizeAdulthood.wordpress.com>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
cfe-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

Excellent! I thought I had to use the catch statement, but this is indeed
far better.
I guess you have to know the AST matcher expressions... Are there tutorials
on top of the doxygen doc? Or perhaps even books?

There aren't any books that I'm aware of, and I'm not certain about
other tutorials (perhaps they exist and I've simply not found them). I
mostly go off the AST dumps (clang -cc1 -ast-dump foo.cpp), the AST
matchers reference, clang-query, and trial & error.

~Aaron

Hi,

Hi,

I guess you have to know the AST matcher expressions... Are there

tutorials

on top of the doxygen doc? Or perhaps even books?

Try <https://clang.llvm.org/docs/LibASTMatchersTutorial.html>.

Regards,

Miklos

Thanks for the pointers.
Is the not() matcher only available in 6.0? I tried the expression in
5.0.1,but it failed.
Still trying to find the list of possible "instructions" in the query.

Regards

Matthieu Brucher

Hi,

I guess you have to know the AST matcher expressions... Are there
tutorials
on top of the doxygen doc? Or perhaps even books?

Try <https://clang.llvm.org/docs/LibASTMatchersTutorial.html>.

Regards,

Miklos

Thanks for the pointers.
Is the not() matcher only available in 6.0? I tried the expression in
5.0.1,but it failed.
Still trying to find the list of possible "instructions" in the query.

There isn't a not() matcher; you want to use unless().

~Aaron

Oh yes, I forgot…
Thanks.

Seems like this query also matches function arguments. I suppose I have to use a condition saying that the previous or parent statement is catch?

Matthieu

I believe the matcher you're looking for is:
varDecl(hasType(references(qualType(isConstQualified()))))

For example, given:

void f1() {
  try {
  } catch (int &e) {
  }
}

void f2() {
  try {
  } catch (const int &e) {
  }
}

produces:

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

Match #1:

C:\Users\Aaron\Desktop\test.cpp:9:12: note: "root" binds here
  } catch (const int &e) {
           ^~~~~~~~~~~~
1 match.

~Aaron

[Please reply *only* to the list and do not include my email directly
in the To: or Cc: of your reply; otherwise I will not see your reply.
Thanks.]

In article
<CAHCaCkKdVLA-Mvg6i8BLAURRAeFfq5_GSGc6NmY3bEjRPpXq3Q@mail.gmail.com>,
    Matthieu Brucher via cfe-dev <cfe-dev@lists.llvm.org> writes:

> Have you tried prototyping with clang-query?
>

I know how to use it to create the query, but that's it. And even then, I
can only do basic query, as I don't know where to find documentation on
the
specifics.
It's possible to use for "dematching"? The ideal would be to select all
catch statements that are not const&, but there are no example anywhere
on
that kind of selection.

I confess that I find the type related matchers confusing and I'm
never quite sure how to use them. If you look at the matcher
reference <http://clang.llvm.org/docs/LibASTMatchersReference.html>
you'll see a matcher for isExceptionVariable which is how you match
variable declarations in a catch statement. (Maybe the matcher name
here isn't the best.)

        c:\tmp
        > copy con: tmp.cpp
        #include <stdexcept>

        void f()
        {
          try {
                g();
          } catch (std::exception &e) {
                throw;
          }
        }
        ^Z
                        1 file(s) copied.

        c:\tmp
        > clang-query tmp.cpp --
        clang-query> match varDecl(isExceptionVariable())

        Match #1:

        c:\tmp\tmp.cpp:9:12: note: "root" binds here
          } catch (std::exception &e) {
                           ^~~~~~~~~~~~~~~~~
        1 match.
        clang-query>

The part that always confuses me about the matchers is how to modify
matchers that find statements or declarations to qualify the matches
by aspects of the associated type.

Here we want to narrow the varDecl() so that the type of the variable
is reference but not reference to const. Frankly, I have never
figured out how to do that in clang-query and I'd love for someone to
enlighten me :slight_smile:

Seems like this query also matches function arguments. I suppose I have to
use a condition saying that the previous or parent statement is catch?

It will match all variable declarations. For just catch arguments, I
think you will want:

varDecl(isExceptionVariable(),
hasType(references(qualType(isConstQualified()))))

~Aaron

I really have to look at the ast_matchers functions (because I just noticed
that this is where these are!).

Thanks a lot!

Regards,

Matthieu