Sto scrivendo un bootloader in C11. Quando il bootloader deve trasferire il controllo al firmware, legge un puntatore a una funzione all'indirizzo di memoria predefinito e lo chiama. Il codice è simile al seguente:Come utilizzare noreturn con il puntatore funzione?
typedef void (FirmwareBootFn)(void);
typedef struct
{
uint32_t stackPointer;
FirmwareBootFn* programCounter;
}
FirmwareBootControl;
static FirmwareBootControl g_bootControl __attribute__ ((section (".boot_control")));
void
Firmware_boot(void)
{
setStackPointer(g_bootControl.stackPointer);
g_bootControl.programCounter();
}
Funzione Firmware_boot()
non ritorna mai, quindi aveva senso di dichiararla come noreturn
:
#include <stdnoreturn.h>
noreturn void
Firmware_boot(void);
ma ho bisogno di dichiarare FirmwareBootFn
come noreturn
anche per evitare il compilatore che lamenta che Firmware_boot()
potrebbe restituire.
Ho provato (eventualmente) tutte le permutazioni di noreturn
nello typedef
senza alcun risultato. Inoltre ho capito che l'attributo non può essere impostato nel typedef
perché non fa parte del tipo.
C'è un modo per taggare il mio Firmware_boot()
come noreturn
evitando l'avviso (beh, senza barare con soppressione degli avvisi :-))?
Ho appena trovato una soluzione alternativa per gcc: l'utilizzo di ** __ builtin_unreachable **() contrassegna un punto di codice specifico come "questa riga non verrà mai eseguita", garantendo così la proprietà noreturn. Nonostante funzioni, non è portabile e non consente al compilatore di capire che (almeno IMO) g_bootControl.programCounter() non ritorna e applica l'ottimizzazione corretta. – MaxP
@MaxP, sia la documentazione che l'output assemblatore di un piccolo programma di test sembrano indicare che viene utilizzato per l'ottimizzazione. (Se 'pippo' è dichiarato' _Noreturn' e 'bar' no,' foo(); 'e' bar(); __builtin_unreachable(); 'genera codice equivalente.) – mafso
Se si desidera utilizzare un'estensione, usa un 'attributo'. Per favore vedi la mia risposta. –