diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1695,9 +1695,6 @@ def ext_missing_exception_specification : ExtWarn< err_missing_exception_specification.Text>, InGroup>; -def ext_ms_missing_exception_specification : ExtWarn< - err_missing_exception_specification.Text>, - InGroup; def err_noexcept_needs_constant_expression : Error< "argument to noexcept specifier must be a constant expression">; def err_exception_spec_not_parsed : Error< diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -391,9 +391,8 @@ NewProto->getExtProtoInfo().withExceptionSpec(ESI))); } - if (getLangOpts().MSVCCompat && ESI.Type != EST_DependentNoexcept) { - // Allow missing exception specifications in redeclarations as an extension. - DiagID = diag::ext_ms_missing_exception_specification; + if (getLangOpts().MSVCCompat && isDynamicExceptionSpec(ESI.Type)) { + DiagID = diag::ext_missing_exception_specification; ReturnValueOnError = false; } else if (New->isReplaceableGlobalAllocationFunction() && ESI.Type != EST_DependentNoexcept) { @@ -402,6 +401,10 @@ DiagID = diag::ext_missing_exception_specification; ReturnValueOnError = false; } else if (ESI.Type == EST_NoThrow) { + // Don't emit any warning for missing 'nothrow' in MSVC. + if (getLangOpts().MSVCCompat) { + return false; + } // Allow missing attribute 'nothrow' in redeclarations, since this is a very // common omission. DiagID = diag::ext_missing_exception_specification; diff --git a/clang/test/SemaCXX/MicrosoftCompatibility.cpp b/clang/test/SemaCXX/MicrosoftCompatibility.cpp --- a/clang/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/clang/test/SemaCXX/MicrosoftCompatibility.cpp @@ -2,6 +2,8 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.27 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=19.00 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions -fms-compatibility-version=18.00 +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++17 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions + #if defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT char16_t x; @@ -350,6 +352,7 @@ void foo(); // expected-note {{previous declaration}} void foo() throw(); // expected-warning {{exception specification in declaration does not match previous declaration}} +#if __cplusplus < 201703L void r6() throw(...); // expected-note {{previous declaration}} void r6() throw(int); // expected-warning {{exception specification in declaration does not match previous declaration}} @@ -362,6 +365,7 @@ virtual void f2() throw(...); virtual void f3(); }; +#endif class A { virtual ~A() throw(); @@ -377,14 +381,14 @@ #endif }; -} +void f4() throw(); // expected-note {{previous declaration is here}} +void f4() {} // expected-warning {{'f4' is missing exception specification 'throw()'}} -namespace PR25265 { -struct S { - int fn() throw(); // expected-note {{previous declaration is here}} -}; +__declspec(nothrow) void f5(); +void f5() {} -int S::fn() { return 0; } // expected-warning {{is missing exception specification}} +void f6() noexcept; // expected-note {{previous declaration is here}} +void f6() {} // expected-error {{'f6' is missing exception specification 'noexcept'}} } namespace PR43265 {