4

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 or fp2.
  • 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?

10
  • 1
    Twelve years too late to complain, since the same can be said of the _Noreturn keyword. Commented Jun 25 at 10:53
  • @StoryTeller-UnslanderMonica Yeah but that was just an oddball feature for manual optimization purposes. The purpose of the new attributes isn't just optimization, but program safety. Supposedly.
    – Lundin
    Commented Jun 25 at 11:04
  • I feel old for agreeing and still using __attribute__((deprecated)) foo_t* fp1; and __attribute__((warn_unused_result)) foo_t *fp3;
    – KamilCuk
    Commented Jun 25 at 11:50
  • 2
    Re “Furthermore, there appears to be no check between function declarations and definitions���: Draft N3096 says “A name or entity declared without the 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… Commented Jun 25 at 14:16
  • 1
    Re “I do not get a warning when assigning fp1 to fp2”: There is no need for that since a warning was already given for referring to a deprecated function when assigning to fp1. The specification for deprecated 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 a nodiscard result is more troubling, as there bad code can escape warning. Commented Jun 25 at 14:20

0

Browse other questions tagged or ask your own question.