NSDictionary == NSMutableDictionary #pragma
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
On Jul 6, 2019, at 2:19 PM, yetanothermeagain <gofennex@...> wrote: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
On Jul 6, 2019, at 18:04, Jack Brindle via Groups.Io <jackbrindle@...> wrote:Yes. Re-read the example. If the function takes NSMutableDictionary**, it should complain when you pass it an NSDictionary**, same as if it wants NSMutableDictionary* and you pass it NSDictionary*.
Is this really a bug?
The opposite, however, is perfectly fine and correct; passing an NSMutableDictionary (with any number of splats) to a function that wants an NSDictionary. That’s how subclassing works.
Steve via iPad
but when i build this exact source from terminal i am getting the warning (or error if warnings are treated as errors) as expected!
> clang main.m -Werror
> main.m:10:13: error: incompatible pointer types passing 'NSDictionary **' to parameter of type
'NSMutableDictionary **' [-Werror,-Wincompatible-pointer-types]
foo(&dictionary);
^~~~~~~~~~~
main.m:3:32: note: passing argument to parameter 'mutableDictionary' here
void foo(NSMutableDictionary** mutableDictionary) {
^
1 error generated.
clang version is this:
> clang -v
> Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
and when I compile with Xcode i see the same path:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
====================
#import <Foundation/Foundation.h>
void foo(NSMutableDictionary** mutableDictionary) {
(*mutableDictionary)[@"hello"] = @"world";
}
int main(int argc, const char* argv[]) {
@autoreleasepool {
NSDictionary* dictionary = [NSDictionary new];
foo(&dictionary);
}
return 0;
}
i tracked the difference down to this: "clang main.m -Werror -fobjc-arc"
it looks like the apple responder to my bug report just didn't use the "-fobjc-arc" key, so it worked for him and thus he replied with "it works in" whatever version of Xcode / clang he happened to have on his machine without properly investigating the cause of the problem... i can see the same happening with Xcode 11 beta 2 (clang-1100.0.20.17). will update my bug report with this information.
is Xcode 12 beta already out?
On Jul 7, 2019, at 11:05 PM, Marco S Hyman <marc@...> wrote:*facepalm*
You’re off a digit. Current Xcode is 10.2.1. Beta Xcode is 11.0. 12 is still in the future.is Xcode 12 beta already out?Yes, it’s been out since WWDC a month ago. You can download beta 3 now; it’s pretty solid.
That’s what I get for emailing on my iPad. Sorry!
—Jens
Because this amuses me, particularly as it's so easily reproducible yet symptomatic of Apple's incapacity to address basic bugs, I've filed my own bug using your code sample: FB10228325.
(What's your bug number? Could add a cross-reference from mine.)
-ben
On 13 Jun 2022, at 9:17 am, yetanothermeagain <gofennex@...> wrote:
Fast forward 2022 Xcode 13 - This is still unfixed, I still see no warning/error - and then the crash with ARC enabled (the crash is expected in this case, the absence of error or warning - not).
On Jun 13, 2022, at 12:00 PM, yetanothermeagain <gofennex@...> wrote:Thank you for filing the bug!
Mine was "originally rdar://49775697 plus FB6447069, this time against Xcode"
> Apple's incapacity to address basic bugs
Understandably Obj-C is not the focus anymore for a number of years.
What’s the specific error?I don’t see the explanation in the email thread. It’s possible my coffee levels are too low. Do I need another cup?Thanks,Alex ZavatoneOn Jun 13, 2022, at 12:00 PM, yetanothermeagain <gofennex@...> wrote:Thank you for filing the bug!
Mine was "originally rdar://49775697 plus FB6447069, this time against Xcode"
> Apple's incapacity to address basic bugs
Understandably Obj-C is not the focus anymore for a number of years.
On 13 Jun 2022, at 12:15 pm, Alex Zavatone via groups.io <zav@...> wrote:Whose opinion are you seeking?
Silly question. Does this fall under the case of “yes, Apple, fix this” or “OK, now you know. Don’t do that.”
Or both?
Sort of a “yes you can do this but you should know better” or does this actually fall under a valid use of the language?
At least two of us participating in this discussion feel that this demonstrates an obvious compiler bug, which is why we've filed reports. I haven't seen a contrary argument (unless I missed it).
-ben
On Jun 13, 2022, at 2:48 PM, Ben Kennedy <ben-groups@...> wrote:Just any of the list members. The fact that two of us feel it is a compiler bug and not a valid use certainly matters. I was just thinking that it was worth asking since I’ve never even tried pointers to pointers because from what I’ve learned, it’s just asking for trouble.On 13 Jun 2022, at 12:15 pm, Alex Zavatone via groups.io <zav@...> wrote:Whose opinion are you seeking?
Silly question. Does this fall under the case of “yes, Apple, fix this” or “OK, now you know. Don’t do that.”
Or both?
Sort of a “yes you can do this but you should know better” or does this actually fall under a valid use of the language?
At least two of us participating in this discussion feel that this demonstrates an obvious compiler bug, which is why we've filed reports. I haven't seen a contrary argument (unless I missed it).
-ben
Cheers,
Alex Zavatone
On 13 Jun 2022, at 1:22 pm, Alex Zavatone via groups.io <zav@...> wrote:I'm not sure I'm following your line of inquiry (surely, the language and the compiler are supposed to be well-specified and deterministic). But I feel it's worth pointing out that double indirection is often used in Obj-C API, typically for returning things by reference; you've probably used it a bunch yourself, particularly in `NSError **` arguments.
Just any of the list members. The fact that two of us feel it is a compiler bug and not a valid use certainly matters. I was just thinking that it was worth asking since I’ve never even tried pointers to pointers because from what I’ve learned, it’s just asking for trouble.
-ben
On Jun 13, 2022, at 4:23 PM, Ben Kennedy <ben-groups@...> wrote:Perhaps I should have said “I’ve never implemented methods in that manner myself.”On 13 Jun 2022, at 1:22 pm, Alex Zavatone via groups.io <zav@...> wrote:I'm not sure I'm following your line of inquiry (surely, the language and the compiler are supposed to be well-specified and deterministic). But I feel it's worth pointing out that double indirection is often used in Obj-C API, typically for returning things by reference; you've probably used it a bunch yourself, particularly in `NSError **` arguments.
Just any of the list members. The fact that two of us feel it is a compiler bug and not a valid use certainly matters. I was just thinking that it was worth asking since I’ve never even tried pointers to pointers because from what I’ve learned, it’s just asking for trouble.
-ben
For reference, my report included the following code (lifted from the original thread):
@import Foundation;The Apple reply is as follows:
void foo(NSMutableDictionary** mutableDictionary)
{
(*mutableDictionary)[@"hello"] = @"world";
}
int main(int argc, const char * argv[])
{
NSDictionary* dictionary = [[NSDictionary alloc] init];
foo(&dictionary); // no compilation error here!
return 0;
}
Is it necessary for foo to take parameter NSMutableDictionary**? Can you change it to NSMutableDictionary*`?I don't think I understand the reasoning offered by the Apple respondent, but before I reply, I wanted to see if it's meaningful to anyone else.
void foo(NSMutableDictionary* mutableDictionary)
{
mutableDictionary[@"hello"] = @"world";
}
We don’t think clang should reject the code just because it is passing a NSDictionary** to a function expecting a NSMutableDictionary**. We don’t want to reject the following code, for example:
void foo(NSMutableDictionary** mutableDictionary)
{
NSMutableDictionary* md = [[NSMutableDictionary alloc] init];
*mutableDictionary = md;
}
foo is assigning a pointer to a newly created NSMutableDictionary object to dictionary, which is an NSDictionary pointer, in main.
Whether or not foo() takes a double indirection, and despite what it might do in its body, I don't see how the suggested change remedies the error of passing an immutable dictionary reference at the call site in main().
-ben