Static analyzer question on how to tell if a Decl is a particular c++ function, or a particular class

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Static analyzer question on how to tell if a Decl is a particular c++ function, or a particular class

Hans Wennborg via cfe-dev
Hi folks,

If this is not the correct mailing list for this question, please let me know.

I am trying to write a static analyzer for code base of my current job. The particular static analyzer I am writing involves a particular class of my company's code base. Let's say it is T. I want to write a checker to ensure T.ok() is called before T.value() is called.

Static analyzer is perfect for this type of check as it requires path sensitive checks. When I trying to write the checker, I basically checks for pre-call and post-call. I want to tell if a CallEvent is T.ok() and T.value(). Currently what I am doing is:
1. From CallEvent, I cast to CXXMemberCall, and getOriginExpr(), then call getMethodDecl().
2. From CXXMethodDecl, I first call getThisType(), then call getAsCXXRecordDecl(), then getQualifiedNameAsString(), and compare with qualified name of T, to make sure it is member of T.
3. From CXXMethodDecl, I call getNameAsString() to get the method name, and compare them with "ok" and "value".

It works, but it looks complicated, and involves string comparison, which I assume is slow. Is there a easier way, blessed by clang static analyzer official teams, that tell if a MethodDecl, or CXXRecordDecl, is the function or class I am interested in?

The ideal way is, there is one-time call to lookup the MethodDecl for T::ok() and T::value(), and CXXRecordDecl for T. Then ever since then, I just need to compare the pointers.

Another way is, the first time I found it is T, T::ok() or T::value(), I save the pointer of CXXRecordDecl or MethodDecl, and use the pointers later. Is this the reliable (assume I use the pointer canonical decl will not change) and blessed way to do it? If it is, is my steps above the correct and simplest way to determine it is T::ok or T::value? Is there some better and more reliable way?

Thanks.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Static analyzer question on how to tell if a Decl is a particular c++ function, or a particular class

Hans Wennborg via cfe-dev
Hello Li,

What you're doing is mostly fine. I can only add some potentially useful info inline.

14.02.2018 23:04, Li Kan via cfe-dev пишет:
Hi folks,

If this is not the correct mailing list for this question, please let me know.
You're in the right place. Welcome :)

I am trying to write a static analyzer for code base of my current job. The particular static analyzer I am writing involves a particular class of my company's code base. Let's say it is T. I want to write a checker to ensure T.ok() is called before T.value() is called.

Static analyzer is perfect for this type of check as it requires path sensitive checks. When I trying to write the checker, I basically checks for pre-call and post-call. I want to tell if a CallEvent is T.ok() and T.value(). Currently what I am doing is:
1. From CallEvent, I cast to CXXMemberCall, and getOriginExpr(), then call getMethodDecl().
You can also try to do the following chain: dyn_cast_or_null<CXXMethodDecl>(CallEvent.getDecl()) to obtain CXXMethodDecl.

2. From CXXMethodDecl, I first call getThisType(), then call getAsCXXRecordDecl(), then getQualifiedNameAsString(), and compare with qualified name of T, to make sure it is member of T.
To obtain parent class declaration from CXXMethodDecl, you can use getParent() method. So, the pseudocode will look like "MethodDecl->getParent()->getQualifiedNameAsString()".

3. From CXXMethodDecl, I call getNameAsString() to get the method name, and compare them with "ok" and "value".
This looks OK. But it can be useful to know that getQualifiedNameAsString() for CXXMethodDecl will also include parent name. So, you can just check if MethodDecl->getQualifiedNameAsString() is equal to "T::value" or "T::ok".

It works, but it looks complicated, and involves string comparison, which I assume is slow. Is there a easier way, blessed by clang static analyzer official teams, that tell if a MethodDecl, or CXXRecordDecl, is the function or class I am interested in?

The ideal way is, there is one-time call to lookup the MethodDecl for T::ok() and T::value(), and CXXRecordDecl for T. Then ever since then, I just need to compare the pointers.
This is possible. You can just launch a simple matcher against AST:
cxxMethodDecl(hasName("::T::value"))
and get CXXMethodDecl you need and compare with it later.

Another way is, the first time I found it is T, T::ok() or T::value(), I save the pointer of CXXRecordDecl or MethodDecl, and use the pointers later. Is this the reliable (assume I use the pointer canonical decl will not change) and blessed way to do it? If it is, is my steps above the correct and simplest way to determine it is T::ok or T::value? Is there some better and more reliable way?
I think it is reliable enough: pointers to canonical declarations don't change in AST.

