[PATCH] D33333: Emit warning when throw exception in destruct or dealloc functions which has a (possible implicit) noexcept specifier

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 1 09:55:57 PDT 2017


aaron.ballman added a comment.

In https://reviews.llvm.org/D33333#768332, @jyu2 wrote:

> Okay this CFG version of this change.  In this change I am basic using same algorithm with -Winfinite-recursion.
>
> In addition to my original implementation,  I add handler type checking which basic using  https://reviews.llvm.org/D19201 method.


Thank you, I think this is a step in the right direction!

> There are couple things I am worry about this implementation:
>  1> compile time...

Do you have any timing data on whether this has a negative performance impact?

> 2> Correctness...

Your implementation looks reasonable to me, but with further review (and good tests), we should have a better grasp on correctness.

> 3> Stack overflow for large CFG...

I would be surprised if that were a problem, but is something we could address if it ever arises.



================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:6341
+    : Warning<"%0 has a non-throwing exception specification but can still "
+      "throw, may result in unexpected program termination.">, 
+      InGroup<Exceptions>;
----------------
throw, may -> throw, which may

Also, remove the period at the end of the diagnostic.


================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:6344
+def note_throw_in_dtor 
+    : Note<"destructor or deallocator has a (possible implicit) non-throwing "
+      "excepton specification">;
----------------
possible -> possibly


================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:6347
+def note_throw_in_function 
+    : Note<"nonthrowing function declare here">;
 def err_seh_try_outside_functions : Error<
----------------
nonthrowing -> non-throwing

(to be consistent with other diagnostics.)


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:290
+
+static bool mayThrowBeCaughted(const CXXThrowExpr *Throw,
+                               const CXXCatchStmt *Catch) {
----------------
Caughted -> Caught


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:292
+                               const CXXCatchStmt *Catch) {
+  bool MayCaught = false;
+  const auto *ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull();
----------------
MayCaught -> IsCaught ?


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:293-294
+  bool MayCaught = false;
+  const auto *ThrowType = Throw->getSubExpr()->getType().getTypePtrOrNull();
+  const auto *CaughtType = Catch->getCaughtType().getTypePtrOrNull();
+
----------------
Please don't use `auto` unless the type is explicitly spelled out in the initializer (here and elsewhere).


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:298
+    return true;
+  if (CaughtType == ThrowType)
+    return true;
----------------
You can combine this with the above check.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:304
+  if (CaughtAsRecordType && ThrowTypeAsRecordType) {
+    if (CaughtAsRecordType == ThrowTypeAsRecordType)
+      MayCaught = true;
----------------
This does not seem quite correct. Consider:
```
struct S{};

void f() {
  try {
    throw S{};
  } catch (const S *s) {
  }
}
```


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:311
+
+static bool mayThrowBeCaughtedByHandlers(const CXXThrowExpr *CE,
+                                         const CXXTryStmt *TryStmt) {
----------------
mayThrowBeCaughtedByHandlers -> isThrowCaughtByAHandler


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:314
+  bool Caught = false;
+  for (unsigned h = 0; h < TryStmt->getNumHandlers(); ++h) {
+    const CXXCatchStmt *CS = TryStmt->getHandler(h);
----------------
h -> H (or Idx, or anything else that meets the coding standard).


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:317-318
+    if (mayThrowBeCaughted(CE, CS)) {
+      Caught = true;
+      break;
+    }
----------------
Just return true here instead of setting a local variable. Return false below.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:324
+
+static bool hasThrowOutNothrowingFuncInPath(CFGBlock &Block,
+                                            SourceLocation *OpLoc) {
----------------
Perhaps it's more clear as: `doesThrowEscapePath()`?


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:330
+      continue;
+    const CXXThrowExpr *CE =
+        dyn_cast<CXXThrowExpr>(B.getAs<CFGStmt>()->getStmt());
----------------
Can use `const auto *` here.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:334
+      continue;
+    else
+      HasThrowOutFunc = true;
----------------
You can drop the `else` here and just set `HasThrowOutFunc` to true.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:337
+
+    (*OpLoc) = CE->getThrowLoc();
+    for (CFGBlock::const_succ_iterator I = Block.succ_begin(),
----------------
If OpLoc cannot be null, you should take it by reference. If it can be null, then you should guard against that here (and drop the parens).


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:338-340
+    for (CFGBlock::const_succ_iterator I = Block.succ_begin(),
+                                       E = Block.succ_end();
+         I != E; ++I) {
----------------
You can use a range-based for loop over `Block.succs()`


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:376
+
+      if (hasThrowOutNothrowingFuncInPath(*CurBlock, OpLoc)) {
+        CurState = FoundPathForThrow;
----------------
Elide braces.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:384
+
+    for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
+      if (*I) {
----------------
Can use range-based for loop over `succs()`.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:420
+  SourceLocation OpLoc;
+  if (hasThrowOutNonThrowingFunc(FD, &OpLoc, cfg)) {
+    EmitDiagForCXXThrowInNonThrowingFunc(OpLoc, S, FD);
----------------
Elide braces.


================
Comment at: lib/Sema/AnalysisBasedWarnings.cpp:2282
 
+  //Check for throw out in non-throwing function.
+  if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func,
----------------
Space after `//`.
out in non-throwing -> out of a non-throwing


================
Comment at: test/SemaCXX/warn-throw-out-noexcept-func.cpp:1
+// RUN: %clang_cc1 %s  -fdelayed-template-parsing -fcxx-exceptions -fexceptions -fsyntax-only -Wexceptions -verify -std=c++11
+struct A {
----------------
Please drop the svn auto props.


https://reviews.llvm.org/D33333





More information about the cfe-commits mailing list