If a function with a dynamic-exception-specification throws an exception that is not listed in the dynamic-exception-specification, the function std::unexpected() is called ([exception.unexpected]) immediately after completing the stack unwinding for the former function.
[ Note: By default, std::unexpected() calls std::terminate(), but a program can install its own handler function ([set.unexpected]). In either case, the constraints in the following paragraph apply. — end note ]
The std::unexpected() function shall not return, but it can throw (or re-throw) an exception. If it throws a new exception which is allowed by the exception specification which previously was violated, then the search for another handler will continue at the call of the function whose exception specification was violated. If it throws or rethrows an exception that the dynamic-exception-specification does not allow then the following happens: If the dynamic-exception-specification does not include the class std::bad_exception ([bad.exception]) then the function std::terminate() is called, otherwise the thrown exception is replaced by an implementation-defined object of the type std::bad_exception and the search for another handler will continue at the call of the function whose dynamic-exception-specification was violated.
Thus, a dynamic-exception-specification guarantees that only the listed exceptions will be thrown. If the dynamic-exception-specification includes the type std::bad_exception then any exception not on the list may be replaced by std::bad_exception within the function std::unexpected().