Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm when update Xcode to 5.1 (5B130a)

Yesterday, I updated Xcode to the newest version (5.1 (5B130a)) to compatible with iOS 7.1. Then I build my project, I get the error "Cast from pointer to smaller type 'int' loses information" in EAGLView.mm file (line 408) when 64-bit simulators (e.g.: iPhone Retina 4-inch 64-bit) is selected.

I'm using cocos2d-x-2.2.2. Before I update Xcode, my project still can build and run normally with all devices.

Thanks for all recommendation.

Update: Today, i download the latest version of cocos2d-x (cocos2d-x 2.2.3). But the problem has still happened.

Here is some piece of code where that error occur:

/cocos2d-x-2.2.2/cocos2dx/platform/ios/EAGLView.mm:408:18: Cast from pointer to smaller type 'int' loses information

// Pass the touches to the superview
#pragma mark EAGLView - Touch Delegate
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (isKeyboardShown_)
    {
        [self handleTouchesAfterKeyboardShow];
        return;
    }

    int ids[IOS_MAX_TOUCHES_COUNT] = {0};
    float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
    float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};

    int i = 0;
    for (UITouch *touch in touches) {
        ids[i] = (int)touch;     // error occur here
        xs[i] = [touch locationInView: [touch view]].x * view.contentScaleFactor;;
        ys[i] = [touch locationInView: [touch view]].y * view.contentScaleFactor;;
        ++i;
    }
    cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
}
like image 760
nvg58 Avatar asked Mar 15 '14 03:03

nvg58


4 Answers

Apparently the clang version in Xcode 5.1 and above is more strict about potential 32bit vs. 64 bit incompatibilities in source code than older clang versions have been. To be honest, I think, clang is too restrictive here. A sane compiler may throw a warning on lines like this but by no way it should throw an error, because this code is NOT wrong, it is just potentially error-prone, but can be perfectly valid.

The original code is

ids[i] = (int)touch;

with ids being an array of ints and touch being a pointer.

In a 64bit build a pointer is 64bit (contrary to a 32bit build, where it is 32bit), while an int is 32bit, so this assignment stores a 64bit value in a 32bit storage, which may result in a loss of information.

Therefore it is perfectly valid for the compiler to throw an error for a line like

ids[i] = touch;

However the actual code in question contains an explicit c-style cast to int. This explicit cast clearly tells the compiler "Shut up, I know that this code does not look correct, but I do know what I am doing".

So the compiler is very picky here and the correct solution to make the code compile again and still let it show the exact same behavior like in Xcode 5.0 is to first cast to an integer type with a size that matches the one of a pointer and to then do a second cast to the int that we actually want:

ids[i] = (int)(size_t)touch;

I am using size_t here, because it is always having the same size as a pointer, no matter the platform. A long long would not work for 32bit systems and a long would not work for 64 bit Windows (while 64bit Unix and Unix-like systems like OS X use the LP64 data model, in which a long is 64bit, 64bit Windows uses the LLP64 data model, in which a long has a size of 32bit (http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)).

like image 54
Kaiserludi Avatar answered Nov 15 '22 21:11

Kaiserludi


I meet this problem too.

ids[i] = (int)touch; // error occur here => I change this to below.

ids[i] = (uintptr_t)touch;

Then i can continue compiling. Maybe you can try this too.

like image 44
Muhammad Aamir Ali Avatar answered Nov 15 '22 19:11

Muhammad Aamir Ali


XCode 5.1 is change all architecture to 64 bit.

you can just change architecture to support 32 bit compilation by all below in in Build Settings

  • use $(ARCHS_STANDARD_32_BIT) at Architecture instead of $(ARCHS_STANDARD)
  • remove arm64 at Valid Architectures

Hope it helps.

like image 2
Peeradon Tadsanaborrisut Avatar answered Nov 15 '22 20:11

Peeradon Tadsanaborrisut


You can fix this error by replacing this line of code.

ids[i] = (uint64_t)touch;

You should perform type conversion based on 64bit build system because the type "int" supports only -32768 ~ 32768.

like image 2
user6385420 Avatar answered Nov 15 '22 21:11

user6385420