Questions about ctor/dtor attribute related diagnostics

Hi,

I noticed that there are some diagnostics discrepancies between clang and gcc related to __attribute__((constructor(n))) and __attribute__((destructor(n))).

[clang]

It seems priorities >65535 and <0 on ctor/dtor functions are ignored and are set back to default 65535 in clang and Clang only gives an error when > 32-bit unsigned value specified.

[g++]
g++ gives an error for any values <0 and >65535.

I am wondering should we let Clang’s diagnostics match g++ to make things clearer to the user? Or why Clang emits an error for >32-bit unsigned value only?

Thank you,
Xiangling

ping.

Hi,

I noticed that there are some diagnostics discrepancies between clang and gcc related to `__attribute__((constructor(n)))` and `__attribute__((destructor(n)))`.

[clang]
It seems priorities >65535 and <0 on ctor/dtor functions are ignored and are set back to default 65535 in clang and Clang only gives an error when > 32-bit unsigned value specified.

[g++]
g++ gives an error for any values <0 and >65535.

I am wondering should we let Clang's diagnostics match g++ to make things clearer to the user? Or why Clang emits an error for >32-bit unsigned value only?

The code for this lives in SemaDeclAttr.cpp in
`handleConstructorAttr()` and `handleDestructorAttr()`, both of which
are defined similarly as trying to read the attribute argument as an
unsigned 32-bit value. If the value is outside of the range of a
32-bit unsigned number, the `checkUInt32Argument()` helper function
will diagnose it as an error. We don't have any further range checking
happening for the argument, though.

I think it's reasonable for us to match GCC's behavior with
diagnostics here. You could model the check after what is done in
`handleInitPriorityAttr()` which has to do a similar range check.
However, you should also verify whether values < 0 or > 65535 are
reserved to the implementation itself (perhaps are used as part of
system headers like glibc) as they are with `init_priority` values <
101 or > 65535. The `init_priority` attribute shows how to exclude
system headers from the range check if that's needed.

~Aaron

>
> Hi,
>
> I noticed that there are some diagnostics discrepancies between clang and gcc related to `__attribute__((constructor(n)))` and `__attribute__((destructor(n)))`.
>
> [clang]
> It seems priorities >65535 and <0 on ctor/dtor functions are ignored and are set back to default 65535 in clang and Clang only gives an error when > 32-bit unsigned value specified.
>
> [g++]
> g++ gives an error for any values <0 and >65535.
>
> I am wondering should we let Clang's diagnostics match g++ to make things clearer to the user? Or why Clang emits an error for >32-bit unsigned value only?

The code for this lives in SemaDeclAttr.cpp in
`handleConstructorAttr()` and `handleDestructorAttr()`, both of which
are defined similarly as trying to read the attribute argument as an
unsigned 32-bit value. If the value is outside of the range of a
32-bit unsigned number, the `checkUInt32Argument()` helper function
will diagnose it as an error. We don't have any further range checking
happening for the argument, though.

I think it's reasonable for us to match GCC's behavior with
diagnostics here. You could model the check after what is done in
`handleInitPriorityAttr()` which has to do a similar range check.
However, you should also verify whether values < 0 or > 65535 are
reserved to the implementation itself (perhaps are used as part of
system headers like glibc) as they are with `init_priority` values <
101 or > 65535. The `init_priority` attribute shows how to exclude
system headers from the range check if that's needed.

~Aaron

Supplement: the range [0,100] is reserved for use by system runtime
libraries and will be warned by -Wprio-ctor-dtor (unimplemented in
Clang).

I added #pragma GCC diagnostic ignored "-Wprio-ctor-dtor" for exactly
this diagnostic in compiler-rt/lib/profile/GCDAProfiling.c