问题
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 case
s 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