]> granicus.if.org Git - clang/commitdiff
PR38141: check whether noexcept-specifications are equivalent in redeclarations
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Jul 2018 21:11:25 +0000 (21:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Jul 2018 21:11:25 +0000 (21:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336946 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExceptionSpec.cpp
test/CXX/except/except.spec/p3.cpp
test/SemaCXX/cxx1z-noexcept-function-type.cpp

index 8dce6d59c60e1d2eb25b008b8f182cf6f16b8b11..df5bc9b82b96a7bac57cb1f43ed20d1003039a4d 100644 (file)
@@ -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.
index 03f1d7626c0d17c08fb8da098e54bac7a2dd3e5f..d5af4651047fa5a6eaa52f24406bf66d0a01f774 100644 (file)
@@ -104,3 +104,13 @@ void* operator new(mysize_t);
 void* operator new[](mysize_t);
 void* operator new[](mysize_t) throw(std::bad_alloc);
 
+template<bool X> void equivalent() noexcept (X);
+template<bool X> void equivalent() noexcept (X);
+
+template<bool X, bool Y> void not_equivalent() noexcept (X); // expected-note {{previous}}
+template<bool X, bool Y> void not_equivalent() noexcept (Y); // expected-error {{does not match}}
+
+template<bool X> 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<bool P> void missing(); // expected-error {{missing exception specification 'noexcept(X)'}}
index 814b04c6e42f1887c6bb7cee37d01e881dedb0fe..82ed724e1bd9749c16ff2c58fb1666f67559481b 100644 (file)
@@ -10,7 +10,7 @@ template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type
 template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}}
 
 template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}}
-template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{conflicting types}}
+template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{does not match previous}}
 
 // These have the same canonical type, but are still different.
 template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}}