Ok so C23 adds function attributes to the language but I'm not sure if anyone actually considered how they are supposed to be used. Consider this example:
[[deprecated]] int foo () { return 0; }
[[nodiscard]] int bar () { return 0; }
int main()
{
typedef int foo_t ();
foo_t* fp1;
foo_t* fp2;
foo_t* fp3;
fp1 = foo;
fp2 = fp1;
fp3 = bar;
fp1();
fp2();
fp3();
}
Some things of note here:
- It is not possible for me to specify an attribute in the
typedef
because apparently attributes are not attached to the type. - The only warning I get in gcc or clang for this entire program is during
fp1 = foo;
assignment.foo
is deprecated. - I do not get a warning when assigning fp1 to fp2.
- I do not get a warning when calling a deprecated function through
fp1
orfp2
. - I do not get a warning when calling
fp3
but ignore/discard the result.
Furthermore, there appears to be no check between function declarations and definitions. This compiles cleanly:
[[unsequenced]] int foo ();
[[nodiscard]] int foo ();
[[deprecated]] int foo () { return 0; }
Why would I ever want a compiler to allow such nonsense?
Function attributes are not attached to the type, so how can we get "function attribute correctness" and making them work as intended? Or are they just plain underspecified/broken, added to the language at a whim, to be fixed at a later point when someone can be bothered to actually examine the consequences of them?
Am I missing something here?
_Noreturn
keyword.__attribute__((deprecated)) foo_t* fp1;
and__attribute__((warn_unused_result)) foo_t *fp3;
deprecated
attribute can later be redeclared with the attribute and vice versa. An entity is considered marked with the attribute after the first declaration that marks it” and there is similar text for some other attributes (I did not check them). So this (a) appears intentional and (b) can be specified by the standard independently for each attribute. One use of it would be that a programmer wishes to be warned…fp1
. The specification fordeprecated
is such that no program that refers to a deprecated function will compile without a diagnostic (when the compiler follows recommended practice). The lack of a warning for ignoring anodiscard
result is more troubling, as there bad code can escape warning.