llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.65k stars 11.84k forks source link

Clang doesn't equate __attribute__((noreturn)) and [[noreturn]] #113511

Open aoates opened 4 hours ago

aoates commented 4 hours ago

When __attribute__((noreturn)) is set on a function pointer, a function marked [[noreturn]] cannot be assigned to it.

Original context on gdb-patches mailing list (https://sourceware.org/pipermail/gdb-patches/2024-October/212507.html)

Example:

typedef __attribute__((noreturn)) void (*noreturn_ptr)(void);

__attribute__((noreturn)) void function_attr1(void);
[[noreturn]] void function_attr2(void);
void function_noattr(void);

void test(void) {
  noreturn_ptr fptr[3];

  fptr[0] = &function_attr1;   // OK
  fptr[1] = &function_attr2;   // Should be OK?  But is error.
  fptr[2] = &function_noattr;  // Error
}

Compiling:

$ clang -c -o /dev/null noreturn_test.c
noreturn_test.c:11:11: error: incompatible function pointer types assigning to 'noreturn_ptr' (aka 'void (*)(void) __attribute__((noreturn))') from 'void (*)(void)' [-Wincompatible-function-pointer-types]
   11 |   fptr[1] = &function_attr2;   // Should be OK?  But is error.
      |           ^ ~~~~~~~~~~~~~~~
noreturn_test.c:12:11: error: incompatible function pointer types assigning to 'noreturn_ptr' (aka 'void (*)(void) __attribute__((noreturn))') from 'void (*)(void)' [-Wincompatible-function-pointer-types]
   12 |   fptr[2] = &function_noattr;  // Error
      |           ^ ~~~~~~~~~~~~~~~~
2 errors generated.

This seems incorrect --- clang should treat function_attr2 the same as function_attr1. As a point of reference, GCC does this (it allows the assignment in the second line).

llvmbot commented 4 hours ago

@llvm/issue-subscribers-clang-frontend

Author: None (aoates)

When `__attribute__((noreturn))` is set on a function pointer, a function marked `[[noreturn]]` cannot be assigned to it. Original context on gdb-patches mailing list (https://sourceware.org/pipermail/gdb-patches/2024-October/212507.html) Example: ``` typedef __attribute__((noreturn)) void (*noreturn_ptr)(void); __attribute__((noreturn)) void function_attr1(void); [[noreturn]] void function_attr2(void); void function_noattr(void); void test(void) { noreturn_ptr fptr[3]; fptr[0] = &function_attr1; // OK fptr[1] = &function_attr2; // Should be OK? But is error. fptr[2] = &function_noattr; // Error } ``` Compiling: ``` $ clang -c -o /dev/null noreturn_test.c noreturn_test.c:11:11: error: incompatible function pointer types assigning to 'noreturn_ptr' (aka 'void (*)(void) __attribute__((noreturn))') from 'void (*)(void)' [-Wincompatible-function-pointer-types] 11 | fptr[1] = &function_attr2; // Should be OK? But is error. | ^ ~~~~~~~~~~~~~~~ noreturn_test.c:12:11: error: incompatible function pointer types assigning to 'noreturn_ptr' (aka 'void (*)(void) __attribute__((noreturn))') from 'void (*)(void)' [-Wincompatible-function-pointer-types] 12 | fptr[2] = &function_noattr; // Error | ^ ~~~~~~~~~~~~~~~~ 2 errors generated. ``` This seems incorrect --- clang should treat `function_attr2` the same as `function_attr1`. As a point of reference, GCC does this (it allows the assignment in the second line).
shafik commented 4 hours ago

CC @erichkeane