Currently it is not possible to use an enum value (or const int in C++) as an attribute argument (where compiler wants INTEGER_CST). This is because the values are represented by CONST_DECL nodes -- and we don't deal with them. I think it's viable to accept them too, and that is what this patch does along with some clean ups.
Regtested/bootstrapped on x86_64-linux, ok for trunk? 2014-04-14 Marek Polacek <pola...@redhat.com> PR c/50459 c-family/ * c-common.c (get_attrib_value): New function. (get_priority): Call get_attrib_value. (check_user_alignment): Likewise. (handle_alloc_size_attribute): Likewise. (handle_alloc_align_attribute): Likewise. (handle_assume_aligned_attribute): Likewise. (handle_vector_size_attribute): Likewise. (handle_sentinel_attribute): Likewise. testsuite/ * c-c++-common/pr50459.c: New test. * g++.dg/ext/pr50459.C: New test. diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c index 1d56bc0..3c66d49 100644 --- gcc/c-family/c-common.c +++ gcc/c-family/c-common.c @@ -6448,6 +6448,26 @@ attribute_takes_identifier_p (const_tree attr_id) return targetm.attribute_takes_identifier_p (attr_id); } +/* Perform default promotions or extract the integer constant from + an enum value. This function is used for getting a value from + an attribute argument. */ + +static tree +get_attrib_value (tree val) +{ + if (val + && TREE_CODE (val) != IDENTIFIER_NODE + && TREE_CODE (val) != FUNCTION_DECL) + val = default_conversion (val); + else if (TREE_CODE (val) == IDENTIFIER_NODE) + { + tree t = lookup_name (val); + if (t && TREE_CODE (t) == CONST_DECL) + return DECL_INITIAL (t); + } + return val; +} + /* Attribute handlers common to C front ends. */ /* Handle a "packed" attribute; arguments as in @@ -7030,11 +7050,10 @@ get_priority (tree args, bool is_destructor) } arg = TREE_VALUE (args); - if (TREE_CODE (arg) == IDENTIFIER_NODE) - goto invalid; if (arg == error_mark_node) return DEFAULT_INIT_PRIORITY; - arg = default_conversion (arg); + arg = get_attrib_value (arg); + if (!tree_fits_shwi_p (arg) || !INTEGRAL_TYPE_P (TREE_TYPE (arg))) goto invalid; @@ -7418,6 +7437,8 @@ check_user_alignment (const_tree align, bool allow_zero) { int i; + align = get_attrib_value (CONST_CAST_TREE (align)); + if (TREE_CODE (align) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (align))) { @@ -8037,11 +8058,7 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args, unsigned arg_count = type_num_arguments (*node); for (; args; args = TREE_CHAIN (args)) { - tree position = TREE_VALUE (args); - if (position && TREE_CODE (position) != IDENTIFIER_NODE - && TREE_CODE (position) != FUNCTION_DECL) - position = default_conversion (position); - + tree position = get_attrib_value (TREE_VALUE (args)); if (!tree_fits_uhwi_p (position) || !arg_count || !IN_RANGE (tree_to_uhwi (position), 1, arg_count)) @@ -8063,10 +8080,7 @@ handle_alloc_align_attribute (tree *node, tree, tree args, int, bool *no_add_attrs) { unsigned arg_count = type_num_arguments (*node); - tree position = TREE_VALUE (args); - if (position && TREE_CODE (position) != IDENTIFIER_NODE) - position = default_conversion (position); - + tree position = get_attrib_value (TREE_VALUE (args)); if (!tree_fits_uhwi_p (position) || !arg_count || !IN_RANGE (tree_to_uhwi (position), 1, arg_count)) @@ -8088,11 +8102,7 @@ handle_assume_aligned_attribute (tree *, tree, tree args, int, { for (; args; args = TREE_CHAIN (args)) { - tree position = TREE_VALUE (args); - if (position && TREE_CODE (position) != IDENTIFIER_NODE - && TREE_CODE (position) != FUNCTION_DECL) - position = default_conversion (position); - + tree position = get_attrib_value (TREE_VALUE (args)); if (TREE_CODE (position) != INTEGER_CST) { warning (OPT_Wattributes, @@ -8532,10 +8542,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args, *no_add_attrs = true; - size = TREE_VALUE (args); - if (size && TREE_CODE (size) != IDENTIFIER_NODE) - size = default_conversion (size); - + size = get_attrib_value (TREE_VALUE (args)); if (!tree_fits_uhwi_p (size)) { warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -8943,8 +8950,7 @@ handle_sentinel_attribute (tree *node, tree name, tree args, if (args) { - tree position = TREE_VALUE (args); - + tree position = get_attrib_value (TREE_VALUE (args)); if (TREE_CODE (position) != INTEGER_CST) { warning (OPT_Wattributes, diff --git gcc/testsuite/c-c++-common/pr50459.c gcc/testsuite/c-c++-common/pr50459.c index e69de29..f837b63 100644 --- gcc/testsuite/c-c++-common/pr50459.c +++ gcc/testsuite/c-c++-common/pr50459.c @@ -0,0 +1,14 @@ +/* PR c/50459 */ +/* { dg-do compile } */ +/* { dg-options "-Wall -Wextra" } */ + +enum { A = 128, B = 1 }; +void *fn1 (void) __attribute__((assume_aligned (A))); +void *fn2 (void) __attribute__((assume_aligned (A, 4))); +void fn3 (void) __attribute__((constructor (A))); +void fn4 (void) __attribute__((destructor (A))); +void *fn5 (int) __attribute__((alloc_size (B))); +void *fn6 (int) __attribute__((alloc_align (B))); +void fn7 (const char *, ...) __attribute__ ((sentinel (B))); +int __attribute__((vector_size (A))) a; +int __attribute__((aligned (A))) foo; diff --git gcc/testsuite/g++.dg/ext/pr50459.C gcc/testsuite/g++.dg/ext/pr50459.C index e69de29..8acc299 100644 --- gcc/testsuite/g++.dg/ext/pr50459.C +++ gcc/testsuite/g++.dg/ext/pr50459.C @@ -0,0 +1,14 @@ +// PR c/50459 +// { dg-do compile } +// { dg-options "-Wall -Wextra" } + +const int A = 128, B = 1; +void *fn1 (void) __attribute__((assume_aligned (A))); +void *fn2 (void) __attribute__((assume_aligned (A, 4))); +void fn3 (void) __attribute__((constructor (A))); +void fn4 (void) __attribute__((destructor (A))); +void *fn5 (int) __attribute__((alloc_size (B))); +void *fn6 (int) __attribute__((alloc_align (B))); +void fn7 (const char *, ...) __attribute__ ((sentinel (B))); +int __attribute__((vector_size (A))) a; +int __attribute__((aligned (A))) foo; Marek