Hi all,
I’m interested into developing a static analyzer checker that detects exceptions that escape a destructor. It even seems there is a similar suggestion in http://clang-analyzer.llvm.org/potential_checkers.html (ctordtor.ExptInsideDtor).
As a first step, I modified the alpha.cplusplus.VirtualCall checker to walk call hierarchies under destructors searching for throw statements (CXXThrowExpr). It works fine for many cases but there are also some limitations. One of them is that when we want to visit the body of a virtual method call “foo.bar()”, the call (IIUC) is resolved statically -according to foo’s static type-. Is there any way/API to walk/get all possible “bar” method implementations? Any examples to look at?
Of course, any other implementation suggestions are welcome.
Cheers,
George
Hi all,
I’m interested into developing a static analyzer checker that detects exceptions that escape a destructor. It even seems there is a similar suggestion in http://clang-analyzer.llvm.org/potential_checkers.html (ctordtor.ExptInsideDtor).
As a first step, I modified the alpha.cplusplus.VirtualCall checker to walk call hierarchies under destructors searching for throw statements (CXXThrowExpr). It works fine for many cases but there are also some limitations. One of them is that when we want to visit the body of a virtual method call “foo.bar()”, the call (IIUC) is resolved statically -according to foo’s static type-. Is there any way/API to walk/get all possible “bar” method implementations? Any examples to look at?
You want to warn if a destructor calls “foo.bar()” and any implementation of “bar()” can throw, correct? That would include implementations that do not get called from the destructor and make the warning more aggressive, which could potentially lead to false positives. Although, I am not sure how common those cases would happen in real code.
Sounds like you would be able to build on top of this method to find all implementations:
/// \brief Find the method in \p RD that corresponds to this one.
///
/// Find if \p RD or one of the classes it inherits from override this method.
/// If so, return it. \p RD is assumed to be a subclass of the class defining
/// this method (or be the class itself), unless \p MayBeBase is set to true.
CXXMethodDecl *
getCorrespondingMethodInClass(const CXXRecordDecl *RD,
bool MayBeBase = false);
Hi Anna,
You want to warn if a destructor calls “foo.bar()” and any implementation of
“bar()” can throw, correct?
Correct. On top of that, I'm wondering if it's possible to find any
functions/methods in "foo.bar()" call hierarchy that throw an
exception" (e.g. ~destructor() -> foo.bar() -> foo1.bar1() ->
foo2.bar2() { throw ...} => Warn about foo2.bar2)
That would include implementations that do not
get called from the destructor and make the warning more aggressive, which
could potentially lead to false positives. Although, I am not sure how
common those cases would happen in real code.
False positives are ok.
Sounds like you would be able to build on top of this method to find all
implementations:
/// \brief Find the method in \p RD that corresponds to this one.
///
/// Find if \p RD or one of the classes it inherits from override this
method.
/// If so, return it. \p RD is assumed to be a subclass of the class
defining
/// this method (or be the class itself), unless \p MayBeBase is set to
true.
CXXMethodDecl *
getCorrespondingMethodInClass(const CXXRecordDecl *RD,
bool MayBeBase = false);
Is this method able to look at method implementations that are in a
different translation unit (e.g. in the example above, "~destructor"
and "foo.bar()" implementation are in different translation units)?
Any ideas to work around that?
Thank you,
George