[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-14 Thread Douglas Yung via Phabricator via cfe-commits
dyung added a comment.

This appears to be failing on the PS4 linux bot likely due to the PS4 target 
has exceptions disabled by default. Can you take a look?

https://lab.llvm.org/buildbot/#/builders/139/builds/2441


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-14 Thread Balázs Kéri via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG530456caf908: [clang-tidy] Add new check 
bugprone-unhandled-exception-at-new. (authored by balazske).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,208 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+class bad_array_new_length : public bad_alloc {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (const std::bad_array_new_length &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: 

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-14 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 337344.
balazske added a comment.

Add another test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,208 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+class bad_array_new_length : public bad_alloc {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (const std::bad_array_new_length &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_none() throw() {
+  int *I = new int;
+  // 

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-13 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

LGTM!




Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst:7
+Finds calls to ``new`` that may throw ``std::bad_alloc`` exception and
+the exception handler is missing.
+

balazske wrote:
> aaron.ballman wrote:
> > This isn't quite accurate -- if the exception handler is missing or doesn't 
> > handle either `std::bad_alloc` or `std::exception`.
> I restructure the text, but do not want to mention `std::exception` because 
> it is a base class (handling of `std::exception` means handling of 
> `std::bad_alloc`), and then why not mention generic exception handler 
> (`catch(...)`). I think this text is for introduction only, should not be 
> totally precise.
The restructured text is good -- I just wanted the information *somewhere* so 
that users weren't surprised by the behavior.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:20
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);

balazske wrote:
> aaron.ballman wrote:
> > Another interesting test case would be when the user subclasses 
> > `std::bad_alloc` and throws errors of the subclass type from the allocation 
> > function which are in/correctly caught.
> In this case the check must find every (visible) subclass of `std::bad_alloc` 
> check if there is a catch block for every case. Even then a custom allocation 
> function may throw other classes (not derived from `std::bad_alloc`) or 
> classes (may be inherited from `std::bad_alloc` but not visible in the TU) 
> that are not checked. So this is still a partial solution, probably not 
> better than the rule that a handler for `bad_alloc` (or more generic) should 
> exist.
> So this is still a partial solution, probably not better than the rule that a 
> handler for bad_alloc (or more generic) should exist.

Okay, that's fair -- we can always address it in follow-up if it turns out to 
be an issue in practice.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-13 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:20
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);

aaron.ballman wrote:
> Another interesting test case would be when the user subclasses 
> `std::bad_alloc` and throws errors of the subclass type from the allocation 
> function which are in/correctly caught.
In this case the check must find every (visible) subclass of `std::bad_alloc` 
check if there is a catch block for every case. Even then a custom allocation 
function may throw other classes (not derived from `std::bad_alloc`) or classes 
(may be inherited from `std::bad_alloc` but not visible in the TU) that are not 
checked. So this is still a partial solution, probably not better than the rule 
that a handler for `bad_alloc` (or more generic) should exist.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-13 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst:7
+Finds calls to ``new`` that may throw ``std::bad_alloc`` exception and
+the exception handler is missing.
+

aaron.ballman wrote:
> This isn't quite accurate -- if the exception handler is missing or doesn't 
> handle either `std::bad_alloc` or `std::exception`.
I restructure the text, but do not want to mention `std::exception` because it 
is a base class (handling of `std::exception` means handling of 
`std::bad_alloc`), and then why not mention generic exception handler 
(`catch(...)`). I think this text is for introduction only, should not be 
totally precise.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-13 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 337078.
balazske marked 8 inline comments as done.
balazske added a comment.

Rebase, changed documentation, small fix in the code, more tests added.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,196 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+class bad_array_new_length : public bad_alloc {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (const std::bad_array_new_length &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for 

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-12 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp:28-30
+// Generic catch handler should match anything.
+if (CatchS->getCaughtType().isNull())
+  return true;

I think this should move above the call to `InnertMatcher.matches()` so that 
the inner matcher doesn't have to worry quite as much about getting null types.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst:7
+Finds calls to ``new`` that may throw ``std::bad_alloc`` exception and
+the exception handler is missing.
+

This isn't quite accurate -- if the exception handler is missing or doesn't 
handle either `std::bad_alloc` or `std::exception`.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst:17
+
+Calls to ``new`` can throw exception of type ``bad_alloc`` that should be
+handled by the code. Alternatively the nonthrowing form of ``new`` can be





Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:20
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);

Another interesting test case would be when the user subclasses 
`std::bad_alloc` and throws errors of the subclass type from the allocation 
function which are in/correctly caught.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:20
+
+void f1() noexcept {
+  int *I1 = new int;

aaron.ballman wrote:
> It would be useful to also have a test with a function-try-block to ensure 
> those are handled properly.
Still missing this test -- you should add one like:
```
void func() try {
  int *i = new int;
} catch (const std::bad_alloc &) {
}
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-12 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added a comment.

Ping.
The check now handles only check of allocation failure at `new`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-07 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 335767.
balazske added a comment.

Fix a crash, update documentation.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,180 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_none() throw() {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_1() throw(std::bad_alloc) {
+  int *I = new int;
+}
+
+void f_est_dynamic_2() throw(A) {
+  // the exception 

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-06 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added a comment.

Rename the check to "unhandled-bad_alloc" (or similar")? And the error message 
to " missing exception handler 'std::bad_alloc' "?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-04-06 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 335505.
balazske added a comment.

Removed check of possible exceptions from constructor call.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,175 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_none() throw() {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_1() throw(std::bad_alloc) {
+  int *I = new int;
+}
+
+void f_est_dynamic_2() throw(A) {

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-31 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:143
+  f_est_noexcept_dependent_used();
+}

balazske wrote:
> balazske wrote:
> > aaron.ballman wrote:
> > > You have tests for placement new with `nothrow_t`, but I think other 
> > > forms of placement new are also very interesting to test as those 
> > > typically don't throw.
> > > 
> > > Additionally, perhaps tests where the allocation functions have been 
> > > replaced by the user (such as a class allocation function)?
> > I realized that the case of user-defined constructor or allocation function 
> > allows to throw any kind of exception. So the check should be improved to 
> > handle this case: Not rely on the syntax of new expression, instead check 
> > if the called allocation function or the called constructor may throw, and 
> > if yes, check what exceptions are possible. What is your opinion, is it a 
> > better approach?
> > (And a function to collect all possible exceptions called from a function 
> > is needed, `ExceptionAnalyzer` seems usable.)
> It looks like that the user is free to define custom `operator new` and any 
> constructor called that may throw any exception. Even in the "nothrow" case 
> it is possible to use a constructor that may throw? If we would analyze every 
> possible throwable exception that may come out from a new-expression, the 
> checker would end up almost in a general checker that checks for uncaught 
> exceptions. At least it is easy to extend.
> Not rely on the syntax of new expression, instead check if the called 
> allocation function or the called constructor may throw, and if yes, check 
> what exceptions are possible. What is your opinion, is it a better approach?

I think that's a better approach.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:143
+  f_est_noexcept_dependent_used();
+}

aaron.ballman wrote:
> balazske wrote:
> > balazske wrote:
> > > aaron.ballman wrote:
> > > > You have tests for placement new with `nothrow_t`, but I think other 
> > > > forms of placement new are also very interesting to test as those 
> > > > typically don't throw.
> > > > 
> > > > Additionally, perhaps tests where the allocation functions have been 
> > > > replaced by the user (such as a class allocation function)?
> > > I realized that the case of user-defined constructor or allocation 
> > > function allows to throw any kind of exception. So the check should be 
> > > improved to handle this case: Not rely on the syntax of new expression, 
> > > instead check if the called allocation function or the called constructor 
> > > may throw, and if yes, check what exceptions are possible. What is your 
> > > opinion, is it a better approach?
> > > (And a function to collect all possible exceptions called from a function 
> > > is needed, `ExceptionAnalyzer` seems usable.)
> > It looks like that the user is free to define custom `operator new` and any 
> > constructor called that may throw any exception. Even in the "nothrow" case 
> > it is possible to use a constructor that may throw? If we would analyze 
> > every possible throwable exception that may come out from a new-expression, 
> > the checker would end up almost in a general checker that checks for 
> > uncaught exceptions. At least it is easy to extend.
> > Not rely on the syntax of new expression, instead check if the called 
> > allocation function or the called constructor may throw, and if yes, check 
> > what exceptions are possible. What is your opinion, is it a better approach?
> 
> I think that's a better approach.
> Even in the "nothrow" case it is possible to use a constructor that may throw?

Certainly -- the `nothrow` syntax is specifying that the allocation cannot 
throw (it either returns a valid pointer to the allocated memory or null), not 
that the constructor cannot throw if the allocation succeeds.

Is the check intended to care about *allocations* that fail or just exceptions 
in general around `new` expressions? If it's allocations that fail, then I 
wouldn't worry about the ctor's exception specification. If exceptions in 
general, then I agree that we're talking about a general checker for all 
uncaught exceptions in some ways.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-30 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 334156.
balazske added a comment.

Use `mayThrow`, improve test (user and class-specific cases).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,194 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept;
+void *operator new(std::size_t, void *) noexcept;
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void *operator new(std::size_t, int, int);
+void *operator new(std::size_t, int, int, int) noexcept;
+
+struct ClassSpecificNew {
+  void *operator new(std::size_t);
+  void *operator new(std::size_t, std::align_val_t);
+  void *operator new(std::size_t, int, int) noexcept;
+  void *operator new(std::size_t, int, int, int);
+};
+
+struct ConstructorTest {
+  ConstructorTest();
+  ConstructorTest(int) noexcept;
+};
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+}
+
+void f_new_nothrow() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_new_placement() noexcept {
+  char buf[100];
+  int *I = new (buf) int;
+}
+
+void f_new_user_defined() noexcept {
+  int *I1 = new (1, 2) int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  int *I2 = new (1, 2, 3) int;
+}
+
+void f_class_specific() noexcept {
+  ClassSpecificNew *N1 = new ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N2 = new (static_cast(1)) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+  ClassSpecificNew *N3 = new (1, 2) ClassSpecificNew;
+  ClassSpecificNew *N4 = new (1, 2, 3) ClassSpecificNew;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_constructor() noexcept {
+  ConstructorTest *T1 = new ConstructorTest;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: missing exception handler for allocation failure at 'new'
+  ConstructorTest *T2 = new ConstructorTest{1};
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: missing exception handler for allocation failure at 'new'
+  ConstructorTest *T3 = new (std::nothrow) ConstructorTest;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: missing exception handler for 

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-30 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:143
+  f_est_noexcept_dependent_used();
+}

balazske wrote:
> aaron.ballman wrote:
> > You have tests for placement new with `nothrow_t`, but I think other forms 
> > of placement new are also very interesting to test as those typically don't 
> > throw.
> > 
> > Additionally, perhaps tests where the allocation functions have been 
> > replaced by the user (such as a class allocation function)?
> I realized that the case of user-defined constructor or allocation function 
> allows to throw any kind of exception. So the check should be improved to 
> handle this case: Not rely on the syntax of new expression, instead check if 
> the called allocation function or the called constructor may throw, and if 
> yes, check what exceptions are possible. What is your opinion, is it a better 
> approach?
> (And a function to collect all possible exceptions called from a function is 
> needed, `ExceptionAnalyzer` seems usable.)
It looks like that the user is free to define custom `operator new` and any 
constructor called that may throw any exception. Even in the "nothrow" case it 
is possible to use a constructor that may throw? If we would analyze every 
possible throwable exception that may come out from a new-expression, the 
checker would end up almost in a general checker that checks for uncaught 
exceptions. At least it is easy to extend.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-26 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:143
+  f_est_noexcept_dependent_used();
+}

aaron.ballman wrote:
> You have tests for placement new with `nothrow_t`, but I think other forms of 
> placement new are also very interesting to test as those typically don't 
> throw.
> 
> Additionally, perhaps tests where the allocation functions have been replaced 
> by the user (such as a class allocation function)?
I realized that the case of user-defined constructor or allocation function 
allows to throw any kind of exception. So the check should be improved to 
handle this case: Not rely on the syntax of new expression, instead check if 
the called allocation function or the called constructor may throw, and if yes, 
check what exceptions are possible. What is your opinion, is it a better 
approach?
(And a function to collect all possible exceptions called from a function is 
needed, `ExceptionAnalyzer` seems usable.)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-24 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst:17
+Calls to ``new`` can throw exception of type ``bad_alloc`` that should be
+handled by the code. Alternatively the nonthrowing form of ``new`` can be
+used. The check verifies that the exception is handled in the function





Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:20
+
+void f1() noexcept {
+  int *I1 = new int;

It would be useful to also have a test with a function-try-block to ensure 
those are handled properly.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp:143
+  f_est_noexcept_dependent_used();
+}

You have tests for placement new with `nothrow_t`, but I think other forms of 
placement new are also very interesting to test as those typically don't throw.

Additionally, perhaps tests where the allocation functions have been replaced 
by the user (such as a class allocation function)?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-03-09 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added a comment.

Ping.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-02-26 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 326642.
balazske added a comment.

Rebase, fixes according to review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,143 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &);
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &);
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+}
+
+void f3() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_none() throw() {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_1() throw(std::bad_alloc) {
+  int *I = new int;
+}
+
+void f_est_dynamic_2() throw(A) {
+  // the exception specification list is not checked
+  int *I = new int;
+}
+
+template 
+void f_est_noexcept_dependent_unused() noexcept(P) {
+  int *I = new int;
+}
+
+template 
+void f_est_noexcept_dependent_used() noexcept(P) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_1() {
+  f_est_noexcept_dependent_used();
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -99,6 +99,7 @@
`bugprone-too-small-loop-variable `_,
`bugprone-undefined-memory-manipulation `_,
`bugprone-undelegated-constructor `_,
+   `bugprone-unhandled-exception-at-new `_,
`bugprone-unhandled-self-assignment `_,
`bugprone-unused-raii `_, "Yes"
`bugprone-unused-return-value `_,
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - bugprone-unhandled-exception-at-new
+

[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-02-23 Thread Nathan James via Phabricator via cfe-commits
njames93 added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp:23-24
+const CXXCatchStmt *CatchS = Node.getHandler(I);
+if (InnerMatcher.matches(CatchS->getCaughtType(), Finder, Builder))
+  return true;
+// Generic catch handler should match anything.

This can leak bound nodes If it doesn't match.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h:28
+  bool isLanguageVersionSupported(const LangOptions ) const override {
+return LangOpts.CPlusPlus;
+  }

I'd suggest this check is only ran when exceptions are enabled.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-02-22 Thread Eugene Zelenko via Phabricator via cfe-commits
Eugene.Zelenko added inline comments.



Comment at: clang-tools-extra/docs/ReleaseNotes.rst:73
+
+New checks
+^^

Please rebase from trunk.



Comment at: clang-tools-extra/docs/ReleaseNotes.rst:79
+
+Finds calls to ``new`` that may throw exception that is not handled.
 

Please indent.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97196/new/

https://reviews.llvm.org/D97196

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97196: [clang-tidy] Add new check 'bugprone-unhandled-exception-at-new'.

2021-02-22 Thread Balázs Kéri via Phabricator via cfe-commits
balazske created this revision.
Herald added subscribers: martong, gamesh411, Szelethus, dkrupp, xazax.hun, 
whisperity, mgorny.
balazske requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97196

Files:
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-unhandled-exception-at-new.cpp
@@ -0,0 +1,133 @@
+// RUN: %check_clang_tidy -std=c++14 %s bugprone-unhandled-exception-at-new %t
+
+namespace std {
+typedef __typeof__(sizeof(0)) size_t;
+enum class align_val_t : std::size_t {};
+class exception {};
+class bad_alloc : public exception {};
+struct nothrow_t {};
+extern const nothrow_t nothrow;
+} // namespace std
+
+void *operator new(std::size_t, const std::nothrow_t &);
+void *operator new(std::size_t, std::align_val_t, const std::nothrow_t &);
+
+class A {};
+typedef std::bad_alloc badalloc1;
+using badalloc2 = std::bad_alloc;
+using badalloc3 = std::bad_alloc &;
+
+void f1() noexcept {
+  int *I1 = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: missing exception handler for allocation failure at 'new'
+  try {
+int *I2 = new int;
+try {
+  int *I3 = new int;
+} catch (A) {
+}
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::bad_alloc &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const badalloc1 &) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc2) {
+  }
+
+  try {
+int *I = new int;
+  } catch (badalloc3) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (std::bad_alloc *) {
+  }
+
+  try {
+int *I = new int;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: missing exception handler for allocation failure at 'new'
+  } catch (A) {
+  }
+}
+
+void f2() noexcept {
+  try {
+int *I = new int;
+  } catch (A) {
+  } catch (std::bad_alloc) {
+  }
+
+  try {
+int *I = new int;
+  } catch (...) {
+  }
+
+  try {
+int *I = new int;
+  } catch (const std::exception &) {
+  }
+}
+
+void f3() noexcept {
+  int *I1 = new (std::nothrow) int;
+  int *I2 = new (static_cast(1), std::nothrow) int;
+}
+
+void f_est_none() {
+  int *I = new int;
+}
+
+void f_est_noexcept_false() noexcept(false) {
+  int *I = new int;
+}
+
+void f_est_noexcept_true() noexcept(true) {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_none() throw() {
+  int *I = new int;
+  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: missing exception handler for allocation failure at 'new'
+}
+
+void f_est_dynamic_1() throw(std::bad_alloc) {
+  int *I = new int;
+}
+
+void f_est_dynamic_2() throw(A) {
+  // the exception specification list is not checked
+  int *I = new int;
+}
+
+template 
+void f_est_noexcept_dependent() noexcept(P) {
+  int *I = new int;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -99,6 +99,7 @@
`bugprone-too-small-loop-variable `_,
`bugprone-undefined-memory-manipulation `_,
`bugprone-undelegated-constructor `_,
+   `bugprone-unhandled-exception-at-new `_,
`bugprone-unhandled-self-assignment `_,
`bugprone-unused-raii `_, "Yes"
`bugprone-unused-return-value `_,
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-exception-at-new.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - bugprone-unhandled-exception-at-new
+
+bugprone-unhandled-exception-at-new
+===
+
+Finds calls to ``new`` that may throw exception that is not handled.
+
+.. code-block:: c++
+
+  int *f() noexcept {
+int *p