https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96516
Bug ID: 96516 Summary: template + __attribute__((copy)) produce compiler errors Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: sagebar at web dot de Target Milestone: --- Created attachment 49016 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49016&action=edit Same code as already seen in the bug description Using `__attribute__((copy(...)))' to inherit an `returns_nonnull' attribute will cause a compiler error if the applied-to function's return type uses a decltype type-expression, or has it's is-pointer-y-ness depend on a template parameter. However, when `returns_nonnull' is not inherited via `copy()', but explicitly used, then everything still works fine, so there appears to be a discrepency between using `copy()' to inherit `returns_nonnull', and specifying `returns_nonnull' directly. ``` __attribute__((returns_nonnull)) void *base(void *); __attribute__((copy(base))) __typeof__((void *)0) wrap1(void *); __attribute__((copy(base))) decltype((void *)0) wrap2(void *); template<class T> __attribute__((copy(base))) T *wrap3(T *); template<class T> __attribute__((copy(base))) decltype(T()) *wrap4(T *); template<class T> __attribute__((returns_nonnull)) decltype((T *)0) wrap5(T *); template<class T> __attribute__((copy(base))) decltype((T *)0) wrap6(T *); template<class T> __attribute__((copy(base))) __typeof__((T *)0) wrap7(T *); template<class T> __attribute__((copy(base))) T wrap8(T); template<class T> __attribute__((returns_nonnull)) T wrap9(T); ``` All of these `wrapN()' functions should work the same, and none of them should produce an error, but `wrap6()', `wrap7()' and `wrap8()' produce errors: `returns_nonnull attribute on a function not returning a pointer' I know that `__attribute__((copy(...)))' is a gcc extension, and this bug only happens with g++, and I also know that it being an extension, it's correct behavior isn't written in stone. But in this example, it's behavior is plainly inconsistent (if `returns_nonnull' wasn't allowed with a template-dependent return expression, then `wrap5()' and `wrap9()' should also cause errors, even though they don't), and as already stated, _all_ of the above should work without issues in my opinion. I've placed this Report under c++ since this bug seems to be specific to the combination of `template' + `__attribute__((copy))', where the template-part is specific to c++. But if I had to guess, this is probably caused by a minor difference in how `copy()' sets the `returns_nonnull' attribute vs. how directly making use of `returns_nonnull' does the same. Note: The same thing also happens with `__attribute((malloc))' and `__attribute((nonnull(...)))' (in the case of `nonnull(...)', it even appears to produce errors for _all_ template-functions that use `copy()' (`wrap5' and `wrap9' continue to work correctly, so this is most definitely a problem with `copy()')) (s.a. the attached `bug.cc`, which is replicated in the following): ``` __attribute__((returns_nonnull, malloc, nonnull(1))) void *base(void *); __attribute__((copy(base))) __typeof__((void *)0) wrap1(decltype((void *)0)); __attribute__((copy(base))) decltype((void *)0) wrap2(decltype((void *)0)); template<class T> __attribute__((copy(base))) T *wrap3(decltype((T *)0)); template<class T> __attribute__((copy(base))) decltype(T()) *wrap4(decltype((T *)0)); template<class T> __attribute__((returns_nonnull, nonnull(1))) decltype((T *)0) wrap5(decltype((T *)0)); template<class T> __attribute__((copy(base))) decltype((T *)0) wrap6(decltype((T *)0)); template<class T> __attribute__((copy(base))) __typeof__((T *)0) wrap7(decltype((T *)0)); template<class T> __attribute__((copy(base))) T wrap8(T); template<class T> __attribute__((returns_nonnull, nonnull(1))) T wrap9(T); ``` The following are the errors produced by the above code. Note that inheriting `__attribute__((malloc))' causes the `returns_nonnull` error to become duplicated for `wrap6()', `wrap7()' and `wrap8()' for some reason (possibly an unrelated bug), and that `wrap5()' and `wrap9()' (i.e. the declarations that don't use `copy()') produces no errors or warnings: ``` [wrap3]: warning: 'nonnull' attribute argument value '1' refers to parameter type 'decltype ((T*)(0))' [-Wattributes] [wrap4]: warning: 'nonnull' attribute argument value '1' refers to parameter type 'decltype ((T*)(0))' [-Wattributes] [wrap6]: warning: 'malloc' attribute ignored [-Wattributes] [wrap6]: warning: 'nonnull' attribute argument value '1' refers to parameter type 'decltype ((T*)(0))' [-Wattributes] [wrap6]: error: returns_nonnull attribute on a function not returning a pointer [wrap6]: error: returns_nonnull attribute on a function not returning a pointer [wrap7]: warning: 'malloc' attribute ignored [-Wattributes] [wrap7]: warning: 'nonnull' attribute argument value '1' refers to parameter type 'decltype ((T*)(0))' [-Wattributes] [wrap7]: error: returns_nonnull attribute on a function not returning a pointer [wrap7]: error: returns_nonnull attribute on a function not returning a pointer [wrap8]: warning: 'malloc' attribute ignored [-Wattributes] [wrap8]: warning: 'nonnull' attribute argument value '1' refers to parameter type 'T' [-Wattributes] [wrap8]: error: returns_nonnull attribute on a function not returning a pointer [wrap8]: error: returns_nonnull attribute on a function not returning a pointer ```