Reputation: 23
I encountered the following SonarQube remark (MISRA-C:2012), while implementing the startup code in C, for an ARM Cortex-M3:
Function names should be used either as a call with a parameter list or with the "&" operator
with the following description:
Using a "bald" function name is likely a bug. Rather than testing the return value of a function with a void parameter list, it implicitly retrieves the address of that function in memory. If that's truly what's intended, then it should be made explicit with the use of the & (address-of) operator. If it's not, then a parameter list (even an empty one) should be added after the function name.
I am using the following compiler:
armclang V6.12, with Language C99
The version of the SonarQube is:
Version 6.7 (build 33306)
The SonarQube remark is raised on the Reference of Reset_Handler inside the Vector Table array. (see the code below)
/*----------------------------------------------------------------------------
Exception / Interrupt Handler Function Prototype
*----------------------------------------------------------------------------*/
typedef void (*pFunc)(void);
/*----------------------------------------------------------------------------
External References
*----------------------------------------------------------------------------*/
extern uint32_t __INITIAL_SP;
extern __NO_RETURN void __PROGRAM_START(void);
/*----------------------------------------------------------------------------
Internal References
*----------------------------------------------------------------------------*/
__NO_RETURN void Default_Handler(void);
__NO_RETURN void Reset_Handler(void);
/*----------------------------------------------------------------------------
Exception / Interrupt Handler
*----------------------------------------------------------------------------*/
/* Exceptions */
void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void HardFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void MemManage_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
/*----------------------------------------------------------------------------
Exception / Interrupt Vector table
*----------------------------------------------------------------------------*/
extern const pFunc __VECTOR_TABLE[16];
const pFunc __VECTOR_TABLE[16] __VECTOR_TABLE_ATTRIBUTE = {
(pFunc)(&__INITIAL_SP), /* Initial Stack Pointer */
Reset_Handler, /* Reset Handler <<<<<------ WHERE THE SONARQUBE REMARK IS */
NMI_Handler, /* -14 NMI Handler */
HardFault_Handler, /* -13 Hard Fault Handler */
MemManage_Handler, /* -12 MPU Fault Handler */
BusFault_Handler, /* -11 Bus Fault Handler */
UsageFault_Handler, /* -10 Usage Fault Handler */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
SVC_Handler, /* -5 SVCall Handler */
DebugMon_Handler, /* -4 Debug Monitor Handler */
0, /* Reserved */
PendSV_Handler, /* -2 PendSV Handler */
SysTick_Handler, /* -1 SysTick Handler */
};
void Reset_Handler(void)
{
SystemInit(); // CMSIS System Initialization
__PROGRAM_START(); // Enter PreMain (C library entry point)
}
void Default_Handler(void)
{
while (1) {
__asm volatile(""); /* this line is considered to have side-effects */
}
}
I don't really understand why it complains at that particular point, and I don't really see what am I missing:
- the function pointer is defined at the beginning pFunc
- the return type is defined as void, and also there are no parameters for the functions
- the type of the Vector Table array is "pFunc"
- both the Default_Handler, as well as the Reset_Handler match the correct prototype as defined by the function pointer
Any help would be appreciated. :)
Thank you.
@Lundin I found the following example of non-compliant code:
int func(void) {
// ...
}
void f2(int a, int b) {
// ...
if (func) { // Noncompliant - tests that the memory address of func() is non-null
//...
}
// ...
}
Compliant code:
void f2(int a, int b) {
// ...
if (func()) { // tests that the return value of func() > 0
//...
}
// ...
}
So you seem to be right. The tool thinks is a different issue.
Upvotes: 2
Views: 417
Reputation: 224917
The SonarQube warning is complaining that you're using the name of a function without calling it, suspecting that you meant to actually call it.
Because a function name is automatically converted to a pointer to a function, func
and &func
refer to the same thing, so you can use them interchangeably.
Since you're not attempting to call the functions but are instead putting their addresses in an array, use the address-of operator to make it explicit that you want to take the address of the function instead of calling it, along with any other function pointers.
extern const pFunc __VECTOR_TABLE[16];
const pFunc __VECTOR_TABLE[16] __VECTOR_TABLE_ATTRIBUTE = {
(pFunc)(&__INITIAL_SP), /* Initial Stack Pointer */
&Reset_Handler, /* Reset Handler */
&NMI_Handler, /* -14 NMI Handler */
&HardFault_Handler, /* -13 Hard Fault Handler */
&MemManage_Handler, /* -12 MPU Fault Handler */
&BusFault_Handler, /* -11 Bus Fault Handler */
&UsageFault_Handler, /* -10 Usage Fault Handler */
NULL, /* Reserved */
NULL, /* Reserved */
NULL, /* Reserved */
NULL, /* Reserved */
&SVC_Handler, /* -5 SVCall Handler */
&DebugMon_Handler, /* -4 Debug Monitor Handler */
NULL, /* Reserved */
&PendSV_Handler, /* -2 PendSV Handler */
&SysTick_Handler, /* -1 SysTick Handler */
};
Upvotes: 1