mattd created this revision.
mattd added reviewers: erik.pilkington, rsmith.

The flag: `-Wc++17-compat-mangling` was not emitting a warning diagnostic in 
all cases, specifically if a function has parameters that happen to have 
function pointers that have  noexecept parameters.  For example:

  void fn(void (*)(void (*)() noexcept)){}

That example will produce different symbol names between c++17 and earlier 
dialects.  I believe that clang should be emitting the compatibility warning in 
this case.  This patch modifies the existing logic to recursively check the 
parameters of a function and warn if they too are noexcept.

This fixes PR39656.


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,16 @@
   auto f5() -> void (*)() throw();
   auto f6() -> void (&)() throw();
   auto f7() -> void (X::*)() throw();
+  void f8(int, void (*)(int, void (*)() 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@-9 {{mangled name of 'f1' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f2' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f3' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f4' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f5' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f6' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f7' will change in C++17 due to 
non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f8' 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
@@ -10209,7 +10209,7 @@
     // 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 {
+      std::function<bool(QualType)> 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.
@@ -10219,9 +10219,12 @@
           T = T->getPointeeType();
         else if (auto *MPT = T->getAs<MemberPointerType>())
           T = MPT->getPointeeType();
-        if (auto *FPT = T->getAs<FunctionProtoType>())
-          if (FPT->isNothrow())
+        if (auto *FPT = T->getAs<FunctionProtoType>()) {
+          if (FPT->isNothrow() ||
+              llvm::any_of(FPT->param_types(),
+                           [&](QualType Q) { return HasNoexcept(Q); }))
             return true;
+        }
         return false;
       };
 


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,16 @@
   auto f5() -> void (*)() throw();
   auto f6() -> void (&)() throw();
   auto f7() -> void (X::*)() throw();
+  void f8(int, void (*)(int, void (*)() 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@-9 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}}
+  // expected-warning@-9 {{mangled name of 'f8' 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
@@ -10209,7 +10209,7 @@
     // 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 {
+      std::function<bool(QualType)> 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.
@@ -10219,9 +10219,12 @@
           T = T->getPointeeType();
         else if (auto *MPT = T->getAs<MemberPointerType>())
           T = MPT->getPointeeType();
-        if (auto *FPT = T->getAs<FunctionProtoType>())
-          if (FPT->isNothrow())
+        if (auto *FPT = T->getAs<FunctionProtoType>()) {
+          if (FPT->isNothrow() ||
+              llvm::any_of(FPT->param_types(),
+                           [&](QualType Q) { return HasNoexcept(Q); }))
             return true;
+        }
         return false;
       };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to