NSDictionary != NSMutableDictionary

Xcode (tested with 10, and Xcode 11 Betas) allows a pointer to NSDictionary* (a pointer to a pointer) be used instead of a pointer to NSMutableDictionary*, which leads to a runtime crash instead of expected compilation error. I submitted a bug about it, but the bug returned with "works with clang-1001.0.46.3 which is part of Xcode 10.2". i wonder what that means to me as I do not use clang in terminal, only via Xcode. Can / should I somehow change the clang version that is used by Xcode?


a side question, are there several versions of clang installed with Xcode and for whatever reason Xcode is not using the latest one?


void foo(NSMutableDictionary** mutableDictionary) {

(*mutableDictionary)[@"hello"] = @"world";

}


...

NSDictionary* dictionary = [NSDictionary new];

foo(&dictionary); // no compilation error here!


// runtime error:

// *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionary0 setObject:forKeyedSubscript:]: unrecognized selector sent to instance

....


originally rdar://49775697

plus FB6447069, this time against Xcode

Replies

not even the above, even this:


void foo(NSMutableDictionary** mutableDictionary) {

(*mutableDictionary)[@"hello"] = @"world";

}

...

NSObject* whatever = [NSObject new];

foo(&whatever); // no compilation error or warning here! obvious runtime crash down the road


looks like any superclass pointer causes this behavior. quite dangerous behaviour.


Animal -> Dog -> Labrador


void labradors_only_here_please(Labrador** labrador) {

[*labrador whatever_only_labradors_can_do];

}


Dog* generic_dog = [Dog new];

labradors_only_here_please(&generic_dog) // ok cap, no problem... boom, crash

I tried your example and got the following warning:


Incompatible pointer types passing 'NSDictionary **' to parameter of type 'NSMutableDictionary **'

weird... i even enabled "pedantic warnings", "treat incompatible pointer types warnings as errors" and "treat warnings as errors" and still no joy. tried different "C language dialects" as well. can you reveal the exact warning message in the build window, and post here the message - if there's a "code" in brackets i might be able putting it as an explicit "Werror" in the project.

are you using arc at all? try with -fobjc-arc flag.

i noticed that makes a difference.

apperently it is not fixed neither in clang-1001.0.46.3 (Xcode 10.2) nor in clang-1100.0.20.17 (Xcode 11 Beta 2)

i now realize it was not obvious what and who i was referring to..

John, if you compile the app with "-fobjc-arc -Werror" flag you'll notice it stops emitting the wanted warning / error.

in other words this compiler bug is triggered only with "-fobjc-arc". switching ARC off is not an option for me in this case.

I submitted a bug about it, but the bug returned with "works with clang-1001.0.46.3 which is part of Xcode 10.2".

I think you misinterpreted that response. I just had a look at the state of your bug (r. 49775697) and it’s definitely still open and being treated as a bug by the compiler folks.

ps The fact that the warning is not emitted in the ARC case is likely to be the result of the compiler taking a different code path in order to handle one of the many complexities of ARC.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I did compile a sample app and could reproduce the problem. Originally I tried it in my own app, which doesn't use ARC. Sounds like yet another reason to avoid using ARC if it is going to silently mask errors like this.

>>I did compile a sample app and could reproduce the problem.


thanks


>>Originally I tried it in my own app, which doesn't use ARC. Sounds like yet another reason to avoid using ARC if it is going to silently mask errors like this.


that would be a ******* :-) i only use Obj-C now when have to, generally it is a very thin shim between swift and C++ (that i also use only when i have to). in this context it's particularly problematic to use Obj-C w/o ARC.

I think you've got that backwards. Swift is a heavy, syntatic-sugar wrapper around Objective-C with ARC. Although Swift is written in C++, it is completely incompatible with it. Memory management, like type management, is a trivially easy task.

i mean i use Obj-C as a thin bridge layer between swift and C++. it is hard/impossible to use C++ without Obj-C layer in the otherwise swift app.