2015-02-26 14 views
10

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 :-))?

+0

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

+1

@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

+0

Se si desidera utilizzare un'estensione, usa un 'attributo'. Per favore vedi la mia risposta. –

risposta

6

_Noreturn in C11 può essere applicato solo a definizioni di funzioni o dichiarazioni. Il fatto che la funzione non ritorni non fa parte del prototipo, sfortunatamente.

Dal momento che ti sembra di avere gcc si potrebbe usare un'estensione

typedef struct 
{ 
    uint32_t stackPointer; 
    __attribute__((__noreturn__)) FirmwareBootFn* programCounter; 
} 
FirmwareBootControl; 

per contrassegnare il puntatore a funzione, come non tornare. Sfortunatamente, però, non sembra esserci un modo per garantire che la funzione assegnata a tale proprietà abbia realmente quella sintassi, a parte tutti.

Problemi correlati