2

"Xcode 12.0 (12A7209)" shows compile error against Cocos3D library (written in Objective-C) in the following code:
(The past versions of Xcode ((ie ver.11, 10), including ver 11.7(11801a)) don't have this problems but Xcode 12.0 does.)

Error message:
Incompatible block pointer types sending 'void (^)(CC3ShaderProgram *, BOOL *)' to parameter of type 'void (^)(id, BOOL *)'

// CC3Shaders.m
+(void) willBeginDrawingScene {
    [_programCache enumerateObjectsUsingBlock: ^(CC3ShaderProgram* prog, BOOL* stop) {
        [prog willBeginDrawingScene];
    }];
}

// CC3Cache.m
-(void) enumerateObjectsUsingBlock: (void (^) (id<CC3Cacheable> obj, BOOL* stop)) block {
    [self lock];
    [_objectsByName enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL* stop) {
        block([obj resolveWeakReference], stop);
    }];
    [self unlock];
}

Basically Xcode 12.0's ObjC compiler complains about mismatching of object types of the input argument of the block "enumerateObjectsUsingBlock:".

But "CC3ShaderProgram" is inherited from "NSObject with CC3Cacheable protocol" as follows:

@interface CC3ShaderProgram : CC3Identifiable 
@interface CC3Identifiable : NSObject <CC3Cacheable, NSCopying>

So, "CC3ShaderProgram" is a matching type with "id" so compiler shouldn't complain but Xcode12.0 does.

Not only at "willBeginDrawingScene" but in other places in the library where "enumerateObjectsUsingBlock:" is being used have same problems.

I have been using Cocos3D library for past few years with several different versions of Xcode without this problem.

Are there any changes made in CLANG or SDK of "Xcode 12.0" to become stricter in terms of block argument type checking (something like "using generic object pointer "id" is not allowed") ? Otherwise, I don't understand why those two matching types are regarded as mis-matching types by the compiler and cause compile error in Xcode 12.0.

Would you be able to provide any good solution for this? It will be much appreciated.

Thank you.

Update: After changing the argument type to include "NSCopying" protocol in the block (to make the argument type's protocol set as same as "CC3ShaderProgram"), Xcode12 compiler has stopped complaining. (Previsouly, only CC3Cacheable protocol was included.)

-(void) enumerateObjectsUsingBlock: (void (^) (id<CC3Cacheable, NSCopying> obj, BOOL* stop)) block

For now, the code binary builds without this compile error. However, still I don't understand why Xcode 12.0 complains this, unless Xcode12's CLANG has become a lot stricter than its previous versions in terms of type checking.

s4mt6
  • 143
  • 1
  • 2
  • 9

2 Answers2

3

There are two ways to fix this in Cocos3D.

It can be fixed in code in CC3Cache.h, by adding __kindof to the definition of [CC3Cache enumerateObjectsUsingBlock:] as follows:

-(void) enumerateObjectsUsingBlock: (void (^) (__kindof id<CC3Cacheable> obj, BOOL* stop)) block;

which is where it should be fixed.

Alternately, the error can be muted at build time without code changes by including:

-Xclang -fcompatibility-qualified-id-block-type-checking

in the OTHER_CFLAGS build setting.

The original source of these solutions can be found here and here.

Bill Hollings
  • 2,344
  • 17
  • 25
  • Thanks for your reply, appreciate it. BTW, do you have any idea why this happens in Xcode12 not in other 'older' versions (ie Xcode 11, 10)? Perhaps any changes made in CLANG in Xcode12 to have its type checking stricter than others? – s4mt6 Sep 20 '20 at 18:02
  • I should think that's quite likely. Compilers evolve and receive enhancements like any other software. So this check may have recently been added as a new "feature". – Bill Hollings Sep 21 '20 at 01:25
  • If this solves the issue, can you accept this answer, so others know where to look, please? – Bill Hollings Sep 21 '20 at 01:26
  • It has solved the issue, so the answer has been accepted. Thanks, again. – s4mt6 Sep 21 '20 at 02:48
1

EDIT cleaned it up a bit

Try adding

-Wno-incompatible-pointer-types

to your compiler flags (Build Settings > Apple Clang > Custom Compiler Flags > Other Warning Flags). This is the best and a very useful option as it silences this often pesky warning.

In Xcode there is an option for that, under Build Settings > Apple Clang > Warnings > All languages you'll find Treat incompatible pointer types as warnings. This does not silence it though, but toggles between it being a warning or an error.

skaak
  • 2,988
  • 1
  • 8
  • 16
  • Thanks for you reply to my posting. BTW, "Treat Incompatible Pointer Type Warnings as Errors" in the build settings has been already turned off, but the compile error occurs. So I guess, Xcode's Clang or SDK has some changes in type checking. For now, anyway I can build the binary by changing the type in the block as I mentioned in the update. I have sent an inquiry to apple support. If I get something, I will post it. Thanks. – s4mt6 Sep 17 '20 at 15:53
  • Ok - thanks for the feedback ... the way I understand the Clang manual that setting should turn it off and I assume that the mentioned option in Xcode does the same. If not then (the new) Xcode is maybe a bit too strict. – skaak Sep 17 '20 at 16:18