_Noreturn in a struct in c: error: expected specifier-qualifier-list before '_Noreturn'

﹥>﹥吖頭↗ 提交于 2019-12-10 17:27:56

问题


I am trying to compile a piece of code that contains _Noreturn:

#ifndef SOMEHEADER_H
#define SOMEHEADER_H

#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

extern struct s {

    _Noreturn void (*somenoreturnfunc)(bool);
} svar;

#endif

Which gives me:

error: expected specifier-qualifier-list before '_Noreturn' on: _Noreturn void (*somenoreturnfunc)(bool);

So I tried the suggestion from here:

#ifndef SOMEHEADER_H
#define SOMEHEADER_H

#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

#include "noreturn.h"

extern struct s {

    noreturn void (*somenoreturnfunc)(bool);
} svar;

#endif

noreturn.h:

#ifndef NO_RETURN_H
#define NO_RETURN_H
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define noreturn _Noreturn
#elif defined(__GNUC__)
#define noreturn __attribute__((noreturn))
#else
#define noreturn
#endif
#endif

But the error still happens:

In file included from ../include/someinclude.h:8:0,
                 from src/main.c:17:
../include/noreturn.h:4:18: error: expected specifier-qualifier-list before '_Noreturn'
 #define noreturn _Noreturn
                  ^
../include/someinclude.h:19:5: note: in expansion of macro 'noreturn'
     noreturn void (*somenoreturnfunc)(bool);
     ^

I am baffled because it is compiled with c11 so it should work:

make V=1
cc src/main.c
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -std=c11 -Wall -pedantic -ffreestanding -static -I../libopencm3/include -I../include -DSTM32F1 -g -DDEBUG -DBUILD_STYLE=\"DEBUG\" -O0 -Iinclude -I../librt/include  -MMD -MT build/main.o -MF build/main.d -o build/main.o -c src/main.c
In file included...

GCC version is 5.4.1:

arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:5.4.1+svn241155-1) 5.4.1 20160919
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

which should support all C11 features (_Noreturn is supported since 4.7).

What am I doing wrong and how could I resolve this error?

--
Edit: Maybe a self contained example can help:

main.c:

#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>

struct s {

    _Noreturn void (*somenoreturnfunc)(bool);
} svar;

int main()
{
        svar.somenoreturnfunc = 0;
        return 0;
}

Compiling this:

arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -std=c11 -Wall -pedantic -ffreestanding -static -DSTM32F1 -g -DDEBUG -DBUILD_STYLE=\"DEBUG\" -O0 -MMD -MT main.o -MF main.d -o main.o -c main.c
main.c:7:5: error: expected specifier-qualifier-list before '_Noreturn'
     _Noreturn void (*somenoreturnfunc)(bool);
     ^
main.c:5:8: warning: struct has no members [-Wpedantic]
 struct s {
        ^
main.c: In function 'main':
main.c:12:6: error: 'struct s' has no member named 'somenoreturnfunc'
  svar.somenoreturnfunc = 0;
      ^

Yet when compiling with the same command line and removing _Noreturn the compilation succeeds.

This also happens when compiling with gcc -std=c11 -o main main.c:

$ gcc -std=c11 -o main main.c
main.c:7:5: error: expected specifier-qualifier-list before ‘_Noreturn’
     _Noreturn void (*somenoreturnfunc)(bool);
     ^~~~~~~~~
main.c: In function ‘main’:
main.c:12:6: error: ‘struct s’ has no member named ‘somenoreturnfunc’
  svar.somenoreturnfunc = 0;
      ^
$ gcc --version
gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

回答1:


In ISO C, _Noreturn cannot be used on the declaration of a function pointer. It can only be used on the declaration of a function. (Ref: C11 6.7.4/2).

You will have to abandon this idea. The function specifiers (inline and _Noreturn) are not part of a function's type.

There is another problem in your code: you define svar in the header, this will cause an ODR violation if the header is included in two or more translation units. It should only have a declaration in the header, and a definition in one unit.


To call through the function pointer and retain _Noreturn semantics , perhaps you could make a shim, e.g.:

inline _Noreturn void call_somefunc( struct s *ps, bool b )
{
    ps->somenoreturnfunc(b);
}

but there is no way to have the compiler enforce that when you assign to the function pointer, it is actually a _Noreturn function.




回答2:


The function specifiers _Noreturn and inline are not part of the type of a function, they are part of the declaration. And the C17 standard states in 6.7.4 that function specifiers "shall be used only in the declaration of an identifier for a function." This means they cannot be used in the in the declaration of a pointer to a function.

So unfortunately this is not possible; a typedef won't help either.




回答3:


Many good answers already, but for clarity I would like to ad the following:

From C11, 6.7.4.9:

The implementation should produce a diagnostic message for a function declared with a _Noreturn function specifier that appears to be capable of returning to its caller.

So _Noreturn has the purpose of informing the compiler to check there is no control path in the function declared as _Noreturn where it actually returns.

Knowing this, it is now clear why you cannot declare a function pointer to be _Noreturn because the compiler cannot check the return semantics of the function assigned.

(Of course, a compiler could see _Noreturn as part of the type and then check that only _Noreturn functions are assigned to the function pointer. The current definition in the standard seems a bit useless to me.)



来源:https://stackoverflow.com/questions/51746897/noreturn-in-a-struct-in-c-error-expected-specifier-qualifier-list-before-no

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!