This is an archive of the discontinued LLVM Phabricator instance.

[PATCH] clang-tidy checker for nothrow copy constructible exception objects
ClosedPublic

Authored by aaron.ballman on Nov 12 2015, 9:13 AM.

Details

Reviewers
alexfh
sbenza
Summary

This patch adds a new clang-tidy checker that flags throw expressions whose thrown type is not nothrow copy constructible. While the compiler is free to elide copy constructor calls in some cases, it is under no obligation to do so, which makes the code a portability concern as well as a security concern.

This checker corresponds to the CERT secure coding rule: https://www.securecoding.cert.org/confluence/display/cplusplus/ERR60-CPP.+Exception+objects+must+be+nothrow+copy+constructible

Diff Detail

Event Timeline

aaron.ballman retitled this revision from to [PATCH] clang-tidy checker for nothrow copy constructible exception objects.
aaron.ballman updated this object.
aaron.ballman added reviewers: alexfh, sbenza.
aaron.ballman added a subscriber: cfe-commits.
bcraig added a subscriber: bcraig.Nov 12 2015, 9:24 AM

I would love to see a test case with dynamic allocation. Something along the following...

struct Allocates {

int *x;
Allocates() : x(new int(0)) {}
Allocates(const Allocates &other) : x(new int(*other.x)) {}

};

... and then the flip side of that ...

struct OptionallyAllocates {

int *x;
OptionallyAllocates () : x(new int(0)) {}
OptionallyAllocates (const Allocates &other) {
  // try / catch(...) would be fine here if std::nothrow is unappealing
  x = new(std::nothrow) int(*other.x));
}

};

test/clang-tidy/cert-throw-exception-type.cpp
2

Doesn't this need an "| FileCheck %s"

Added new test cases

aaron.ballman marked an inline comment as done.Nov 12 2015, 9:36 AM
aaron.ballman added inline comments.
test/clang-tidy/cert-throw-exception-type.cpp
3

Doesn't this need an "| FileCheck %s"

No, check_clang_tidy handles that for you.

alexfh added inline comments.Nov 12 2015, 10:04 AM
clang-tidy/cert/ThrownExceptionTypeCheck.cpp
37

I'd slightly prefer this check to be expressed as a matcher:

cxxThrowExpr(has(cxxConstructExpr(hasDeclaration(<insert your isNothrow() matcher here>))))

Which is also a more correct thing to do and doesn't seem to be "a lot harder" ;)

Looks good to me.

aaron.ballman marked an inline comment as done.

Addressing review comments.

aaron.ballman marked an inline comment as done.Nov 12 2015, 12:13 PM
aaron.ballman added inline comments.
clang-tidy/cert/ThrownExceptionTypeCheck.cpp
38

Your slight preference is my firmest desire! :-P Seriously, I think the code is more clear after implementing your suggestion, so thank you!

alexfh edited edge metadata.Nov 13 2015, 5:24 AM

Much better now. A few more comments.

clang-tidy/cert/ThrownExceptionTypeCheck.cpp
19

nit: I suggest changing isNoThrowCopyConstructible to isNoThrowCopyConstructor, because "constructible" is a trait of a class, not its constructor.

23

Out of curiosity: are we short-circuiting here for performance reasons or would the code below return false in this case?

35

Is this return reachable? If yes, when exactly does this happen and is there a test for this case?

aaron.ballman marked 4 inline comments as done.Nov 13 2015, 7:28 AM
aaron.ballman added inline comments.
clang-tidy/cert/ThrownExceptionTypeCheck.cpp
19

Good catch; that was a holdover from the previous version where it was operating on the CXXRecordDecl instead.

23

I pulled the logic from the unary type trait evaluation logic, but stripped out the bits that were already handled by the AST matcher logic itself. I don't believe this is actually necessary for this checker, however.

35

No, it is not reachable. There's no way, that I am aware of, to get a copy constructor with no function prototype.

aaron.ballman edited edge metadata.
aaron.ballman marked 3 inline comments as done.

Updated to address review comments.

alexfh accepted this revision.Nov 13 2015, 7:45 PM
alexfh edited edge metadata.

Looks good with one nit. Thank you!

clang-tidy/cert/ThrownExceptionTypeCheck.cpp
23

The comment is not relevant now.

This revision is now accepted and ready to land.Nov 13 2015, 7:45 PM

Commit in r253246