fix: support NVIDIA-PGI HPC SDK (#2475)

* Added guards to the includes

Added new CI config

Added new trigger

Changed CI workflow name

Debug CI

Debug CI

Debug CI

Debug CI

Added flags fro PGI

Disable Eigen

Removed tests that fail

Uncomment lines

* fix: missing include

fix: minor style cleanup

tests: support skipping

ci: remove and tighten a bit

fix: try msvc workaround for pgic

* tests: split up prealoc tests

* fix: PGI compiler fix

* fix: PGI void_t only

* fix: try to appease nvcc

* ci: better ordering for slow tests

* ci: minor improvements to testing

* ci: Add NumPy to testing

* ci: Eigen generates CUDA warnings / PGI errors

* Added CentOS7 back for a moment

* Fix YAML

* ci: runs-on missing

* centos7 is missing pytest

* ci: use C++11 on CentOS 7

* ci: test something else

* Try just adding flags on CentOS 7

* fix: CentOS 7

* refactor: move include to shared location

* Added verbose flag

* Try to use system cmake3 on CI

* Try to use system cmake3 on CI, attempt2

* Try to use system cmake3 on CI, attempt3

* tests: not finding pytest should be a warning, not a fatal error

* tests: cleanup

* Weird issue?

* fix: final polish

Co-authored-by: Andrii Verbytskyi <andrii.verbytskyi@mpp.mpg.de>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Andrii Verbytskyi <averbyts@cern.ch>
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e59c75c..45e094b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -16,6 +16,29 @@
   cmake_policy(VERSION 3.18)
 endif()
 
+# Only needed for CMake < 3.5 support
+include(CMakeParseArguments)
+
+# Filter out items; print an optional message if any items filtered
+#
+# Usage:
+#   pybind11_filter_tests(LISTNAME file1.cpp file2.cpp ... MESSAGE "")
+#
+macro(PYBIND11_FILTER_TESTS LISTNAME)
+  cmake_parse_arguments(ARG "" "MESSAGE" "" ${ARGN})
+  set(PYBIND11_FILTER_TESTS_FOUND OFF)
+  foreach(filename IN LISTS ARG_UNPARSED_ARGUMENTS)
+    list(FIND ${LISTNAME} ${filename} _FILE_FOUND)
+    if(_FILE_FOUND GREATER -1)
+      list(REMOVE_AT ${LISTNAME} ${_FILE_FOUND})
+      set(PYBIND11_FILTER_TESTS_FOUND ON)
+    endif()
+  endforeach()
+  if(PYBIND11_FILTER_TESTS_FOUND AND ARG_MESSAGE)
+    message(STATUS "${ARG_MESSAGE}")
+  endif()
+endmacro()
+
 # New Python support
 if(DEFINED Python_EXECUTABLE)
   set(PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
@@ -34,6 +57,9 @@
 set(PYBIND11_TEST_OVERRIDE
     ""
     CACHE STRING "Tests from ;-separated list of *.cpp files will be built instead of all tests")
+set(PYBIND11_TEST_FILTER
+    ""
+    CACHE STRING "Tests from ;-separated list of *.cpp files will be removed from all tests")
 
 if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
   # We're being loaded directly, i.e. not via add_subdirectory, so make this
@@ -106,21 +132,23 @@
   set(PYBIND11_TEST_FILES ${PYBIND11_TEST_OVERRIDE})
 endif()
 
-# Skip test_async for Python < 3.5
-list(FIND PYBIND11_TEST_FILES test_async.cpp PYBIND11_TEST_FILES_ASYNC_I)
-if((PYBIND11_TEST_FILES_ASYNC_I GREATER -1) AND (PYTHON_VERSION VERSION_LESS 3.5))
-  message(STATUS "Skipping test_async because Python version ${PYTHON_VERSION} < 3.5")
-  list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_ASYNC_I})
+# You can also filter tests:
+if(PYBIND11_TEST_FILTER)
+  pybind11_filter_tests(PYBIND11_TEST_FILES ${PYBIND11_TEST_FILTER})
+endif()
+
+if(PYTHON_VERSION VERSION_LESS 3.5)
+  pybind11_filter_tests(PYBIND11_TEST_FILES test_async.cpp MESSAGE
+                        "Skipping test_async on Python 2")
 endif()
 
 # Skip tests for CUDA check:
 # /pybind11/tests/test_constants_and_functions.cpp(125):
 #   error: incompatible exception specifications
-list(FIND PYBIND11_TEST_FILES test_constants_and_functions.cpp PYBIND11_TEST_FILES_CAF_I)
-if((PYBIND11_TEST_FILES_CAF_I GREATER -1) AND PYBIND11_CUDA_TESTS)
-  message(
-    STATUS "Skipping test_constants_and_functions due to incompatible exception specifications")
-  list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_CAF_I})
+if(PYBIND11_CUDA_TESTS)
+  pybind11_filter_tests(
+    PYBIND11_TEST_FILES test_constants_and_functions.cpp MESSAGE
+    "Skipping test_constants_and_functions due to incompatible exception specifications")
 endif()
 
 string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
@@ -318,7 +346,7 @@
   endif()
 endforeach()
 
-# Make sure pytest is found or produce a fatal error
+# Make sure pytest is found or produce a warning
 if(NOT PYBIND11_PYTEST_FOUND)
   execute_process(
     COMMAND ${PYTHON_EXECUTABLE} -c "import pytest; print(pytest.__version__)"
@@ -326,15 +354,16 @@
     OUTPUT_VARIABLE pytest_version
     ERROR_QUIET)
   if(pytest_not_found)
