2015-02-26 4 views
10

Я пишу загрузчик в C11. Когда загрузчику необходимо перенести элемент управления на прошивку, он считывает указатель на определенный предопределенный адрес памяти и вызывает его. Код выглядит следующим образом:Как использовать noreturn с указателем функции?

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(); 
} 

Функция Firmware_boot() никогда не возвращается, так что имеет смысл объявить его как noreturn:

#include <stdnoreturn.h> 

noreturn void 
Firmware_boot(void); 

Но мне нужно объявить FirmwareBootFn, как noreturn также, чтобы избежать компилятор жалуется, что Firmware_boot() может вернуться.

Я пробовал (возможно) каждую перестановку noreturn в typedef без каких-либо результатов. Также я понял, что атрибут не может быть установлен в typedef, потому что он не является частью этого типа.

Есть ли способ пометить мой Firmware_boot() как noreturn, избегая предупреждения (ну без обмана с предупреждением :-))?

+0

Я только что нашел обходное решение для gcc: используя ** __ builtin_unreachable **() отмечает определенную точку кода, поскольку «эта строка никогда не будет выполнена», тем самым предоставив свойство noreturn. Несмотря на это, он не переносится и не позволяет компилятору понять, что (по крайней мере, IMO) g_bootControl.programCounter() не возвращается и не применяет правильную оптимизацию. – MaxP

+1

@MaxP, как документация, так и выход ассемблера небольшой тестовой программы, похоже, указывают, что она используется для оптимизации. (Если 'foo' объявлен' _Noreturn' и 'bar' нет,' foo(); 'и' bar(); __builtin_unreachable(); 'генерировать эквивалентный код.) – mafso

+0

Если вы хотите использовать расширение, используйте атрибут. Пожалуйста, см. Мой ответ. –

ответ

6

_Noreturn в C11 может применяться только к определениям функций или декларациям. К сожалению, тот факт, что функция не возвращается, не является частью прототипа.

Поскольку вы, кажется, GCC вы можете использовать расширение

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

отметить указатель на функцию не возвращаются. К сожалению, хотя, похоже, нет способа гарантировать, что функция, которую вы назначаете, действительно имеет это свойство по синтаксису allone.

 Смежные вопросы

  • Нет связанных вопросов^_^