mattd updated this revision to Diff 176515.
mattd added a comment.

- Move the HasNoexcept lambda to its own static function.
- Added an additional check in HasNoexcept to recursively check return values.
- Modified the parameter check in Sema::CheckFunctionDeclaration to use 
llvm::any_of, all we need to know is if any of the parameters might have a 
mangling change.
- Updated the test to include the example provided by @Rakete1111.


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

https://reviews.llvm.org/D55039

Files:
  lib/Sema/SemaDecl.cpp
  test/CXX/except/except.spec/p2-places.cpp
  test/SemaCXX/cxx1z-noexcept-function-type.cpp

Index: test/SemaCXX/cxx1z-noexcept-function-type.cpp
===================================================================
--- test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -83,14 +83,18 @@
   auto f5() -> void (*)() throw();
   auto f6() -> void (&)() throw();
   auto f7() -> void (X::*)() throw();
+  void f8(int, void (*)(int, void (*)() noexcept));
+  void f9(void (*g())() noexcept);
 #if __cplusplus <= 201402L && !defined(NO_COMPAT_MANGLING)
-  // expected-warning@-8 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}}
-  // expected-warning@-8 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f8' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-10 {{mangled name of 'f9' will change in C++17 due to non-throwing exception specification in function signature}}
 #endif
 
   // An instantiation-dependent exception specification needs to be mangled in
Index: test/CXX/except/except.spec/p2-places.cpp
===================================================================
--- test/CXX/except/except.spec/p2-places.cpp
+++ test/CXX/except/except.spec/p2-places.cpp
@@ -55,7 +55,7 @@
 
   void (*h())() noexcept(false);
 
-  void (*i() noexcept(false))(void (*)() noexcept(true)) noexcept(false);
+  void (*i() noexcept(false))(void (*)() noexcept(true)) noexcept(false); // expected-warning {{mangled name of 'i' will change in C++17 due to non-throwing exception specification in function signature}}
 
   void (**k)(void pfa() noexcept(false)); // no-error
 
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9914,6 +9914,28 @@
       OldDecl, MergeTypeWithPrevious, Previous);
 }
 
+/// Returns true if the type T is a function type that contains a noexcept specifier.
+/// This check recursively checks the params and return types of T if T happens
+/// to be a function.
+static bool hasNoexcept(QualType T) {
+  // Strip off declarator chunks that could be between us and a function
+  // type. We don't need to look far, exception specifications are very
+  // restricted prior to C++17.
+  if (auto *RT = T->getAs<ReferenceType>())
+    T = RT->getPointeeType();
+  else if (T->isAnyPointerType())
+    T = T->getPointeeType();
+  else if (auto *MPT = T->getAs<MemberPointerType>())
+    T = MPT->getPointeeType();
+  if (auto *FPT = T->getAs<FunctionProtoType>()) {
+    if (FPT->isNothrow() || hasNoexcept(FPT->getReturnType()) ||
+        llvm::any_of(FPT->param_types(),
+                     [](QualType Q) { return hasNoexcept(Q); }))
+      return true;
+  }
+  return false;
+}
+
 /// Perform semantic checking of a new function declaration.
 ///
 /// Performs semantic analysis of the new function declaration
@@ -10240,30 +10262,14 @@
     // most cases, and exception specifications are not permitted in most other
     // contexts where they could make it into a mangling.)
     if (!getLangOpts().CPlusPlus17 && !NewFD->getPrimaryTemplate()) {
-      auto HasNoexcept = [&](QualType T) -> bool {
-        // Strip off declarator chunks that could be between us and a function
-        // type. We don't need to look far, exception specifications are very
-        // restricted prior to C++17.
-        if (auto *RT = T->getAs<ReferenceType>())
-          T = RT->getPointeeType();
-        else if (T->isAnyPointerType())
-          T = T->getPointeeType();
-        else if (auto *MPT = T->getAs<MemberPointerType>())
-          T = MPT->getPointeeType();
-        if (auto *FPT = T->getAs<FunctionProtoType>())
-          if (FPT->isNothrow())
-            return true;
-        return false;
-      };
-
       auto *FPT = NewFD->getType()->castAs<FunctionProtoType>();
-      bool AnyNoexcept = HasNoexcept(FPT->getReturnType());
-      for (QualType T : FPT->param_types())
-        AnyNoexcept |= HasNoexcept(T);
-      if (AnyNoexcept)
+      if (hasNoexcept(FPT->getReturnType()) ||
+          llvm::any_of(FPT->param_types(),
+                       [](QualType Q) { return hasNoexcept(Q); })) {
         Diag(NewFD->getLocation(),
              diag::warn_cxx17_compat_exception_spec_in_signature)
             << NewFD;
+      }
     }
 
     if (!Redeclaration && LangOpts.CUDA)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to