mirror of
https://github.com/ArduPilot/ardupilot.git
synced 2026-10-06 19:00:27 +08:00
In Clang (independent of OS or architecture), if three factors are true about a static variable initialization (const or not): * `-ftrapping-math` is turned on * a double literal needs to be rounded and doesn't exactly equal a float * the initialization involves something which isn't constexpr then Clang will decline to do constant initialization, unlike GCC, or Clang if any one of these factors is not true. Constant initialization is where the object is initialized as part of the memory image and is ready to go when the program is loaded. Instead, Clang will generate code at runtime to do the initialization. This is fine in a vacuum, but it makes lots more variables suddenly vulnerable to the static initialization order fiasco. In particular, many of the `AP_Param::Info` tables for the parameter system meet all the factors. The use for these tables, `AP_Param::setup_object_defaults`, is part of constructors of objects which are usually constructed in a different file than the table. Due to the new runtime initialization, there is no longer a guarantee that the table has meaningful data at the time of that setup call. This causes many parameter defaults to not be loaded and the system generally crashes and burns. This PR addresses the issue by fixing the non-constexpr casts in `AP_VAROFFSET` and `AP_CLASSTYPE` to use things permissible in constexpr. The compiler then constant initializes these tables again, parameters get their defaults, and everybody is happy. This is probably easier than fixing all the double literals to be floats. This fix could be "locked in" and be made to cause a compiler error in case of a problem by declaring all tables `constexpr`, but that is a lot of effort. Examination of the binary symbol tables shows that all `var_info` tables are correctly constant initialized now.