SDL: Fix C89 declaration for macOS modules.

From 6c536afdb7bdc9cece4152c7e1f9a18306976b46 Mon Sep 17 00:00:00 2001
From: Pierre Wendling <[EMAIL REDACTED]>
Date: Mon, 27 Jun 2022 15:43:17 -0400
Subject: [PATCH] Fix C89 declaration for macOS modules.

Since Clang 14, `-Wdeclaration-after-statement` is enforced on every
standard.
---
 src/audio/coreaudio/SDL_coreaudio.m      |  15 +-
 src/file/cocoa/SDL_rwopsbundlesupport.m  |  12 +-
 src/filesystem/cocoa/SDL_sysfilesystem.m |  11 +-
 src/hidapi/mac/hid.c                     |  48 ++---
 src/joystick/darwin/SDL_iokitjoystick.c  |   3 +-
 src/joystick/iphoneos/SDL_mfijoystick.m  |  31 +--
 src/render/metal/SDL_render_metal.m      | 238 +++++++++++++----------
 src/timer/unix/SDL_systimer.c            |   3 +-
 src/video/cocoa/SDL_cocoaevents.m        |   3 +-
 src/video/cocoa/SDL_cocoakeyboard.m      |  11 +-
 src/video/cocoa/SDL_cocoamessagebox.m    |  13 +-
 src/video/cocoa/SDL_cocoamodes.m         |  54 ++---
 src/video/cocoa/SDL_cocoamouse.m         |  74 ++++---
 src/video/cocoa/SDL_cocoaopengl.m        |   3 +-
 src/video/cocoa/SDL_cocoaopengles.m      |   3 +-
 src/video/cocoa/SDL_cocoashape.m         |   9 +-
 src/video/cocoa/SDL_cocoawindow.m        | 116 ++++++-----
 17 files changed, 376 insertions(+), 271 deletions(-)

diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m
index 5c267fb3642..6717feaad99 100644
--- a/src/audio/coreaudio/SDL_coreaudio.m
+++ b/src/audio/coreaudio/SDL_coreaudio.m
@@ -824,7 +824,10 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
     const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
     const int iscapture = this->iscapture;
     OSStatus result;
-    int i;
+    int i, numAudioBuffers = 2;
+    AudioChannelLayout layout;
+    double MINIMUM_AUDIO_BUFFER_TIME_MS;
+    const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;;
 
     SDL_assert(CFRunLoopGetCurrent() != NULL);
 
@@ -856,7 +859,6 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
     SDL_CalculateAudioSpec(&this->spec);
 
     /* Set the channel layout for the audio queue */
-    AudioChannelLayout layout;
     SDL_zero(layout);
     switch (this->spec.channels) {
     case 1:
@@ -901,15 +903,13 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
     }
 
     /* Make sure we can feed the device a minimum amount of time */
-    double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
+    MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
 #if defined(__IPHONEOS__)
     if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
         /* Older iOS hardware, use 40 ms as a minimum time */
         MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0;
     }
 #endif
-    const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;
-    int numAudioBuffers = 2;
     if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) {  /* use more buffers if we have a VERY small sample set. */
         numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
     }
