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