weixin_39899630
weixin_39899630
2021-01-09 00:33

Narrowing conversion error trying to compile Urho3D under C++11.

I'm encountering an error with narrowing conversions, while trying to compile Urho3D under C++11 (with URHO3D_C++11 build option). The error occurs in the Bullet code:


C:\Projects\Game Development\Engines\Urho3D\Source\ThirdParty\Bullet\src\LinearMath\btScalar.h:339:54: error: narrowing conversion of '+Inf' from 'double' to 'float' inside { }
 #define btAssign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3}
                                                      ^
C:\Projects\Game Development\Engines\Urho3D\Source\ThirdParty\Bullet\src\LinearMath\btVector3.cpp:442:21: note: in expansion of macro 'btAssign128'
     float4 dotmin = btAssign128( BT_INFINITY,  BT_INFINITY,  BT_INFINITY,  BT_INFINITY );
                     ^

That's the basic error (it is repeated a couple of times, in different places, sometimes with -Inf instead of +Inf).

My compiler is TDM-GCC 5.1.0, under Windows. This error cropped up this time with commit 9b78bbacb60ea3a37faa3001ee60cd87c3ec31f1, but it has occurred to me earlier as well (cannot recall the commit hash).

I managed to work around it by changing the Bullet source code which throws the error (mentioned above in the log):


 #define btAssign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3}

to:


#define btAssign128(r0,r1,r2,r3) (__m128){static_cast<float>(r0),static_cast<float>(r1),static_cast<float>(r2),static_cast<float>(r3)}
</float></float></float></float>

I feel like this is a time bomb that's ticking away, though.

Any help would be appreciated. Please ask if you need more information.

EDIT: Adding Wno-narrowing and/or Wno-error=narrowing to CMAKE_CXX_FLAGS did not help with the issue.

该提问来源于开源项目:urho3d/Urho3D

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

13条回答

  • weixin_39711721 weixin_39711721 3月前

    Actually there is already an existing workaround for this issue. Please see commit 02e1aec083a19b902d12b8d76f9846fb3e1dcbb7. However, it is applied only when the MinGW version is 6.1.0 or above. I hit this issue even without C++11 standard enabled.

    点赞 评论 复制链接分享
  • weixin_39585070 weixin_39585070 3月前

    My testing seems to indicate, too, that the -Wno-narrowing option does not help with this compiler. The static cast should be a safe compile-time no-op when the INFINITY constant already is a float, so seems safe to apply regardless.

    点赞 评论 复制链接分享
  • weixin_39551188 weixin_39551188 3月前

    Would it be better to sc<> around INFINITY instead of btAssign128? In this case user will receive this warning if use btAssign128 with doubles

    点赞 评论 复制链接分享
  • weixin_39899630 weixin_39899630 3月前

    : Yes, I actually tried lowering the version check to 5.1.0 and applying the workaround, but it didn't help either. Sorry, I forgot to mention that.

    What do you think about 's idea? It seems like a good one, too. They bring up a point, too: in the fix I made, the "bug" (not sure if we can call it that exactly?) might still occur in different code paths/define paths (not sure).
    So if we finally up and define BT_INFINITY as static_cast<float> in the end, would that make this possible issue go away for all code paths?

    点赞 评论 复制链接分享
  • weixin_39676348 weixin_39676348 3月前

    I was looking at how std::numeric_limits<float>::infinity(); is implemented. And it seems to return __builtin_huge_valf() which is most likely available as macro HUGE_VALF in C++11.

    So either one of these could work without having to cast to float:

    
    #define BT_INFINITY std::numeric_limits<float>::infinity()
    #define BT_INFINITY HUGE_VALF
    </float>

    Or, explicitly check if you're on GCC/MinGW and use #define BT_INFINITY __builtin_huge_valf() since the problem occurs mostly on MinGW.

    The only time this starts to get nasty is when btScalar is a double because it was compiled with double floating point precision. You'll need a few extra macro conditions to make sure you don't reach that situation.

    点赞 评论 复制链接分享
  • weixin_39585070 weixin_39585070 3月前

    Went with a localized fix in the btVector3.cpp file in the end, to not need to mess with Bullet headers or how infinity is defined for the rest of the library.

    点赞 评论 复制链接分享
  • weixin_39585070 weixin_39585070 3月前

    Can you check how the BT_INFINITY gets defined on your compiler? I understood that the INFINITY constant (which should be used for win32 code path) should be a float.

    点赞 评论 复制链接分享
  • weixin_39899630 weixin_39899630 3月前

    It's defined like so:

    
    #define BT_INFINITY INFINITY
    

    Maybe this INFINITY is in the math.h header? In which case it's being defined:

    
    #define INFINITY    __builtin_inf()
    

    __builtin_inf() seems to return a double after a bit of searching around (here's the page, search for __builtin_inf). So yeah, it's being defined as a double?

    点赞 评论 复制链接分享
  • weixin_39585070 weixin_39585070 3月前

    I'd say the cast to float in the macro would be an acceptable fix. Whether it's double or float seems to be compiler-dependant, then.

    点赞 评论 复制链接分享
  • weixin_39676348 weixin_39676348 3月前

    You can try the following to be sure it's a double printf("%s", typeid(INFINITY).name()); should output a d if it's a double.

    点赞 评论 复制链接分享
  • weixin_39899630 weixin_39899630 3月前

    OK, so I printed out typeid(BT_INFINITY).name() (it will have the same effect since it is defined as INFINITY) from within my Urho3D project, and it's d like said.

    点赞 评论 复制链接分享
  • weixin_39899630 weixin_39899630 3月前

    I made a pull request that applies the fix. Ignore that first one, that's just some stupidity on my part.

    点赞 评论 复制链接分享
  • weixin_39585070 weixin_39585070 3月前

    Thanks!

    点赞 评论 复制链接分享