[libc] Move FPExceptMatcher out of TestHelpers.h

TestHelpers.h pulls few pieces from LLVM libc's unittest framework
which aren't available on platforms like Fuchsia which use their own
unittest framework. So, by moving FPExceptMatcher to a different file
we can exclude LLVM libc specific pieces in a cleaner way.

In a later pass, it might make more sense to rename TestHelpers.h also
to FPMatcher.h. That way, we can make macros like EXPECT_FP_EQ to be
equivalent to EXPECT_EQ on platforms like Fuchsia.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D107129

GitOrigin-RevId: 3d758e68a766545db0cc92d177d309f0616a67f4
diff --git a/test/src/fenv/enabled_exceptions_test.cpp b/test/src/fenv/enabled_exceptions_test.cpp
index c30d675..f38c736 100644
--- a/test/src/fenv/enabled_exceptions_test.cpp
+++ b/test/src/fenv/enabled_exceptions_test.cpp
@@ -11,7 +11,7 @@
 #include "src/fenv/fetestexcept.h"
 
 #include "utils/FPUtil/FEnvUtils.h"
-#include "utils/FPUtil/TestHelpers.h"
+#include "utils/FPUtil/FPExceptMatcher.h"
 #include "utils/UnitTest/Test.h"
 
 #include <fenv.h>
diff --git a/test/src/fenv/feholdexcept_test.cpp b/test/src/fenv/feholdexcept_test.cpp
index 2f7b741..37b479f 100644
--- a/test/src/fenv/feholdexcept_test.cpp
+++ b/test/src/fenv/feholdexcept_test.cpp
@@ -9,7 +9,7 @@
 #include "src/fenv/feholdexcept.h"
 
 #include "utils/FPUtil/FEnvUtils.h"
-#include "utils/FPUtil/TestHelpers.h"
+#include "utils/FPUtil/FPExceptMatcher.h"
 #include "utils/UnitTest/Test.h"
 
 #include <fenv.h>
diff --git a/utils/FPUtil/CMakeLists.txt b/utils/FPUtil/CMakeLists.txt
index 49c594a..812bccb 100644
--- a/utils/FPUtil/CMakeLists.txt
+++ b/utils/FPUtil/CMakeLists.txt
@@ -36,6 +36,8 @@
 
 add_library(
   LibcFPTestHelpers
+    FPExceptMatcher.cpp
+    FPExceptMatcher.h
     TestHelpers.cpp
     TestHelpers.h
 )
diff --git a/utils/FPUtil/FPExceptMatcher.cpp b/utils/FPUtil/FPExceptMatcher.cpp
new file mode 100644
index 0000000..b8b30d5
--- /dev/null
+++ b/utils/FPUtil/FPExceptMatcher.cpp
@@ -0,0 +1,52 @@
+//===-- FPExceptMatchers.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "FPExceptMatcher.h"
+
+#include <fenv.h>
+#include <memory>
+#include <setjmp.h>
+#include <signal.h>
+
+namespace __llvm_libc {
+namespace fputil {
+namespace testing {
+
+#if defined(_WIN32)
+#define sigjmp_buf jmp_buf
+#define sigsetjmp(buf, save) setjmp(buf)
+#define siglongjmp(buf, val) longjmp(buf, val)
+#endif
+
+static thread_local sigjmp_buf jumpBuffer;
+static thread_local bool caughtExcept;
+
+static void sigfpeHandler(int sig) {
+  caughtExcept = true;
+  siglongjmp(jumpBuffer, -1);
+}
+
+FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
+  auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
+  std::unique_ptr<FunctionCaller> funcUP(func);
+
+  caughtExcept = false;
+  fenv_t oldEnv;
+  fegetenv(&oldEnv);
+  if (sigsetjmp(jumpBuffer, 1) == 0)
+    funcUP->call();
+  // We restore the previous floating point environment after
+  // the call to the function which can potentially raise SIGFPE.
+  fesetenv(&oldEnv);
+  signal(SIGFPE, oldSIGFPEHandler);
+  exceptionRaised = caughtExcept;
+}
+
+} // namespace testing
+} // namespace fputil
+} // namespace __llvm_libc
diff --git a/utils/FPUtil/FPExceptMatcher.h b/utils/FPUtil/FPExceptMatcher.h
new file mode 100644
index 0000000..883fcc2
--- /dev/null
+++ b/utils/FPUtil/FPExceptMatcher.h
@@ -0,0 +1,67 @@
+//===-- FPExceptMatcher.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_UTILS_FPUTIL_FP_EXCEPT_MATCHER_H
+#define LLVM_LIBC_UTILS_FPUTIL_FP_EXCEPT_MATCHER_H
+
+#ifndef LLVM_LIBC_TEST_USE_FUCHSIA
+
+#include "utils/UnitTest/Test.h"
+
+namespace __llvm_libc {
+namespace fputil {
+namespace testing {
+
+// TODO: Make the matcher match specific exceptions instead of just identifying
+// that an exception was raised.
+class FPExceptMatcher : public __llvm_libc::testing::Matcher<bool> {
+  bool exceptionRaised;
+
+public:
+  class FunctionCaller {
+  public:
+    virtual ~FunctionCaller(){};
+    virtual void call() = 0;
+  };
+
+  template <typename Func> static FunctionCaller *getFunctionCaller(Func func) {
+    struct Callable : public FunctionCaller {
+      Func f;
+      explicit Callable(Func theFunc) : f(theFunc) {}
+      void call() override { f(); }
+    };
+
+    return new Callable(func);
+  }
+
+  // Takes ownership of func.
+  explicit FPExceptMatcher(FunctionCaller *func);
+
+  bool match(bool unused) { return exceptionRaised; }
+
+  void explainError(testutils::StreamWrapper &stream) override {
+    stream << "A floating point exception should have been raised but it "
+           << "wasn't\n";
+  }
+};
+
+} // namespace testing
+} // namespace fputil
+} // namespace __llvm_libc
+
+#define ASSERT_RAISES_FP_EXCEPT(func)                                          \
+  ASSERT_THAT(                                                                 \
+      true,                                                                    \
+      __llvm_libc::fputil::testing::FPExceptMatcher(                           \
+          __llvm_libc::fputil::testing::FPExceptMatcher::getFunctionCaller(    \
+              func)))
+#else
+#define ASSERT_RAISES_FP_EXCEPT(func) ASSERT_DEATH(func, WITH_SIGNAL(SIGFPE))
+#endif // LLVM_LIBC_TEST_USE_FUCHSIA
+
+#endif // LLVM_LIBC_UTILS_FPUTIL_FP_EXCEPT_MATCHER_H
diff --git a/utils/FPUtil/TestHelpers.cpp b/utils/FPUtil/TestHelpers.cpp
index 21053c8..2c7614e 100644
--- a/utils/FPUtil/TestHelpers.cpp
+++ b/utils/FPUtil/TestHelpers.cpp
@@ -10,10 +10,6 @@
 
 #include "FPBits.h"
 
