Newer version of GCC throws reinterpret_cast error

痞子三分冷 提交于 2021-01-28 14:09:48

问题


I am developing an embedded project (on STM32). I currently use GCC 4.9.2, but I would like to switch to newer version of my toolchain. Unfortunately my code which succesfully compiles on gcc 4.9.2, throws reinpreted_cast errors on version 6.2.0 or 7.2.0 and I have no idea why. It looks like that newer gcc sees some problems when casting int to pointer and back to int - which I think should be quite normal operation.

Error message thrown:

1>STM32L4\CMSIS\stm32l4a6xx.h(1567,30): error : 'reinterpret_cast<ADC_TypeDef*>(1342439424)' is not a constant expression
1>          #define ADC1                ((ADC_TypeDef *) ADC1_BASE)
1>                                       ^
1>         Sources\CAdc.cpp(31,35): note:  in expansion of macro 'ADC1'
1>             case reinterpret_cast<uint32_t>ADC1: u32DMAChannel = LL_DMA_CHANNEL_1; break;

Here is part of my code which error refers to:

switch ((uint32_t)adc)
{
case (uint32_t)ADC1: u32DMAChannel = LL_DMA_CHANNEL_1; break;
case (uint32_t)ADC2: u32DMAChannel = LL_DMA_CHANNEL_2; break;
case (uint32_t)ADC3: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}

And adc declaration:

private:
   ADC_TypeDef *adc;

Here are all macros definitions:

#define PERIPH_BASE           (0x40000000UL) /*!< Peripheral base address */
#define AHB2PERIPH_BASE       (PERIPH_BASE + 0x08000000UL)
#define ADC1_BASE             (AHB2PERIPH_BASE + 0x08040000UL)
#define ADC1                  ((ADC_TypeDef *) ADC1_BASE)

So for compiler, my in-switch cast looks like this:

(uint32_t)((ADC_TypeDef *) (((0x40000000UL)+ 0x08000000UL)+ 0x08040000UL))

Simple cast of unsigned long to some struct pointer and back to unsigned long. What is wrong with it? Whould should I do to get rid of this error? Any macro edition is impossible for me because these are BSP libraries.


回答1:


It is not the reinterpret that is failing, but rather the reinterpreted value is not regarded as a constant so therefore cannot be used as a case label.

Case labels must be a constant expression, and a constant expression is any expression that can be evaluated at compile time. In C++ evaluation of a reinterpret_cast expression is not a constant expression.

The compiler behaviour change here appears that the compiler translates the previously brute-force C-style cast into a more restrictive C++ reinterpret_cast. Testing at https://www.onlinegdb.com/ shows that this behaviour occurs when C++17 compilation is used but not C++14, so the simple "no code change" solution is to set the compilation to the earlier standard - arguably a sensible approach for legacy code in any case to avoid any other surprises or gotchas.

It seems however that the stm32l4a6xx.h header already provides two representations of the ADC base address one an integer (ADCx_BASE) and the other a pointer (ADCx). It is generally better to avoid casts at all and use the appropriate representation of the purpose. In this case:

switch ((uint32_t)adc)
{
    case ADC1_BASE: u32DMAChannel = LL_DMA_CHANNEL_1; break;
    case ADC2_BASE: u32DMAChannel = LL_DMA_CHANNEL_2; break;
    case ADC3_BASE: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}



回答2:


You might change code to avoid cast in cases of switch:

switch ((uint32_t)adc)
{
    case ADC1_BASE: u32DMAChannel = LL_DMA_CHANNEL_1; break;
    case ADC2_BASE: u32DMAChannel = LL_DMA_CHANNEL_2; break;
    case ADC3_BASE: u32DMAChannel = LL_DMA_CHANNEL_3; break;
}


来源:https://stackoverflow.com/questions/54056811/newer-version-of-gcc-throws-reinterpret-cast-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!