-    message(FATAL_ERROR "Running the tests requires pytest. Please install it manually"
-                        " (try: ${PYTHON_EXECUTABLE} -m pip install pytest)")
+    message(WARNING "Running the tests requires pytest. Please install it manually"
+                    " (try: ${PYTHON_EXECUTABLE} -m pip install pytest)")
   elseif(pytest_version VERSION_LESS 3.1)
-    message(FATAL_ERROR "Running the tests requires pytest >= 3.1. Found: ${pytest_version}"
-                        "Please update it (try: ${PYTHON_EXECUTABLE} -m pip install -U pytest)")
+    message(WARNING "Running the tests requires pytest >= 3.1. Found: ${pytest_version}"
+                    "Please update it (try: ${PYTHON_EXECUTABLE} -m pip install -U pytest)")
+  else()
+    set(PYBIND11_PYTEST_FOUND
+        TRUE
+        CACHE INTERNAL "")
   endif()
-  set(PYBIND11_PYTEST_FOUND
-      TRUE
-      CACHE INTERNAL "")
 endif()
 
 if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
diff --git a/tests/test_factory_constructors.cpp b/tests/test_factory_constructors.cpp
index 61cf33d..f614743 100644
--- a/tests/test_factory_constructors.cpp
+++ b/tests/test_factory_constructors.cpp
@@ -11,6 +11,7 @@
 #include "pybind11_tests.h"
 #include "constructor_stats.h"
 #include <cmath>
+#include <new>
 
 // Classes for testing python construction via C++ factory function:
 // Not publicly constructible, copyable, or movable:
diff --git a/tests/test_factory_constructors.py b/tests/test_factory_constructors.py
index 6c4bed1..b141c13 100644
--- a/tests/test_factory_constructors.py
+++ b/tests/test_factory_constructors.py
@@ -336,10 +336,10 @@
     return re.sub(r'\s+#.*', '', s)
 
 
-def test_reallocations(capture, msg):
+def test_reallocation_a(capture, msg):
     """When the constructor is overloaded, previous overloads can require a preallocated value.
     This test makes sure that such preallocated values only happen when they might be necessary,
-    and that they are deallocated properly"""
+    and that they are deallocated properly."""
 
     pytest.gc_collect()
 
@@ -353,6 +353,9 @@
         ~NoisyAlloc()
         noisy delete
     """
+
+
+def test_reallocation_b(capture, msg):
     with capture:
         create_and_destroy(1.5)
     assert msg(capture) == strip_comments("""
@@ -365,6 +368,8 @@
         noisy delete   # operator delete
     """)
 
+
+def test_reallocation_c(capture, msg):
     with capture:
         create_and_destroy(2, 3)
     assert msg(capture) == strip_comments("""
@@ -375,6 +380,8 @@
         noisy delete   # operator delete
     """)
 
+
+def test_reallocation_d(capture, msg):
     with capture:
         create_and_destroy(2.5, 3)
     assert msg(capture) == strip_comments("""
@@ -386,6 +393,8 @@
         noisy delete   # operator delete
     """)
 
+
+def test_reallocation_e(capture, msg):
     with capture:
         create_and_destroy(3.5, 4.5)
     assert msg(capture) == strip_comments("""
@@ -397,6 +406,8 @@
         noisy delete   # operator delete
     """)
 
+
+def test_reallocation_f(capture, msg):
     with capture:
         create_and_destroy(4, 0.5)
     assert msg(capture) == strip_comments("""
@@ -409,6 +420,8 @@
         noisy delete   # operator delete
     """)
 
+
+def test_reallocation_g(capture, msg):
     with capture:
         create_and_destroy(5, "hi")
     assert msg(capture) == strip_comments("""
diff --git a/tests/test_smart_ptr.py b/tests/test_smart_ptr.py
index c9267f6..0b1ca45 100644
--- a/tests/test_smart_ptr.py
+++ b/tests/test_smart_ptr.py
@@ -1,7 +1,8 @@
 # -*- coding: utf-8 -*-
 import pytest
-from pybind11_tests import smart_ptr as m
-from pybind11_tests import ConstructorStats
+
+m = pytest.importorskip("pybind11_tests.smart_ptr")
+from pybind11_tests import ConstructorStats  # noqa: E402
 
 
 def test_smart_ptr(capture):
diff --git a/tests/test_virtual_functions.cpp b/tests/test_virtual_functions.cpp
index 6dcf294..c5ee636 100644
--- a/tests/test_virtual_functions.cpp
+++ b/tests/test_virtual_functions.cpp
@@ -139,7 +139,7 @@
     std::string print_movable(int a, int b) { return get_movable(a, b).get_value(); }
 };
 class NCVirtTrampoline : public NCVirt {
-#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__)
+#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
     NonCopyable get_noncopyable(int a, int b) override {
         PYBIND11_OVERLOAD(NonCopyable, NCVirt, get_noncopyable, a, b);
     }
@@ -205,7 +205,7 @@
         .def(py::init<int, int>());
 
     // test_move_support
-#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__)
+#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
     py::class_<NCVirt, NCVirtTrampoline>(m, "NCVirt")
         .def(py::init<>())
         .def("get_noncopyable", &NCVirt::get_noncopyable)
diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py
index b7bd5ba..66a353a 100644
--- a/tests/test_virtual_functions.py
+++ b/tests/test_virtual_functions.py
@@ -3,8 +3,8 @@
 
 import env  # noqa: F401
 
-from pybind11_tests import virtual_functions as m
-from pybind11_tests import ConstructorStats
+m = pytest.importorskip("pybind11_tests.virtual_functions")
+from pybind11_tests import ConstructorStats  # noqa: E402
 
 
 def test_override(capture, msg):