-#include <fenv.h>
-#include <memory>
-#include <setjmp.h>
-#include <signal.h>
 #include <string>
 
 namespace __llvm_libc {
@@ -74,36 +70,6 @@
 template void describeValue<long double>(const char *, long double,
                                          testutils::StreamWrapper &);
 
-#if defined(_WIN32)
-#define sigjmp_buf jmp_buf
-#define sigsetjmp(buf, save) setjmp(buf)
-#define siglongjmp(buf, val) longjmp(buf, val)
-#endif
-
-static thread_local sigjmp_buf jumpBuffer;
-static thread_local bool caughtExcept;
-
-static void sigfpeHandler(int sig) {
-  caughtExcept = true;
-  siglongjmp(jumpBuffer, -1);
-}
-
-FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
-  auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
-  std::unique_ptr<FunctionCaller> funcUP(func);
-
-  caughtExcept = false;
-  fenv_t oldEnv;
-  fegetenv(&oldEnv);
-  if (sigsetjmp(jumpBuffer, 1) == 0)
-    funcUP->call();
-  // We restore the previous floating point environment after
-  // the call to the function which can potentially raise SIGFPE.
-  fesetenv(&oldEnv);
-  signal(SIGFPE, oldSIGFPEHandler);
-  exceptionRaised = caughtExcept;
-}
-
 } // namespace testing
 } // namespace fputil
 } // namespace __llvm_libc
diff --git a/utils/FPUtil/TestHelpers.h b/utils/FPUtil/TestHelpers.h
index 286f443..263eace 100644
--- a/utils/FPUtil/TestHelpers.h
+++ b/utils/FPUtil/TestHelpers.h
@@ -61,39 +61,6 @@
   return FPMatcher<T, C>(expectedValue);
 }
 
-// TODO: Make the matcher match specific exceptions instead of just identifying
-// that an exception was raised.
-class FPExceptMatcher : public __llvm_libc::testing::Matcher<bool> {
-  bool exceptionRaised;
-
-public:
-  class FunctionCaller {
-  public:
-    virtual ~FunctionCaller(){};
-    virtual void call() = 0;
-  };
-
-  template <typename Func> static FunctionCaller *getFunctionCaller(Func func) {
-    struct Callable : public FunctionCaller {
-      Func f;
-      explicit Callable(Func theFunc) : f(theFunc) {}
-      void call() override { f(); }
-    };
-
-    return new Callable(func);
-  }
-
-  // Takes ownership of func.
-  explicit FPExceptMatcher(FunctionCaller *func);
-
-  bool match(bool unused) { return exceptionRaised; }
-
-  void explainError(testutils::StreamWrapper &stream) override {
-    stream << "A floating point exception should have been raised but it "
-           << "wasn't\n";
-  }
-};
-
 } // namespace testing
 } // namespace fputil
 } // namespace __llvm_libc
@@ -131,15 +98,4 @@
       __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_NE>( \
           expected))
 
-#ifdef LLVM_LIBC_TEST_USE_FUCHSIA
-#define ASSERT_RAISES_FP_EXCEPT(func) ASSERT_DEATH(func, WITH_SIGNAL(SIGFPE))
-#else
-#define ASSERT_RAISES_FP_EXCEPT(func)                                          \
-  ASSERT_THAT(                                                                 \
-      true,                                                                    \
-      __llvm_libc::fputil::testing::FPExceptMatcher(                           \
-          __llvm_libc::fputil::testing::FPExceptMatcher::getFunctionCaller(    \
-              func)))
-#endif // LLVM_LIBC_TEST_USE_FUCHSIA
-
 #endif // LLVM_LIBC_UTILS_FPUTIL_TEST_HELPERS_H