@@ -946,6 +946,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
 audioqueue_thread(void *arg)
 {
     SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
+    int rc;
 
     #if MACOSX_COREAUDIO
     const AudioObjectPropertyAddress default_device_address = {
@@ -960,7 +961,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
     }
     #endif
 
-    const int rc = prepare_audioqueue(this);
+    rc = prepare_audioqueue(this);
     if (!rc) {
         this->hidden->thread_error = SDL_strdup(SDL_GetError());
         SDL_SemPost(this->hidden->ready_semaphore);
@@ -977,6 +978,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
 
         #if MACOSX_COREAUDIO
         if ((this->handle == NULL) && SDL_AtomicGet(&this->hidden->device_change_flag)) {
+            const AudioDeviceID prev_devid = this->hidden->deviceID;
             SDL_AtomicSet(&this->hidden->device_change_flag, 0);
 
             #if DEBUG_COREAUDIO
@@ -986,7 +988,6 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
             /* if any of this fails, there's not much to do but wait to see if the user gives up
                and quits (flagging the audioqueue for shutdown), or toggles to some other system
                output device (in which case we'll try again). */
-            const AudioDeviceID prev_devid = this->hidden->deviceID;
             if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
                 AudioQueueStop(this->hidden->audioQueue, 1);
                 if (assign_device_to_audioqueue(this)) {
diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.m b/src/file/cocoa/SDL_rwopsbundlesupport.m
index 478522cea5e..55e104a950e 100644
--- a/src/file/cocoa/SDL_rwopsbundlesupport.m
+++ b/src/file/cocoa/SDL_rwopsbundlesupport.m
@@ -36,18 +36,22 @@
 { @autoreleasepool
 {
     FILE* fp = NULL;
+    NSFileManager* file_manager;
+    NSString* resource_path;
+    NSString* ns_string_file_component;
+    NSString* full_path_with_file_to_try;
 
     /* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
     if(strcmp("r", mode) && strcmp("rb", mode)) {
         return fopen(file, mode);
     }
 
-    NSFileManager* file_manager = [NSFileManager defaultManager];
-    NSString* resource_path = [[NSBundle mainBundle] resourcePath];
+    file_manager = [NSFileManager defaultManager];
+    resource_path = [[NSBundle mainBundle] resourcePath];
 
-    NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
+    ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
 
-    NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
+    full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
     if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
         fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
     } else {
diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m
index b20e8fc5bf5..ba2e332799c 100644
--- a/src/filesystem/cocoa/SDL_sysfilesystem.m
+++ b/src/filesystem/cocoa/SDL_sysfilesystem.m
@@ -71,6 +71,10 @@
 SDL_GetPrefPath(const char *org, const char *app)
 { @autoreleasepool
 {
+    char *retval = NULL;
+    static SDL_bool shown = SDL_FALSE;
+    NSArray *array;
+
     if (!app) {
         SDL_InvalidParamError("app");
         return NULL;
@@ -79,9 +83,8 @@
         org = "";
     }
 
-    char *retval = NULL;
 #if !TARGET_OS_TV
-    NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+    array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
 #else
     /* tvOS does not have persistent local storage!
      * The only place on-device where we can store data is
@@ -91,15 +94,13 @@
      * between sessions. If you want your app's save data to
      * actually stick around, you'll need to use iCloud storage.
      */
-
-    static SDL_bool shown = SDL_FALSE;
     if (!shown)
     {
         shown = SDL_TRUE;
         SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n");
     }
 
-    NSArray *array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+    array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
 #endif /* !TARGET_OS_TV */
 
     if ([array count] > 0) {  /* we only want the first item in the list. */
diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c
index ec7ffaf1694..cfad07c25c1 100644
--- a/src/hidapi/mac/hid.c
+++ b/src/hidapi/mac/hid.c
@@ -156,11 +156,12 @@ static hid_device *new_hid_device(void)
 
 static void free_hid_device(hid_device *dev)
 {
+	struct input_report *rpt;
 	if (!dev)
 		return;
 	
 	/* Delete any input reports still left over. */
-	struct input_report *rpt = dev->input_reports;
+	rpt = dev->input_reports;
 	while (rpt) {
 		struct input_report *next = rpt->next;
 		free(rpt->data);
@@ -260,14 +261,12 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
 	buf[0] = 0;
 	
 	if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
-		len --;
-		
-		CFIndex str_len = CFStringGetLength(str);
+		CFIndex used_buf_len, chars_copied;
 		CFRange range;
+		CFIndex str_len = CFStringGetLength(str);
+		len --;
 		range.location = 0;
 		range.length = (str_len > len)? len: str_len;
-		CFIndex used_buf_len;
-		CFIndex chars_copied;
 		chars_copied = CFStringGetBytes(str,
 										range,
 										kCFStringEncodingUTF32LE,
@@ -299,14 +298,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
 	buf[0] = 0;
 	
 	if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
-		len--;
-		
-		CFIndex str_len = CFStringGetLength(str);
+		CFIndex used_buf_len, chars_copied;
 		CFRange range;
+		CFIndex str_len = CFStringGetLength(str);
+		len--;
 		range.location = 0;
 		range.length = (str_len > len)? len: str_len;
-		CFIndex used_buf_len;
-		CFIndex chars_copied;
 		chars_copied = CFStringGetBytes(str,
 										range,
 										kCFStringEncodingUTF8,
@@ -517,6 +514,8 @@ struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
 	struct hid_device_info *root = NULL; // return object
 	struct hid_device_info *cur_dev = NULL;
 	CFIndex num_devices;
+	CFSetRef device_set;
+	IOHIDDeviceRef *device_array;
 	int i;
 	
 	/* Set up the HID Manager if it hasn't been done */
@@ -527,7 +526,7 @@ struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
 	process_pending_events();
 	
 	/* Get a list of the Devices */
-	CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
+	device_set = IOHIDManagerCopyDevices(hid_mgr);
 	if (!device_set)
 		return NULL;
 
@@ -537,7 +536,7 @@ struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
 		CFRelease(device_set);
 		return NULL;
 	}
-	IOHIDDeviceRef *device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
+	device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
 	CFSetGetValues(device_set, (const void **) device_array);
 	
 	/* Iterate over each device, making an entry for it. */	
@@ -733,13 +732,14 @@ static void perform_signal_callback(void *context)
 static void *read_thread(void *param)
 {
 	hid_device *dev = (hid_device *)param;
+	CFRunLoopSourceContext ctx;
+    SInt32 code;
 	
 	/* Move the device's run loop to this thread. */
 	IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
 	
 	/* Create the RunLoopSource which is used to signal the
 	 event loop to stop when hid_close() is called. */
-	CFRunLoopSourceContext ctx;
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.version = 0;
 	ctx.info = dev;
@@ -756,7 +756,6 @@ static void *read_thread(void *param)
 	
 	/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
 	 reports into the hid_report_callback(). */
-	SInt32 code;
 	while (!dev->shutdown_thread && !dev->disconnected) {
 		code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
 		/* Return if the device has been disconnected */
@@ -796,10 +795,12 @@ static void *read_thread(void *param)
 
 hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
 {
-  	int i;
+	int i;
 	hid_device *dev = NULL;
 	CFIndex num_devices;
-	
+	CFSetRef device_set;
+	IOHIDDeviceRef *device_array;
+
 	dev = new_hid_device();
 	
 	/* Set up the HID Manager if it hasn't been done */
@@ -809,10 +810,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
 	/* give the IOHIDManager a chance to update itself */
 	process_pending_events();
 	
-	CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
+	device_set = IOHIDManagerCopyDevices(hid_mgr);
 	
 	num_devices = CFSetGetCount(device_set);
-	IOHIDDeviceRef *device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
+	device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
 	CFSetGetValues(device_set, (const void **) device_array);	
 	for (i = 0; i < num_devices; i++) {
 		char cbuf[BUF_LEN];
@@ -824,6 +825,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
 			IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
 			if (ret == kIOReturnSuccess) {
 				char str[32];
+				struct hid_device_list_node *node;
 				
 				free(device_array);
 				CFRelease(device_set);
@@ -845,7 +847,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
 													   os_dev, dev->input_report_buf, dev->max_input_report_len,
 													   &hid_report_callback, dev);
 
-				struct hid_device_list_node *node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
+				node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
 				node->dev = dev;
 				node->next = device_list;
 				device_list = node;
@@ -1083,13 +1085,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
 {
 	CFIndex len = length;
 	IOReturn res;
-	
+	int skipped_report_id = 0, report_number;
+
 	/* Return if the device has been unplugged. */
 	if (dev->disconnected)
 		return -1;
 	
-	int skipped_report_id = 0;
-	int report_number = data[0];
+	report_number = data[0];
 	if (report_number == 0x0) {
 		/* Offset the return buffer by 1, so that the report ID
 		 will remain in byte 0. */
diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c
index 91072c52e0e..6b6945ea0d6 100644
--- a/src/joystick/darwin/SDL_iokitjoystick.c
+++ b/src/joystick/darwin/SDL_iokitjoystick.c
@@ -985,7 +985,7 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
     recDevice *device = joystick->hwdata;
     recElement *element;
     SInt32 value, range;
-    int i;
+    int i, goodRead = SDL_FALSE;
 
     if (!device) {
         return;
@@ -1001,7 +1001,6 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
     element = device->firstAxis;
     i = 0;
 
-    int goodRead = SDL_FALSE;
     while (element) {
         goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
         if (goodRead) {
diff --git a/src/joystick/iphoneos/SDL_mfijoystick.m b/src/joystick/iphoneos/SDL_mfijoystick.m
index c55cf78873e..7c701319335 100644
--- a/src/joystick/iphoneos/SDL_mfijoystick.m
+++ b/src/joystick/iphoneos/SDL_mfijoystick.m
@@ -180,16 +180,16 @@ @interface GCMicroGamepad (SDL)
 static BOOL
 IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
 {
-    if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
-        GCController.shouldMonitorBackgroundEvents = YES;
-    }
-
     Uint16 *guid16 = (Uint16 *)device->guid.data;
     Uint16 vendor = 0;
     Uint16 product = 0;
     Uint8 subtype = 0;
-
     const char *name = NULL;
+
+    if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
+        GCController.shouldMonitorBackgroundEvents = YES;
+    }
+
     /* Explicitly retain the controller because SDL_JoystickDeviceItem is a
      * struct, and ARC doesn't work with structs. */
     device->controller = (__bridge GCController *) CFBridgingRetain(controller);
@@ -213,6 +213,7 @@ @interface GCMicroGamepad (SDL)
         BOOL is_MFi = (!is_xbox && !is_ps4 && !is_ps5);
 #endif
         int nbuttons = 0;
+        BOOL has_direct_menu;
 
 #ifdef SDL_JOYSTICK_HIDAPI
         if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_CONTROLLER_TYPE_XBOXONE)) ||
@@ -251,7 +252,7 @@ @interface GCMicroGamepad (SDL)
             device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_GUIDE);
             ++nbuttons;
         }
-        BOOL has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
+        has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
 #if TARGET_OS_TV
         /* On tvOS MFi controller menu button brings you to the home screen */
         if (is_MFi) {
@@ -575,6 +576,7 @@ static int is_macos11(void)
 #endif
 
     @autoreleasepool {
+        NSNotificationCenter *center;
 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
         if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
             /* Default behavior, accelerometer as joystick */
@@ -599,7 +601,7 @@ static int is_macos11(void)
                             SDL_AppleTVRemoteRotationHintChanged, NULL);
 #endif /* TARGET_OS_TV */
 
-        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+        center = [NSNotificationCenter defaultCenter];
 
         connectObserver = [center addObserverForName:GCControllerDidConnectNotification
                                               object:nil
@@ -907,9 +909,8 @@ static int is_macos11(void)
 
 #ifdef ENABLE_PHYSICAL_INPUT_PROFILE
             if (joystick->hwdata->has_dualshock_touchpad) {
-                buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
-
                 GCControllerDirectionPad *dpad;
+                buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
 
                 dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne];
                 if (dpad.xAxis.value || dpad.yAxis.value) {
@@ -1129,6 +1130,7 @@ -(int)setIntensity:(float)intensity
     @autoreleasepool {
         if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
             NSError *error = nil;
+            CHHapticDynamicParameter *param;
 
             if (self.engine == nil) {
                 return SDL_SetError("Haptics engine was stopped");
@@ -1143,8 +1145,8 @@ -(int)setIntensity:(float)intensity
             }
 
             if (self.player == nil) {
-                CHHapticEventParameter *param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
-                CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
+                CHHapticEventParameter *event_param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
+                CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:event_param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
                 CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error];
                 if (error != nil) {
                     return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]);
@@ -1157,7 +1159,7 @@ -(int)setIntensity:(float)intensity
                 self.active = false;
             }
 
-            CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
+            param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
             [self.player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
             if (error != nil) {
                 return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]);
@@ -1176,8 +1178,10 @@ -(int)setIntensity:(float)intensity
 -(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0))
 {
     @autoreleasepool {
-        self = [super init];
         NSError *error;
+        __weak __typeof(self) weakSelf;
+        self = [super init];
+        weakSelf = self;
 
         self.engine = [controller.haptics createEngineWithLocality:locality];
         if (self.engine == nil) {
@@ -1191,7 +1195,6 @@ -(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)l
             return nil;
         }
 
-        __weak __typeof(self) weakSelf = self;
         self.engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
             SDL_RumbleMotor *_this = weakSelf;
             if (_this == nil) {
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 6ade20c12cc..b17bb4548ef 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -240,16 +240,24 @@ @implementation METAL_TextureData
 MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
                   NSString *blendlabel, SDL_BlendMode blendmode)
 {
+    MTLRenderPipelineDescriptor *mtlpipedesc;
+    MTLVertexDescriptor *vertdesc;
+    MTLRenderPipelineColorAttachmentDescriptor *rtdesc;
+    NSError *err = nil;
+    id<MTLRenderPipelineState> state;
+    METAL_PipelineState pipeline;
+    METAL_PipelineState *states;
+
     id<MTLFunction> mtlvertfn = [data.mtllibrary newFunctionWithName:GetVertexFunctionName(cache->vertexFunction)];
     id<MTLFunction> mtlfragfn = [data.mtllibrary newFunctionWithName:GetFragmentFunctionName(cache->fragmentFunction)];
     SDL_assert(mtlvertfn != nil);
     SDL_assert(mtlfragfn != nil);
 
-    MTLRenderPipelineDescriptor *mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
+    mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
     mtlpipedesc.vertexFunction = mtlvertfn;
     mtlpipedesc.fragmentFunction = mtlfragfn;
 
-    MTLVertexDescriptor *vertdesc = [MTLVertexDescriptor vertexDescriptor];
+    vertdesc = [MTLVertexDescriptor vertexDescriptor];
 
     switch (cache->vertexFunction) {
         case SDL_METAL_VERTEX_SOLID:
@@ -287,7 +295,7 @@ @implementation METAL_TextureData
 
     mtlpipedesc.vertexDescriptor = vertdesc;
 
-    MTLRenderPipelineColorAttachmentDescriptor *rtdesc = mtlpipedesc.colorAttachments[0];
+    rtdesc = mtlpipedesc.colorAttachments[0];
     rtdesc.pixelFormat = cache->renderTargetFormat;
 
     if (blendmode != SDL_BLENDMODE_NONE) {
@@ -304,15 +312,13 @@ @implementation METAL_TextureData
 
     mtlpipedesc.label = [@(cache->label) stringByAppendingString:blendlabel];
 
-    NSError *err = nil;
-    id<MTLRenderPipelineState> state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
+    state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
     SDL_assert(err == nil);
 
-    METAL_PipelineState pipeline;
     pipeline.blendMode = blendmode;
     pipeline.pipe = (void *)CFBridgingRetain(state);
 
-    METAL_PipelineState *states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
+    states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
 
     if (states) {
         states[cache->count++] = pipeline;
@@ -542,6 +548,10 @@ @implementation METAL_TextureData
 { @autoreleasepool {
     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
     MTLPixelFormat pixfmt;
+    MTLTextureDescriptor *mtltexdesc;
+    id<MTLTexture> mtltexture, mtltexture_uv;
+    BOOL yuv, nv12;
+    METAL_TextureData *texturedata;
 
     switch (texture->format) {
         case SDL_PIXELFORMAT_ABGR8888:
@@ -560,7 +570,7 @@ @implementation METAL_TextureData
             return SDL_SetError("Texture format %s not supported by Metal", SDL_GetPixelFormatName(texture->format));
     }
 
-    MTLTextureDescriptor *mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
+    mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
                                             width:(NSUInteger)texture->w height:(NSUInteger)texture->h mipmapped:NO];
 
     /* Not available in iOS 8. */
@@ -572,15 +582,15 @@ @implementation METAL_TextureData
         }
     }
 
-    id<MTLTexture> mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
+    mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
     if (mtltexture == nil) {
         return SDL_SetError("Texture allocation failed");
     }
 
-    id<MTLTexture> mtltexture_uv = nil;
+    mtltexture_uv = nil;
 #if SDL_HAVE_YUV
-    BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
-    BOOL nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
+    yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
+    nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
 
     if (yuv) {
         mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
@@ -601,7 +611,7 @@ @implementation METAL_TextureData
         }
     }
 #endif /* SDL_HAVE_YUV */
-    METAL_TextureData *texturedata = [[METAL_TextureData alloc] init];
+    texturedata = [[METAL_TextureData alloc] init];
     if (texture->scaleMode == SDL_ScaleModeNearest) {
         texturedata.mtlsampler = data.mtlsamplernearest;
     } else {
@@ -672,6 +682,8 @@ @implementation METAL_TextureData
     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
     SDL_Rect stagingrect = {0, 0, rect.w, rect.h};
     MTLTextureDescriptor *desc;
+    id<MTLTexture> stagingtex;
+    id<MTLBlitCommandEncoder> blitcmd;
 
     /* If the texture is managed or shared and this is the first upload, we can
      * use replaceRegion to upload to it directly. Otherwise we upload the data
@@ -693,7 +705,7 @@ @implementation METAL_TextureData
     /* TODO: We could have a pool of textures or a MTLHeap we allocate from,
      * and release a staging texture back to the pool in the command buffer's
      * completion handler. */
-    id<MTLTexture> stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
+    stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
     if (stagingtex == nil) {
         return SDL_OutOfMemory();
     }
@@ -709,7 +721,7 @@ @implementation METAL_TextureData
         data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
     }
 
-    id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
+    blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
 
     [blitcmd copyFromTexture:stagingtex
                  sourceSlice:0
@@ -877,6 +889,7 @@ @implementation METAL_TextureData
 { @autoreleasepool {
     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
     METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
+    id<MTLBlitCommandEncoder> blitcmd;
     SDL_Rect rect = texturedata.lockedrect;
     int pitch = SDL_BYTESPERPIXEL(texture->format) * rect.w;
     SDL_Rect UVrect = {rect.x / 2, rect.y / 2, (rect.w + 1) / 2, (rect.h + 1) / 2};
@@ -894,7 +907,7 @@ @implementation METAL_TextureData
         data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
     }
 
-    id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
+    blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
 
     [blitcmd copyFromBuffer:texturedata.lockedbuffer
                sourceOffset:0
@@ -1068,11 +1081,13 @@ @implementation METAL_TextureData
         cmd->data.draw.b,
         cmd->data.draw.a
     };
+    size_t vertlen;
+    float *verts;
 
     SDL_assert(count >= 2);  /* should have been checked at the higher level. */
 
-    const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
-    float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
+    vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
+    verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
     if (!verts) {
         return -1;
     }
@@ -1095,15 +1110,17 @@ @implementation METAL_TextureData
     points -= 2;  /* update the last line. */
     verts -= 2 + 1;
 
-    const float xstart = points[0].x;
-    const float ystart = points[0].y;
-    const float xend = points[1].x;
-    const float yend = points[1].y;
-
-    if (ystart == yend) {  /* horizontal line */
-        verts[0] += (xend > xstart) ? 1.0f : -1.0f;
-    } else if (xstart == xend) {  /* vertical line */
-        verts[1] += (yend > ystart) ? 1.0f : -1.0f;
+    {
+        const float xstart = points[0].x;
+        const float ystart = points[0].y;
+        const float xend = points[1].x;
+        const float yend = points[1].y;
+
+        if (ystart == yend) {  /* horizontal line */
+            verts[0] += (xend > xstart) ? 1.0f : -1.0f;
+        } else if (xstart == xend) {  /* vertical line */
+            verts[1] += (yend > ystart) ? 1.0f : -1.0f;
+        }
     }
 
     return 0;
@@ -1127,6 +1144,7 @@ @implementation METAL_TextureData
 
     for (int i = 0; i < count; i++) {
         int j;
+        float *xy_;
         if (size_indices == 4) {
             j = ((const Uint32 *)indices)[i];
         } else if (size_indices == 2) {
@@ -1137,7 +1155,7 @@ @implementation METAL_TextureData
             j = i;
         }
 
-        float *xy_ = (float *)((char*)xy + j * xy_stride);
+        xy_ = (float *)((char*)xy + j * xy_stride);
 
         *(verts++) = xy_[0] * scale_x;
         *(verts++) = xy_[1] * scale_y;
@@ -1282,11 +1300,10 @@ @implementation METAL_TextureData
 METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
 { @autoreleasepool {
     METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
+    id<MTLBuffer> mtlbufvertex = nil;
     METAL_DrawStateCache statecache;
     SDL_zero(statecache);
 
-    id<MTLBuffer> mtlbufvertex = nil;
-
     statecache.pipeline = nil;
     statecache.vertex_buffer = nil;
     statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
@@ -1363,15 +1380,17 @@ @implementation METAL_TextureData
                 statecache.cliprect_dirty = SDL_TRUE;
                 statecache.viewport_dirty = SDL_TRUE;
 
-                const Uint8 r = cmd->data.color.r;
-                const Uint8 g = cmd->data.color.g;
-                const Uint8 b = cmd->data.color.b;
-                const Uint8 a = cmd->data.color.a;
-                MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
+                {
+                    const Uint8 r = cmd->data.color.r;
+                    const Uint8 g = cmd->data.color.g;
+                    const Uint8 b = cmd->data.color.b;
+                    const Uint8 a = cmd->data.color.a;
+                    MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
 
-                // get new command encoder, set up with an initial clear operation.
-                // (this might fail, and future draw operations will notice.)
-                METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
+                    // get new command encoder, set up with an initial clear operation.
+                    // (this might fail, and future draw operations will notice.)
+                    METAL_Activ

(Patch may be truncated, please check the link at the top of this post.)