diff --git a/extras/Build/CMake/JUCEUtils.cmake b/extras/Build/CMake/JUCEUtils.cmake index 9a481521be..f292d09ea3 100644 --- a/extras/Build/CMake/JUCEUtils.cmake +++ b/extras/Build/CMake/JUCEUtils.cmake @@ -385,11 +385,7 @@ function(_juce_get_platform_plugin_kinds out) endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL "iOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android") - list(APPEND result AAX Unity VST) - - if(NOT MINGW AND NOT MSYS) - list(APPEND result VST3) - endif() + list(APPEND result AAX Unity VST VST3) endif() set(${out} ${result} PARENT_SCOPE) diff --git a/modules/juce_audio_devices/midi_io/ump/juce_UMPDispatcher.h b/modules/juce_audio_devices/midi_io/ump/juce_UMPDispatcher.h index a365b4fdb1..64e2dd9cfa 100644 --- a/modules/juce_audio_devices/midi_io/ump/juce_UMPDispatcher.h +++ b/modules/juce_audio_devices/midi_io/ump/juce_UMPDispatcher.h @@ -108,7 +108,13 @@ public: { using CallbackPtr = decltype (std::addressof (callback)); - struct Callback + #if JUCE_MINGW + #define JUCE_MINGW_HIDDEN_VISIBILITY __attribute__ ((visibility ("hidden"))) + #else + #define JUCE_MINGW_HIDDEN_VISIBILITY + #endif + + struct JUCE_MINGW_HIDDEN_VISIBILITY Callback { Callback (BytestreamToUMPDispatcher& d, CallbackPtr c) : dispatch (d), callbackPtr (c) {} @@ -127,6 +133,8 @@ public: CallbackPtr callbackPtr = nullptr; }; + #undef JUCE_MINGW_HIDDEN_VISIBILITY + Callback inputCallback { *this, &callback }; concatenator.pushMidiData (begin, int (end - begin), timestamp, (void*) nullptr, inputCallback); } diff --git a/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp b/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp index 742b0209e6..2383ae9161 100644 --- a/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp +++ b/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp @@ -194,7 +194,9 @@ namespace static type##functionName ds##functionName = nullptr; #define DSOUND_FUNCTION_LOAD(functionName) \ - ds##functionName = (type##functionName) GetProcAddress (h, #functionName); \ + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-function-type") \ + ds##functionName = (type##functionName) GetProcAddress (h, #functionName); \ + JUCE_END_IGNORE_WARNINGS_GCC_LIKE \ jassert (ds##functionName != nullptr); typedef BOOL (CALLBACK *LPDSENUMCALLBACKW) (LPGUID, LPCWSTR, LPCWSTR, LPVOID); @@ -295,10 +297,10 @@ public: primaryDesc.dwSize = sizeof (DSBUFFERDESC); primaryDesc.dwFlags = 1 /* DSBCAPS_PRIMARYBUFFER */; primaryDesc.dwBufferBytes = 0; - primaryDesc.lpwfxFormat = 0; + primaryDesc.lpwfxFormat = nullptr; JUCE_DS_LOG ("co-op level set"); - hr = pDirectSound->CreateSoundBuffer (&primaryDesc, &pPrimaryBuffer, 0); + hr = pDirectSound->CreateSoundBuffer (&primaryDesc, &pPrimaryBuffer, nullptr); JUCE_DS_LOG_ERROR (hr); if (SUCCEEDED (hr)) @@ -324,7 +326,7 @@ public: secondaryDesc.dwBufferBytes = (DWORD) totalBytesPerBuffer; secondaryDesc.lpwfxFormat = &wfFormat; - hr = pDirectSound->CreateSoundBuffer (&secondaryDesc, &pOutputBuffer, 0); + hr = pDirectSound->CreateSoundBuffer (&secondaryDesc, &pOutputBuffer, nullptr); JUCE_DS_LOG_ERROR (hr); if (SUCCEEDED (hr)) @@ -335,14 +337,14 @@ public: unsigned char* pDSBuffData; hr = pOutputBuffer->Lock (0, (DWORD) totalBytesPerBuffer, - (LPVOID*) &pDSBuffData, &dwDataLen, 0, 0, 0); + (LPVOID*) &pDSBuffData, &dwDataLen, nullptr, nullptr, 0); JUCE_DS_LOG_ERROR (hr); if (SUCCEEDED (hr)) { zeromem (pDSBuffData, dwDataLen); - hr = pOutputBuffer->Unlock (pDSBuffData, dwDataLen, 0, 0); + hr = pOutputBuffer->Unlock (pDSBuffData, dwDataLen, nullptr, 0); if (SUCCEEDED (hr)) { @@ -379,7 +381,7 @@ public: bool service() { - if (pOutputBuffer == 0) + if (pOutputBuffer == nullptr) return true; DWORD playCursor, writeCursor; @@ -481,7 +483,7 @@ public: jassertfalse; } - writeOffset = (writeOffset + dwSize1 + dwSize2) % totalBytesPerBuffer; + writeOffset = (writeOffset + dwSize1 + dwSize2) % (DWORD) totalBytesPerBuffer; pOutputBuffer->Unlock (buf1, dwSize1, buf2, dwSize2); } @@ -605,7 +607,7 @@ public: captureDesc.lpwfxFormat = &wfFormat; JUCE_DS_LOG ("object created"); - hr = pDirectSoundCapture->CreateCaptureBuffer (&captureDesc, &pInputBuffer, 0); + hr = pDirectSoundCapture->CreateCaptureBuffer (&captureDesc, &pInputBuffer, nullptr); if (SUCCEEDED (hr)) { @@ -634,7 +636,7 @@ public: bool service() { - if (pInputBuffer == 0) + if (pInputBuffer == nullptr) return true; DWORD capturePos, readPos; @@ -692,7 +694,7 @@ public: jassertfalse; } - readOffset = (readOffset + dwsize1 + dwsize2) % totalBytesPerBuffer; + readOffset = (readOffset + dwsize1 + dwsize2) % (DWORD) totalBytesPerBuffer; pInputBuffer->Unlock (buf1, dwsize1, buf2, dwsize2); } @@ -932,8 +934,8 @@ public: break; } - const int latencyMs = (int) (bufferSizeSamples * 1000.0 / sampleRate); - const int maxTimeMS = jmax (5, 3 * latencyMs); + const auto latencyMs = (uint32) (bufferSizeSamples * 1000.0 / sampleRate); + const auto maxTimeMS = jmax ((uint32) 5, 3 * latencyMs); while (! threadShouldExit()) { @@ -1037,7 +1039,7 @@ struct DSoundDeviceList outputGuids.clear(); inputGuids.clear(); - if (dsDirectSoundEnumerateW != 0) + if (dsDirectSoundEnumerateW != nullptr) { dsDirectSoundEnumerateW (outputEnumProcW, this); dsDirectSoundCaptureEnumerateW (inputEnumProcW, this); diff --git a/modules/juce_audio_devices/native/juce_win32_Midi.cpp b/modules/juce_audio_devices/native/juce_win32_Midi.cpp index da55de31b0..0851c6ffb0 100644 --- a/modules/juce_audio_devices/native/juce_win32_Midi.cpp +++ b/modules/juce_audio_devices/native/juce_win32_Midi.cpp @@ -109,7 +109,7 @@ private: { stop(); - if (deviceHandle != 0) + if (deviceHandle != nullptr) { for (int count = 5; --count >= 0;) { @@ -183,7 +183,7 @@ private: void start() { - if (deviceHandle != 0 && ! isStarted.load()) + if (deviceHandle != nullptr && ! isStarted.load()) { activeMidiCollectors.addIfNotAlreadyThere (this); @@ -232,7 +232,7 @@ private: } MidiDeviceInfo deviceInfo; - HMIDIIN deviceHandle = 0; + HMIDIIN deviceHandle = nullptr; private: Win32MidiService& midiService; @@ -413,7 +413,7 @@ private: if (d.identifier == deviceIdentifier) { - deviceID = i; + deviceID = (UINT) i; deviceName = d.name; break; } @@ -526,7 +526,7 @@ private: if (d.identifier == deviceIdentifier) { - deviceID = i; + deviceID = (UINT) i; deviceName = d.name; break; } @@ -554,7 +554,7 @@ private: for (int i = 4; --i >= 0;) { - HMIDIOUT h = 0; + HMIDIOUT h = nullptr; auto res = midiOutOpen (&h, deviceID, 0, 0, CALLBACK_NULL); if (res == MMSYSERR_NOERROR) diff --git a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp index f6a1ea196a..c16838a6f6 100644 --- a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp +++ b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp @@ -632,10 +632,10 @@ private: &minPeriod, &maxPeriod))) { - minBufferSize = minPeriod; - defaultBufferSize = defaultPeriod; - lowLatencyMaxBufferSize = maxPeriod; - lowLatencyBufferSizeMultiple = fundamentalPeriod; + minBufferSize = (int) minPeriod; + defaultBufferSize = (int) defaultPeriod; + lowLatencyMaxBufferSize = (int) maxPeriod; + lowLatencyBufferSizeMultiple = (int) fundamentalPeriod; } } } @@ -672,7 +672,7 @@ private: : &nearestFormat))) { if (nearestFormat != nullptr) - rate = nearestFormat->nSamplesPerSec; + rate = (int) nearestFormat->nSamplesPerSec; if (! rates.contains (rate)) rates.addUsingDefaultSort (rate); @@ -780,7 +780,7 @@ private: { if (auto audioClient3 = client.getInterface()) return check (audioClient3->InitializeSharedAudioStream (getStreamFlags(), - bufferSizeSamples, + (UINT32) bufferSizeSamples, (WAVEFORMATEX*) &format, nullptr)); @@ -822,7 +822,7 @@ private: client = nullptr; client = createClient(); - defaultPeriod = samplesToRefTime (numFrames, format.Format.nSamplesPerSec); + defaultPeriod = samplesToRefTime ((int) numFrames, format.Format.nSamplesPerSec); } return false; @@ -903,9 +903,9 @@ public: bool start (int userBufferSize) { - reservoirSize = actualBufferSize + userBufferSize; + reservoirSize = (int) (actualBufferSize + (UINT32) userBufferSize); reservoirMask = nextPowerOfTwo (reservoirSize) - 1; - reservoir.setSize ((reservoirMask + 1) * bytesPerFrame, true); + reservoir.setSize ((size_t) ((reservoirMask + 1) * bytesPerFrame), true); reservoirReadPos = 0; reservoirWritePos = 0; xruns = 0; @@ -957,9 +957,9 @@ public: void* reservoirPtr = addBytesToPointer (reservoir.getData(), localWrite * bytesPerFrame); if ((flags & AUDCLNT_BUFFERFLAGS_SILENT) != 0) - zeromem (reservoirPtr, samplesToDoBytes); + zeromem (reservoirPtr, (size_t) samplesToDoBytes); else - memcpy (reservoirPtr, inputData, samplesToDoBytes); + memcpy (reservoirPtr, inputData, (size_t) samplesToDoBytes); reservoirWritePos += samplesToDo; inputData += samplesToDoBytes; @@ -983,7 +983,7 @@ public: if (offset > 0) { for (int i = 0; i < numDestBuffers; ++i) - zeromem (destBuffers[i], offset * sizeof (float)); + zeromem (destBuffers[i], (size_t) offset * sizeof (float)); bufferSize -= offset; reservoirReadPos -= offset / 2; @@ -1066,8 +1066,8 @@ public: auto samplesToDo = getNumSamplesAvailableToCopy(); uint8* outputData; - if (check (renderClient->GetBuffer (samplesToDo, &outputData))) - renderClient->ReleaseBuffer (samplesToDo, AUDCLNT_BUFFERFLAGS_SILENT); + if (check (renderClient->GetBuffer ((UINT32) samplesToDo, &outputData))) + renderClient->ReleaseBuffer ((UINT32) samplesToDo, AUDCLNT_BUFFERFLAGS_SILENT); if (! check (client->Start())) return false; @@ -1087,10 +1087,10 @@ public: UINT32 padding = 0; if (check (client->GetCurrentPadding (&padding))) - return actualBufferSize - (int) padding; + return (int) actualBufferSize - (int) padding; } - return actualBufferSize; + return (int) actualBufferSize; } void copyBuffers (const float** srcBuffers, int numSrcBuffers, int bufferSize, @@ -1334,8 +1334,8 @@ public: return lastError; } - currentBufferSizeSamples = outputDevice != nullptr ? outputDevice->actualBufferSize - : inputDevice->actualBufferSize; + currentBufferSizeSamples = (int) (outputDevice != nullptr ? outputDevice->actualBufferSize + : inputDevice->actualBufferSize); } if (inputDevice != nullptr) ResetEvent (inputDevice->clientEvent); @@ -1435,7 +1435,7 @@ public: JUCE_LOAD_WINAPI_FUNCTION (dll, AvSetMmThreadCharacteristicsW, avSetMmThreadCharacteristics, HANDLE, (LPCWSTR, LPDWORD)) JUCE_LOAD_WINAPI_FUNCTION (dll, AvSetMmThreadPriority, avSetMmThreadPriority, HANDLE, (HANDLE, AVRT_PRIORITY)) - if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) + if (avSetMmThreadCharacteristics != nullptr && avSetMmThreadPriority != nullptr) { DWORD dummy = 0; diff --git a/modules/juce_audio_formats/juce_audio_formats.h b/modules/juce_audio_formats/juce_audio_formats.h index a185760591..904c1f98ad 100644 --- a/modules/juce_audio_formats/juce_audio_formats.h +++ b/modules/juce_audio_formats/juce_audio_formats.h @@ -104,7 +104,7 @@ #define JUCE_USE_WINDOWS_MEDIA_FORMAT 1 #endif -#if ! JUCE_WINDOWS +#if ! JUCE_WINDOWS || JUCE_MINGW #undef JUCE_USE_WINDOWS_MEDIA_FORMAT #define JUCE_USE_WINDOWS_MEDIA_FORMAT 0 #endif diff --git a/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h b/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h index f62e860e0d..58322b9253 100644 --- a/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h +++ b/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h @@ -31,79 +31,76 @@ namespace juce // This function is in juce_win32_Windowing.cpp extern bool offerKeyMessageToJUCEWindow (MSG&); -namespace +static HHOOK mouseWheelHook = nullptr, keyboardHook = nullptr; +static int numHookUsers = 0; + +struct WindowsHooks { - static HHOOK mouseWheelHook = 0, keyboardHook = 0; - static int numHookUsers = 0; - - struct WindowsHooks + WindowsHooks() { - WindowsHooks() + if (numHookUsers++ == 0) { - if (numHookUsers++ == 0) - { - mouseWheelHook = SetWindowsHookEx (WH_MOUSE, mouseWheelHookCallback, - (HINSTANCE) juce::Process::getCurrentModuleInstanceHandle(), - GetCurrentThreadId()); + mouseWheelHook = SetWindowsHookEx (WH_MOUSE, mouseWheelHookCallback, + (HINSTANCE) juce::Process::getCurrentModuleInstanceHandle(), + GetCurrentThreadId()); - keyboardHook = SetWindowsHookEx (WH_GETMESSAGE, keyboardHookCallback, - (HINSTANCE) juce::Process::getCurrentModuleInstanceHandle(), - GetCurrentThreadId()); - } + keyboardHook = SetWindowsHookEx (WH_GETMESSAGE, keyboardHookCallback, + (HINSTANCE) juce::Process::getCurrentModuleInstanceHandle(), + GetCurrentThreadId()); } + } - ~WindowsHooks() + ~WindowsHooks() + { + if (--numHookUsers == 0) { - if (--numHookUsers == 0) + if (mouseWheelHook != nullptr) { - if (mouseWheelHook != 0) - { - UnhookWindowsHookEx (mouseWheelHook); - mouseWheelHook = 0; - } - - if (keyboardHook != 0) - { - UnhookWindowsHookEx (keyboardHook); - keyboardHook = 0; - } - } - } - - static LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam) - { - if (nCode >= 0 && wParam == WM_MOUSEWHEEL) - { - // using a local copy of this struct to support old mingw libraries - struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; }; - - auto& hs = *(MOUSEHOOKSTRUCTEX_*) lParam; - - if (auto* comp = Desktop::getInstance().findComponentAt ({ hs.pt.x, hs.pt.y })) - if (comp->getWindowHandle() != 0) - return PostMessage ((HWND) comp->getWindowHandle(), WM_MOUSEWHEEL, - hs.mouseData & 0xffff0000, (hs.pt.x & 0xffff) | (hs.pt.y << 16)); + UnhookWindowsHookEx (mouseWheelHook); + mouseWheelHook = nullptr; } - return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam); - } - - static LRESULT CALLBACK keyboardHookCallback (int nCode, WPARAM wParam, LPARAM lParam) - { - MSG& msg = *(MSG*) lParam; - - if (nCode == HC_ACTION && wParam == PM_REMOVE - && offerKeyMessageToJUCEWindow (msg)) + if (keyboardHook != nullptr) { - zerostruct (msg); - msg.message = WM_USER; - return 1; + UnhookWindowsHookEx (keyboardHook); + keyboardHook = nullptr; } - - return CallNextHookEx (keyboardHook, nCode, wParam, lParam); } - }; -} + } + + static LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam) + { + if (nCode >= 0 && wParam == WM_MOUSEWHEEL) + { + // using a local copy of this struct to support old mingw libraries + struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; }; + + auto& hs = *(MOUSEHOOKSTRUCTEX_*) lParam; + + if (auto* comp = Desktop::getInstance().findComponentAt ({ hs.pt.x, hs.pt.y })) + if (comp->getWindowHandle() != nullptr) + return PostMessage ((HWND) comp->getWindowHandle(), WM_MOUSEWHEEL, + hs.mouseData & 0xffff0000, (hs.pt.x & 0xffff) | (hs.pt.y << 16)); + } + + return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam); + } + + static LRESULT CALLBACK keyboardHookCallback (int nCode, WPARAM wParam, LPARAM lParam) + { + MSG& msg = *(MSG*) lParam; + + if (nCode == HC_ACTION && wParam == PM_REMOVE + && offerKeyMessageToJUCEWindow (msg)) + { + zerostruct (msg); + msg.message = WM_USER; + return 1; + } + + return CallNextHookEx (keyboardHook, nCode, wParam, lParam); + } +}; } // namespace juce diff --git a/modules/juce_audio_processors/format_types/juce_VST3Headers.h b/modules/juce_audio_processors/format_types/juce_VST3Headers.h index 8fb39ed49e..9c5dd4f985 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3Headers.h +++ b/modules/juce_audio_processors/format_types/juce_VST3Headers.h @@ -61,7 +61,9 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnon-virtual-dtor", "-Wextra", "-Wclass-memaccess", "-Wmissing-prototypes", - "-Wtype-limits") + "-Wtype-limits", + "-Wcpp", + "-W#warnings") #undef DEVELOPMENT #define DEVELOPMENT 0 // This avoids a Clang warning in Steinberg code about unused values @@ -112,6 +114,14 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnon-virtual-dtor", #include #include + // The following shouldn't leak from fstring.cpp + #undef stricmp + #undef strnicmp + #undef snprintf + #undef vsnprintf + #undef snwprintf + #undef vsnwprintf + #if VST_VERSION >= 0x030608 #include #include diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 3ea2ac0350..e9e792b508 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -28,6 +28,8 @@ #include "juce_VST3Headers.h" #include "juce_VST3Common.h" +#include + namespace juce { diff --git a/modules/juce_core/native/juce_win32_SystemStats.cpp b/modules/juce_core/native/juce_win32_SystemStats.cpp index 0cec079a56..79f2f687e0 100644 --- a/modules/juce_core/native/juce_win32_SystemStats.cpp +++ b/modules/juce_core/native/juce_win32_SystemStats.cpp @@ -291,8 +291,11 @@ String SystemStats::getOperatingSystemName() case MacOSX_10_12: JUCE_FALLTHROUGH case MacOSX_10_13: JUCE_FALLTHROUGH case MacOSX_10_14: JUCE_FALLTHROUGH + case MacOSX_10_15: JUCE_FALLTHROUGH + case MacOS_11: JUCE_FALLTHROUGH case UnknownOS: JUCE_FALLTHROUGH + case WASM: JUCE_FALLTHROUGH default: jassertfalse; break; // !! new type of OS? } diff --git a/modules/juce_core/system/juce_CompilerWarnings.h b/modules/juce_core/system/juce_CompilerWarnings.h index 07cc1c56e9..462e8bafaa 100644 --- a/modules/juce_core/system/juce_CompilerWarnings.h +++ b/modules/juce_core/system/juce_CompilerWarnings.h @@ -127,7 +127,7 @@ /** Quote the argument, turning it into a string. */ #define JUCE_TO_STRING(x) #x -#if JUCE_CLANG || JUCE_GCC +#if JUCE_CLANG || JUCE_GCC || JUCE_MINGW #define JUCE_IGNORE_GCC_IMPL_(compiler, warning) #define JUCE_IGNORE_GCC_IMPL_0(compiler, warning) #define JUCE_IGNORE_GCC_IMPL_1(compiler, warning) \ diff --git a/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp b/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp index 2c7b7bed22..5f799e571c 100644 --- a/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp +++ b/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp @@ -275,7 +275,7 @@ private: { LPTSTR messageBuffer = nullptr; auto size = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, statusCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + nullptr, (DWORD) statusCode, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &messageBuffer, 0, nullptr); String message (messageBuffer, size); @@ -306,6 +306,9 @@ private: void componentPeerChanged() override {} void componentVisibilityChanged() override { owner.visibilityChanged(); } + using ComponentMovementWatcher::componentVisibilityChanged; + using ComponentMovementWatcher::componentMovedOrResized; + private: WebBrowserComponent& owner; @@ -872,7 +875,7 @@ void WebBrowserComponent::checkWindowAssociation() // page to avoid this.. blankPageShown = true; - browser->getInternalWebView().goToURL ("about:blank", 0, 0); + browser->getInternalWebView().goToURL ("about:blank", nullptr, nullptr); } } }