From 37d341d1f0d786e0df31a6983a80cf96c30d5faf Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Jul 2018 21:11:25 +0000 Subject: [PATCH] PR38141: check whether noexcept-specifications are equivalent in redeclarations git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336946 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExceptionSpec.cpp | 14 ++++++++++---- test/CXX/except/except.spec/p3.cpp | 10 ++++++++++ test/SemaCXX/cxx1z-noexcept-function-type.cpp | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 8dce6d59c6..df5bc9b82b 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -530,10 +530,16 @@ static bool CheckEquivalentExceptionSpecImpl( } } - // FIXME: We treat dependent noexcept specifications as compatible even if - // their expressions are not equivalent. - if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) - return false; + // C++14 [except.spec]p3: + // Two exception-specifications are compatible if [...] both have the form + // noexcept(constant-expression) and the constant-expressions are equivalent + if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) { + llvm::FoldingSetNodeID OldFSN, NewFSN; + Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true); + New->getNoexceptExpr()->Profile(NewFSN, S.Context, true); + if (OldFSN == NewFSN) + return false; + } // Dynamic exception specifications with the same set of adjusted types // are compatible. diff --git a/test/CXX/except/except.spec/p3.cpp b/test/CXX/except/except.spec/p3.cpp index 03f1d7626c..d5af465104 100644 --- a/test/CXX/except/except.spec/p3.cpp +++ b/test/CXX/except/except.spec/p3.cpp @@ -104,3 +104,13 @@ void* operator new(mysize_t); void* operator new[](mysize_t); void* operator new[](mysize_t) throw(std::bad_alloc); +template void equivalent() noexcept (X); +template void equivalent() noexcept (X); + +template void not_equivalent() noexcept (X); // expected-note {{previous}} +template void not_equivalent() noexcept (Y); // expected-error {{does not match}} + +template void missing() noexcept (X); // expected-note {{previous}} +// FIXME: The missing exception specification that we report here doesn't make +// sense in the context of this declaration. +template void missing(); // expected-error {{missing exception specification 'noexcept(X)'}} diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp index 814b04c6e4..82ed724e1b 100644 --- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -10,7 +10,7 @@ template void redecl1() noexcept(noexcept(T())); // ok, same type template void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}} template void redecl2() noexcept(A); // expected-note {{previous}} -template void redecl2() noexcept(B); // expected-error {{conflicting types}} +template void redecl2() noexcept(B); // expected-error {{does not match previous}} // These have the same canonical type, but are still different. template void redecl3() throw(A); // expected-note {{previous}} -- 2.40.0