Thanks.


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


-- 
Best regards,
Aleksei Sidorin,
SRR, Samsung Electronics

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Static analyzer question on how to tell if a Decl is a particular c++ function, or a particular class

Hans Wennborg via cfe-dev
Yeah, the traditional way to see if this is a certain method of a
certain class is to compare the name of the method
(CXXMethodDecl->getName()) and the class
(CXXMethodDecl->getParent()->getName()), as strings, to the desired
strings. getQualifiedNameAsString() works fine, but it's considered slow
for whatever reason (i've never observed it personally). ASTMatchers
would also work, even if a bit of an overkill. Don't forget to check the
method's argument number and types as well. We have an effort to make
this whole common idiom more simple via CallDescription, but it doesn't
work for C++ methods yet.

With C++, you'll need to be aware of the bug we're currently having with
object lifetime extension. If you're identifying the object by its
memory region (which is correct), you'd occasionally notice that the
region for a C++ temporary object may change along the analysis even if
no copy-construction occurs. It has been making our new C++ checkers
(most noticeably, the iterator checker) more difficult to write than
they needed to be. More details in
http://lists.llvm.org/pipermail/cfe-dev/2018-February/056898.html - i'm
hoping to do something about it soon.

On 15/02/2018 1:35 AM, Aleksei Sidorin via cfe-dev wrote:

> Hello Li,
>
> What you're doing is mostly fine. I can only add some potentially
> useful info inline.
>
> 14.02.2018 23:04, Li Kan via cfe-dev пишет:
>> Hi folks,
>>
>> If this is not the correct mailing list for this question, please let
>> me know.
> You're in the right place. Welcome :)
>
>> I am trying to write a static analyzer for code base of my current
>> job. The particular static analyzer I am writing involves a
>> particular class of my company's code base. Let's say it is T. I want
>> to write a checker to ensure T.ok() is called before T.value() is called.
>>
>> Static analyzer is perfect for this type of check as it requires path
>> sensitive checks. When I trying to write the checker, I basically
>> checks for pre-call and post-call. I want to tell if a CallEvent is
>> T.ok() and T.value(). Currently what I am doing is:
>> 1. From CallEvent, I cast to CXXMemberCall, and getOriginExpr(), then
>> call getMethodDecl().
> You can also try to do the following chain:
> dyn_cast_or_null<CXXMethodDecl>(CallEvent.getDecl()) to obtain
> CXXMethodDecl.
>
>> 2. From CXXMethodDecl, I first call getThisType(), then call
>> getAsCXXRecordDecl(), then getQualifiedNameAsString(), and compare
>> with qualified name of T, to make sure it is member of T.
> To obtain parent class declaration from CXXMethodDecl, you can use
> getParent() method. So, the pseudocode will look like
> "MethodDecl->getParent()->getQualifiedNameAsString()".
>
>> 3. From CXXMethodDecl, I call getNameAsString() to get the method
>> name, and compare them with "ok" and "value".
> This looks OK. But it can be useful to know that
> getQualifiedNameAsString() for CXXMethodDecl will also include parent
> name. So, you can just check if MethodDecl->getQualifiedNameAsString()
> is equal to "T::value" or "T::ok".
>
>> It works, but it looks complicated, and involves string comparison,
>> which I assume is slow. Is there a easier way, blessed by clang
>> static analyzer official teams, that tell if a MethodDecl, or
>> CXXRecordDecl, is the function or class I am interested in?
>>
>> The ideal way is, there is one-time call to lookup the MethodDecl for
>> T::ok() and T::value(), and CXXRecordDecl for T. Then ever since
>> then, I just need to compare the pointers.
> This is possible. You can just launch a simple matcher against AST:
> cxxMethodDecl(hasName("::T::value"))
> and get CXXMethodDecl you need and compare with it later.
>
>> Another way is, the first time I found it is T, T::ok() or
>> T::value(), I save the pointer of CXXRecordDecl or MethodDecl, and
>> use the pointers later. Is this the reliable (assume I use the
>> pointer canonical decl will not change) and blessed way to do it? If
>> it is, is my steps above the correct and simplest way to determine it
>> is T::ok or T::value? Is there some better and more reliable way?
> I think it is reliable enough: pointers to canonical declarations
> don't change in AST.
>>
>> Thanks.
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
> --
> Best regards,
> Aleksei Sidorin,
> SRR, Samsung Electronics
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev