Message ID | alpine.DEB.2.02.1401182314190.23143@stedding.saclay.inria.fr |
---|---|
State | New |
Headers | show |
Ping http://gcc.gnu.org/ml/gcc-patches/2014-01/msg01168.html (conversation starts at http://gcc.gnu.org/ml/gcc-patches/2013-11/msg03822.html ) On Sat, 18 Jan 2014, Marc Glisse wrote: > On Thu, 2 Jan 2014, Jason Merrill wrote: > >> On 11/30/2013 05:41 AM, Marc Glisse wrote: >>> for some reason one of the attributes can see a FUNCTION_DECL where others >>> see an IDENTIFIER_NODE, I didn't try to understand why and just added that >>> check to the code. >> >> Please do check. > > In the C front-end (at least), the grammar says: > > attrib: > empty > any-word > any-word ( identifier ) > any-word ( identifier , nonempty-expr-list ) > any-word ( expr-list ) > > So when we have: __attribute__((nonnull(bar,bar))) > the parser will keep bar as an identifier for the first argument, but parse > the second one as an expr-list and thus find the associated function_decl. So > this can happen anytime an attribute has several arguments, and I added the > same check to nonnull that I had for alloc_size (and fixed the argument > numbering while I was there). > >>> + if (size && size != error_mark_node && TREE_CODE (size) != >>> IDENTIFIER_NODE) >> >> Why is the error_mark_node check needed here and not in the other places? > > Don't know, I removed it for now. If it is needed, someone will eventually > provide a testcase in bugzilla. > > > Bootstrap and testsuite on x86_64-linux-gnu with > --enable-languages=c,c++,objc,obj-c++. > > 2014-01-19 Marc Glisse <marc.glisse@inria.fr> > > PR c++/53017 > PR c++/59211 > gcc/c-family/ > * c-common.c (handle_aligned_attribute, handle_alloc_size_attribute, > handle_vector_size_attribute, handle_nonnull_attribute): Call > default_conversion on the attribute argument. > (handle_nonnull_attribute): Increment the argument number. > gcc/cp/ > * tree.c (handle_init_priority_attribute): Likewise. > gcc/ > * doc/extend.texi (Function Attributes): Typo. > gcc/testsuite/ > * c-c++-common/attributes-1.c: New testcase. > * g++.dg/cpp0x/constexpr-attribute2.C: Likewise.
On Sat, 1 Feb 2014, Marc Glisse wrote: > Ping > http://gcc.gnu.org/ml/gcc-patches/2014-01/msg01168.html As I understand it, this is only relevant to C++ (in C you should have an INTEGER_CST here, and if you don't then default_conversion won't give you one), so would best be reviewed by Jason not me.
On Sun, 2 Feb 2014, Joseph S. Myers wrote: > On Sat, 1 Feb 2014, Marc Glisse wrote: > >> Ping >> http://gcc.gnu.org/ml/gcc-patches/2014-01/msg01168.html > > As I understand it, this is only relevant to C++ (in C you should have an > INTEGER_CST here, and if you don't then default_conversion won't give you > one), so would best be reviewed by Jason not me. I agree, I just wanted to make sure you weren't opposed to using default_conversion in C as well and were ok with my explanation of why I was testing FUNCTION_DECL for some attributes (in C++, default_conversion will accept anything, so I am doing that for the sake of C). An alternative could be to have a helper function that does nothing in C and calls default_conversion in C++. Or make the C version of default_conversion return its argument unchanged instead of asserting when it sees an unexpected tree. I'll wait for Jason, thanks.
On Sun, 2 Feb 2014, Marc Glisse wrote: > An alternative could be to have a helper function that does nothing in C and > calls default_conversion in C++. Or make the C version of default_conversion > return its argument unchanged instead of asserting when it sees an unexpected > tree. Well, in principle I'm dubious about the cases where different implementations of functions with the same name are used in c-family code; I'd prefer an actual C/C++ set of langhooks, with clearly defined semantics based on what the c-family users need, where the hook used (c_family_lang_hooks.convert_attribute_argument or whatever) would indeed do nothing for C. But more than just default_conversion is involved there, and default_conversion is already used from c-family code, so this isn't an objection to this patch.
On 01/18/2014 05:33 PM, Marc Glisse wrote: > So when we have: __attribute__((nonnull(bar,bar))) > the parser will keep bar as an identifier for the first argument, but > parse the second one as an expr-list and thus find the associated > function_decl. OK, that makes sense. But why do we need to handle that specially? Isn't that an invalid argument whether or not it decays to a pointer? Jason
On Mon, 3 Feb 2014, Jason Merrill wrote: > On 01/18/2014 05:33 PM, Marc Glisse wrote: >> So when we have: __attribute__((nonnull(bar,bar))) >> the parser will keep bar as an identifier for the first argument, but >> parse the second one as an expr-list and thus find the associated >> function_decl. > > OK, that makes sense. But why do we need to handle that specially? Isn't > that an invalid argument whether or not it decays to a pointer? The C version of default_conversion does not convert a function_decl to a pointer (that's done earlier, during parsing), it ICEs. As you can see for the one attribute that is C++-only, I don't have any protection before calling default_conversion, it is only for the C front-end (for which calling default_conversion is useless anyway, but that's how it is already done in a couple other attributes).
On 02/03/2014 12:46 PM, Marc Glisse wrote: > The C version of default_conversion does not convert a function_decl to > a pointer (that's done earlier, during parsing), it ICEs. Ah, I see. The patch is OK, then. Jason
Marc Glisse <marc.glisse@inria.fr> writes: > Index: gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C > =================================================================== > --- gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (revision 0) > +++ gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (working copy) > @@ -0,0 +1,32 @@ > +// { dg-options -std=gnu++11 } > + > +struct t { t(); }; > + > +constexpr int prio = 123; > +constexpr int size = 8; > +constexpr int pos = 1; > +enum A { zero = 0, one, two }; > +__attribute__((init_priority(prio))) t a; > + > +enum class E1 : int { > + first = 101, > + second, > + third, > +}; > +__attribute__((init_priority(E1::second))) t b; // Should not compile? > + > +enum E2 { > + E2_first = 141, > + E2_second, > + E2_third, > +}; > +__attribute__((init_priority(E2_second))) t c; > + > +void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(pos,two))); > +void* my_realloc(void*, unsigned) __attribute__((alloc_size(two))); > + > +typedef char vec __attribute__((vector_size(size))); > + > +void f(char*) __attribute__((nonnull(pos))); > + > +void g() __attribute__((aligned(size))); /usr/local/gcc/gcc-20140204/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C:32:6: error: alignment for 'void g()' must be at least 16 FAIL: g++.dg/cpp0x/constexpr-attribute2.C (test for excess errors) Andreas.
On Tue, 4 Feb 2014, Andreas Schwab wrote: > Marc Glisse <marc.glisse@inria.fr> writes: > >> Index: gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C >> =================================================================== >> --- gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (revision 0) >> +++ gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (working copy) >> @@ -0,0 +1,32 @@ >> +// { dg-options -std=gnu++11 } >> + >> +struct t { t(); }; >> + >> +constexpr int prio = 123; >> +constexpr int size = 8; >> +constexpr int pos = 1; >> +enum A { zero = 0, one, two }; >> +__attribute__((init_priority(prio))) t a; >> + >> +enum class E1 : int { >> + first = 101, >> + second, >> + third, >> +}; >> +__attribute__((init_priority(E1::second))) t b; // Should not compile? >> + >> +enum E2 { >> + E2_first = 141, >> + E2_second, >> + E2_third, >> +}; >> +__attribute__((init_priority(E2_second))) t c; >> + >> +void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(pos,two))); >> +void* my_realloc(void*, unsigned) __attribute__((alloc_size(two))); >> + >> +typedef char vec __attribute__((vector_size(size))); >> + >> +void f(char*) __attribute__((nonnull(pos))); >> + >> +void g() __attribute__((aligned(size))); > > /usr/local/gcc/gcc-20140204/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C:32:6: error: alignment for 'void g()' must be at least 16 (I don't know why we error out for this, align specifies a minimal alignment, if it ends up more aligned, that's fine) > FAIL: g++.dg/cpp0x/constexpr-attribute2.C (test for excess errors) It would be nice to at least mention the platform in this kind of email. Feel free to replace 8 with 16 in the initialization of size (you can commit it as obvious if it works for you). Thanks,
Marc Glisse <marc.glisse@inria.fr> writes: >> /usr/local/gcc/gcc-20140204/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C:32:6: error: alignment for 'void g()' must be at least 16 > > (I don't know why we error out for this, align specifies a minimal > alignment, if it ends up more aligned, that's fine) Probably because there is no packed attribute for functions, so the alignment is always taken to be exact. > Feel free to replace 8 with 16 in the initialization of size (you can > commit it as obvious if it works for you). Are there any targets that may reject an overaligned function decl? Andreas.
On Wed, Feb 05, 2014 at 09:28:16AM +0100, Andreas Schwab wrote: > > Feel free to replace 8 with 16 in the initialization of size (you can > > commit it as obvious if it works for you). > > Are there any targets that may reject an overaligned function decl? I think that is very well possible. Why not just #ifdef that particular test line to a handful of widely used targets where it is known to work? Jakub
On Wed, 5 Feb 2014, Jakub Jelinek wrote: > On Wed, Feb 05, 2014 at 09:28:16AM +0100, Andreas Schwab wrote: >>> Feel free to replace 8 with 16 in the initialization of size (you can >>> commit it as obvious if it works for you). >> >> Are there any targets that may reject an overaligned function decl? > > I think that is very well possible. Why not just #ifdef that particular > test line to a handful of widely used targets where it is known to work? With Dominique's message that Darwin doesn't support init_priority, would this be ok? That's the most frequently tested platform, some attributes are already tested elsewhere, etc. // { dg-do compile { target x86_64-*linux-gnu } }
On Wed, Feb 05, 2014 at 09:58:28AM +0100, Marc Glisse wrote: > On Wed, 5 Feb 2014, Jakub Jelinek wrote: > > >On Wed, Feb 05, 2014 at 09:28:16AM +0100, Andreas Schwab wrote: > >>>Feel free to replace 8 with 16 in the initialization of size (you can > >>>commit it as obvious if it works for you). > >> > >>Are there any targets that may reject an overaligned function decl? > > > >I think that is very well possible. Why not just #ifdef that particular > >test line to a handful of widely used targets where it is known to work? > > With Dominique's message that Darwin doesn't support init_priority, > would this be ok? That's the most frequently tested platform, some > attributes are already tested elsewhere, etc. > > // { dg-do compile { target x86_64-*linux-gnu } } I'd use i?86-*linux* x86_64-*linux* instead, but otherwise LGTM. Please give others a chance to comment on that though. Jakub
On Wed, 5 Feb 2014, Jakub Jelinek wrote: > On Wed, Feb 05, 2014 at 09:58:28AM +0100, Marc Glisse wrote: >> On Wed, 5 Feb 2014, Jakub Jelinek wrote: >> >>> On Wed, Feb 05, 2014 at 09:28:16AM +0100, Andreas Schwab wrote: >>>>> Feel free to replace 8 with 16 in the initialization of size (you can >>>>> commit it as obvious if it works for you). >>>> >>>> Are there any targets that may reject an overaligned function decl? >>> >>> I think that is very well possible. Why not just #ifdef that particular >>> test line to a handful of widely used targets where it is known to work? >> >> With Dominique's message that Darwin doesn't support init_priority, >> would this be ok? That's the most frequently tested platform, some >> attributes are already tested elsewhere, etc. >> >> // { dg-do compile { target x86_64-*linux-gnu } } > > I'd use i?86-*linux* x86_64-*linux* instead, but otherwise LGTM. I wasn't sure if all libc (not just glibc) used on linux could handle all the attributes, but now you've said it, good :-) > Please give others a chance to comment on that though. I'll give it a day (it can easily be changed again later).
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 206766) +++ gcc/c-family/c-common.c (working copy) @@ -7517,24 +7517,32 @@ check_cxx_fundamental_alignment_constrai /* Handle a "aligned" attribute; arguments as in struct attribute_spec.handler. */ static tree handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, int flags, bool *no_add_attrs) { tree decl = NULL_TREE; tree *type = NULL; int is_type = 0; - tree align_expr = (args ? TREE_VALUE (args) - : size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT)); + tree align_expr; int i; + if (args) + { + align_expr = TREE_VALUE (args); + if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE) + align_expr = default_conversion (align_expr); + } + else + align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT); + if (DECL_P (*node)) { decl = *node; type = &TREE_TYPE (decl); is_type = TREE_CODE (*node) == TYPE_DECL; } else if (TYPE_P (*node)) type = node, is_type = 1; if ((i = check_user_alignment (align_expr, false)) == -1 @@ -8014,20 +8022,23 @@ handle_malloc_attribute (tree *node, tre struct attribute_spec.handler. */ static tree handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args, int ARG_UNUSED (flags), bool *no_add_attrs) { 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); if (TREE_CODE (position) != INTEGER_CST || TREE_INT_CST_HIGH (position) || TREE_INT_CST_LOW (position) < 1 || TREE_INT_CST_LOW (position) > arg_count ) { warning (OPT_Wattributes, "alloc_size parameter outside range"); *no_add_attrs = true; return NULL_TREE; @@ -8458,20 +8469,22 @@ handle_vector_size_attribute (tree *node int ARG_UNUSED (flags), bool *no_add_attrs) { unsigned HOST_WIDE_INT vecsize, nunits; enum machine_mode orig_mode; tree type = *node, new_type, size; *no_add_attrs = true; size = TREE_VALUE (args); + if (size && TREE_CODE (size) != IDENTIFIER_NODE) + size = default_conversion (size); if (!tree_fits_uhwi_p (size)) { warning (OPT_Wattributes, "%qE attribute ignored", name); return NULL_TREE; } /* Get the vector size (in bytes). */ vecsize = tree_to_uhwi (size); @@ -8551,25 +8564,30 @@ handle_nonnull_attribute (tree *node, tr if (!prototype_p (type)) { error ("nonnull attribute without arguments on a non-prototype"); *no_add_attrs = true; } return NULL_TREE; } /* Argument list specified. Verify that each argument number references a pointer argument. */ - for (attr_arg_num = 1; args; args = TREE_CHAIN (args)) + for (attr_arg_num = 1; args; attr_arg_num++, args = TREE_CHAIN (args)) { unsigned HOST_WIDE_INT arg_num = 0, ck_num; - if (!get_nonnull_operand (TREE_VALUE (args), &arg_num)) + tree arg = TREE_VALUE (args); + if (arg && TREE_CODE (arg) != IDENTIFIER_NODE + && TREE_CODE (arg) != FUNCTION_DECL) + arg = default_conversion (arg); + + if (!get_nonnull_operand (arg, &arg_num)) { error ("nonnull argument has invalid operand number (argument %lu)", (unsigned long) attr_arg_num); *no_add_attrs = true; return NULL_TREE; } if (prototype_p (type)) { function_args_iterator iter; Index: gcc/cp/tree.c =================================================================== --- gcc/cp/tree.c (revision 206766) +++ gcc/cp/tree.c (working copy) @@ -3242,20 +3242,21 @@ handle_init_priority_attribute (tree* no tree args, int /*flags*/, bool* no_add_attrs) { tree initp_expr = TREE_VALUE (args); tree decl = *node; tree type = TREE_TYPE (decl); int pri; STRIP_NOPS (initp_expr); + initp_expr = default_conversion (initp_expr); if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST) { error ("requested init_priority is not an integer constant"); *no_add_attrs = true; return NULL_TREE; } pri = TREE_INT_CST_LOW (initp_expr); Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 206766) +++ gcc/doc/extend.texi (working copy) @@ -2234,21 +2234,21 @@ information to improve the correctness o The function parameter(s) denoting the allocated size are specified by one or two integer arguments supplied to the attribute. The allocated size is either the value of the single function argument specified or the product of the two function arguments specified. Argument numbering starts at one. For instance, @smallexample void* my_calloc(size_t, size_t) __attribute__((alloc_size(1,2))) -void my_realloc(void*, size_t) __attribute__((alloc_size(2))) +void* my_realloc(void*, size_t) __attribute__((alloc_size(2))) @end smallexample @noindent declares that @code{my_calloc} returns memory of the size given by the product of parameter 1 and 2 and that @code{my_realloc} returns memory of the size given by parameter 2. @item always_inline @cindex @code{always_inline} function attribute Generally, functions are not inlined unless optimization is specified. Index: gcc/testsuite/c-c++-common/attributes-1.c =================================================================== --- gcc/testsuite/c-c++-common/attributes-1.c (revision 0) +++ gcc/testsuite/c-c++-common/attributes-1.c (working copy) @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-prune-output "undeclared here \\(not in a function\\)|\[^\n\r\]* was not declared in this scope" } */ + +void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(1,bar))); /* { dg-warning "outside range" } */ +void* my_realloc(void*, unsigned) __attribute__((alloc_size(bar))); /* { dg-warning "outside range" } */ + +typedef char vec __attribute__((vector_size(bar))); /* { dg-warning "ignored" } */ + +void f1(char*) __attribute__((nonnull(bar))); /* { dg-error "invalid operand" } */ +void f2(char*) __attribute__((nonnull(1,bar))); /* { dg-error "invalid operand" } */ + +void g() __attribute__((aligned(bar))); /* { dg-error "invalid value|not an integer" } */ + +void foo(void); +void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(1,foo))); /* { dg-warning "outside range" } */ +void* my_realloc(void*, unsigned) __attribute__((alloc_size(foo))); /* { dg-warning "outside range" } */ + +typedef char vec __attribute__((vector_size(foo))); /* { dg-warning "ignored" } */ + +void f1(char*) __attribute__((nonnull(foo))); /* { dg-error "invalid operand" } */ +void f2(char*) __attribute__((nonnull(1,foo))); /* { dg-error "invalid operand" } */ + +void g() __attribute__((aligned(foo))); /* { dg-error "invalid value|not an integer" } */ Property changes on: gcc/testsuite/c-c++-common/attributes-1.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Author Date Id Revision URL \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-attribute2.C (working copy) @@ -0,0 +1,32 @@ +// { dg-options -std=gnu++11 } + +struct t { t(); }; + +constexpr int prio = 123; +constexpr int size = 8; +constexpr int pos = 1; +enum A { zero = 0, one, two }; +__attribute__((init_priority(prio))) t a; + +enum class E1 : int { + first = 101, + second, + third, +}; +__attribute__((init_priority(E1::second))) t b; // Should not compile? + +enum E2 { + E2_first = 141, + E2_second, + E2_third, +}; +__attribute__((init_priority(E2_second))) t c; + +void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(pos,two))); +void* my_realloc(void*, unsigned) __attribute__((alloc_size(two))); + +typedef char vec __attribute__((vector_size(size))); + +void f(char*) __attribute__((nonnull(pos))); + +void g() __attribute__((aligned(size)));