Some of my testing exposed a minor problem in GCC 9's validation of the type of function parameters referred to by attribute positional arguments. Whereas GCC 8 accepts all C integer types, including enumerated types, such as:
enum AllocAlign { Align16 = 16, Align32 = 32 }; __attribute__ ((alloc_align (1))) void* alloc (size_t, enum AllocAlign) GCC 9 only accepts signed and unsigned integer types. This change (introduced by myself) was unintentional, and a fix for it is in the attached trivial patch. I plan to commit it without approval in the next day or so unless any concerns or suggestions come up. Tested on x86_64-linux. Martin
PR c/88363 - alloc_align attribute doesn't accept enumerated arguments gcc/c-family/ChangeLog: PR c/88363 * c-attribs.c (positional_argument): Also accept enumerated types. gcc/testsuite/ChangeLog: PR c/88363 * c-c++-common/attributes-4.c: New test. gcc/ChangeLog: PR c/88363 * doc/extend.texi (attribute alloc_align, alloc_size): Update. Index: gcc/c-family/c-attribs.c =================================================================== --- gcc/c-family/c-attribs.c (revision 266963) +++ gcc/c-family/c-attribs.c (working copy) @@ -630,11 +630,11 @@ positional_argument (const_tree fntype, const_tree return NULL_TREE; } - /* Where the expected code is STRING_CST accept any pointer - to a narrow character type, qualified or otherwise. */ bool type_match; if (code == STRING_CST && POINTER_TYPE_P (argtype)) { + /* Where the expected code is STRING_CST accept any pointer + to a narrow character type, qualified or otherwise. */ tree type = TREE_TYPE (argtype); type = TYPE_MAIN_VARIANT (type); type_match = (type == char_type_node @@ -641,6 +641,10 @@ positional_argument (const_tree fntype, const_tree || type == signed_char_type_node || type == unsigned_char_type_node); } + else if (code == INTEGER_TYPE) + /* For integers, accept bool, enums, and other types that + match INTEGRAL_TYPE_P. */ + type_match = INTEGRAL_TYPE_P (argtype); else type_match = TREE_CODE (argtype) == code; Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 266963) +++ gcc/doc/extend.texi (working copy) @@ -2471,7 +2471,8 @@ The @code{aligned} attribute can also be used for @item alloc_align (@var{position}) @cindex @code{alloc_align} function attribute The @code{alloc_align} attribute may be applied to a function that -returns a pointer and takes at least one argument of an integer type. +returns a pointer and takes at least one argument of an integer or +enumerated type. It indicates that the returned pointer is aligned on a boundary given by the function argument at @var{position}. Meaningful alignments are powers of 2 greater than one. GCC uses this information to improve @@ -2495,7 +2496,8 @@ given by parameter 1. @itemx alloc_size (@var{position-1}, @var{position-2}) @cindex @code{alloc_size} function attribute The @code{alloc_size} attribute may be applied to a function that -returns a pointer and takes at least one argument of an integer type. +returns a pointer and takes at least one argument of an integer or +enumerated type. It indicates that the returned pointer points to memory whose size is given by the function argument at @var{position-1}, or by the product of the arguments at @var{position-1} and @var{position-2}. Meaningful Index: gcc/testsuite/c-c++-common/attributes-4.c =================================================================== --- gcc/testsuite/c-c++-common/attributes-4.c (nonexistent) +++ gcc/testsuite/c-c++-common/attributes-4.c (working copy) @@ -0,0 +1,46 @@ +/* PR c/88363 - alloc_align attribute doesn't accept enumerated arguments + Verify that attribute positional arguments can refer to all C integer + types in both C and C++. + { dg-do compile } + { dg-options "-Wall" } + { dg-options "-Wall -Wno-c++-compat" { target c } } */ + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) + +#if __cplusplus == 199711L +typedef __CHAR16_TYPE__ char16_t; +typedef __CHAR32_TYPE__ char32_t; +#elif !__cplusplus +typedef _Bool bool; +typedef __CHAR16_TYPE__ char16_t; +typedef __CHAR32_TYPE__ char32_t; +typedef __WCHAR_TYPE__ wchar_t; +#endif + +enum A { A0 }; + +/* Using bool here is of marginal utility but it's accepted nonetheless. */ +ATTR (alloc_align (1)) void* falloc_align_bool (bool); +ATTR (alloc_align (1)) void* falloc_align_char (char); +ATTR (alloc_align (1)) void* falloc_align_char16 (char16_t); +ATTR (alloc_align (1)) void* falloc_align_char32 (char32_t); +ATTR (alloc_align (1)) void* falloc_align_wchar (wchar_t); +/* Using an enum might make sense in an API that limits the alignments + it accepts to just the set of the defined enumerators. */ +ATTR (alloc_align (1)) void* falloc_align_enum (enum A); +ATTR (alloc_align (1)) void* falloc_align_int128 (__int128_t); + +ATTR (alloc_size (1)) void* falloc_size_bool (bool); +ATTR (alloc_align (1)) void* falloc_size_char (char); +ATTR (alloc_size (1)) void* falloc_size_char16 (char16_t); +ATTR (alloc_size (1)) void* falloc_size_char32 (char32_t); +ATTR (alloc_size (1)) void* falloc_size_wchar (wchar_t); +ATTR (alloc_size (1)) void* falloc_size_enum (enum A); +ATTR (alloc_align (1)) void* falloc_size_int128 (__int128_t); + + +typedef struct { int i; } S; + +ATTR (alloc_align (1)) void* falloc_align_float (float); /* { dg-warning "attribute argument value .1. refers to parameter type .float" } */ +ATTR (alloc_align (1)) void* falloc_align_voidp (void*); /* { dg-warning "attribute argument value .1. refers to parameter type .void ?\\\*" } */ +ATTR (alloc_align (1)) void* falloc_align_struct (S); /* { dg-warning "attribute argument value .1. refers to parameter type .S" } */