Repository: google/googletest
File: googlemock/include/gmock/gmock-matchers.h (C/C++)

Code before:
    *os << "throws an exception of type " << GetTypeName<Err>();
    if (matcher_.GetDescriber() != nullptr) {
      *os << " which ";
      matcher_.DescribeTo(os);
    }
  }

  void DescribeNegationTo(::std::ostream* os) const {
    *os << "not (";
    DescribeTo(os);
    *os << ")";
  }

  template <typename T>
  bool MatchAndExplain(T&& x, MatchResultListener* listener) const {
    try {
      (void)(std::forward<T>(x)());
    } catch (const Err& err) {
      *listener << "throws an exception of type " << GetTypeName<Err>();
      if (matcher_.GetDescriber() != nullptr) {
        *listener << " ";
        return matcher_.MatchAndExplain(err, listener);
      } else {
        return true;
      }
    } catch (const std::exception& err) {
#if GTEST_HAS_RTTI
      *listener << "throws an exception of type "
          << GetTypeName(typeid(err)) << " ";
#else
      *listener << "throws an std::exception-derived error ";
#endif
      *listener << "with description \"" << err.what() << "\"";
      return false;
    } catch (...) {
      *listener << "throws an exception of some other type";
      return false;
    }
    *listener << "does not throw any exception";
    return false;
  }

 private:
  const Matcher<const Err&> matcher_;
};

}  // namespace internal

// Throws()
// Throws(exceptionMatcher)
// ThrowsMessage(messageMatcher)

Review comment (bug):
What happens when `Err` is of type `std::exception`? This will fail to compile, yes? (I think there should be a test for that as well, unless it is intentionally unsupported)

Code after:

  // If the matchee raises an exception of a wrong type, we'd like to
  // catch it and print its message and type. To do that, we add an additional
  // catch clause:
  //
  //     try { ... }
  //     catch (const Err&) { /* an expected exception */ }
  //     catch (const std::exception&) { /* exception of a wrong type */ }
  //
  // However, if the `Err` itself is `std::exception`, we'd end up with two
  // identical `catch` clauses:
  //
  //     try { ... }
  //     catch (const std::exception&) { /* an expected exception */ }
  //     catch (const std::exception&) { /* exception of a wrong type */ }
  //
  // This can cause a warning or an error in some compilers. To resolve
  // the issue, we use a fake error type whenever `Err` is `std::exception`:
  //
  //     try { ... }
  //     catch (const std::exception&) { /* an expected exception */ }
  //     catch (const NeverThrown&) { /* exception of a wrong type */ }
  using DefaultExceptionType = typename std::conditional<
      std::is_same<
          typename std::remove_cv<
              typename std::remove_reference<Err>::type>::type,
          std::exception>::value,
      const NeverThrown&,
      const std::exception&>::type;

 public:
  ExceptionMatcherImpl(Matcher<const Err&> matcher)
      : matcher_(std::move(matcher)) {}

  void DescribeTo(std::ostream* os) const {
    *os << "throws an exception which is a " << GetTypeName<Err>();
    if (matcher_.GetDescriber() != nullptr) {
      *os << " which ";
      matcher_.DescribeTo(os);
    }
  }

  void DescribeNegationTo(std::ostream* os) const {
    *os << "not (";
    DescribeTo(os);
    *os << ")";
  }

  template <typename T>
  bool MatchAndExplain(T&& x, MatchResultListener* listener) const {
    try {