On Mon, Feb 15, 2016 at 11:11:54PM +0000, Joseph Myers wrote: > On Sat, 13 Feb 2016, Stuart Brady wrote: > > > So in other words, adapting all of the sizeof tests would be appropriate, > > and sizeof tests for non-array types would change from expected passes to > > expected failures? > > It's not very clear what's a sizeof test, but all that are testing sizeof > (as opposed to incidentally using it) and applicable to this keyword, yes.
Okay. I will go through all of the gcc.dg tests that mention sizeof and provide an opinion as to whether I think a corresponding __array_size test would be needed, then. > > > Is the rule for your keyword that the operand is evaluated, and the > > > result not an integer constant, iff the operand is an array with a > > > variable number of elements (as opposed to an array with a constant > > > number of elements that themselves are variable-sized, for example)? > > > > If I've understood correctly, then yes: > > > > #include <stdio.h> > > void foo(int i) { > > int a[i], b[__array_size(a)]; > > printf("%zi, %zi\n", __array_size(a), __array_size(b)); > > }; > > int main() { foo(42); } > > That test doesn't relate to my question, which is about when arguments are > evaluated and when results are or are not integer constant expressions. Ah, I think I understand, now. > For whether arguments are evaluated, you need __array_size with arguments > that have side effects, and then test whether those side effects occurred. > For whether results are integer constant expressions, you can test e.g. > whether __array_size (a) - __array_size (a) is accepted in a context > requiring a pointer (whether it acts as a valid null pointer constant). With my patch, void *p = __array_size(a) - __array_size(a) sets p to be null. That behaviour seems desirable to me. I will look into this in some more depth and get back to you, but my thinking is that the requirement should be for any implementation defined behaviour relating to sizeof to have equivalent behaviour for __array_size(). This means that in situations where sizeof(expr) / sizeof(*(expr)) would have side-effects, __array_size(expr) would cause those side-effects to occur only once. My view is that __array_size should result in an integer constant expression iff sizeof would do so, and that __array_size should evaluate its operand with side-effects iff sizeof would do so. This is purely in accordance with the principle of least surprise. I would welcome any discussion as to whether some alternative behaviour might be preferred. > > > C11 6.5.3.4#2 (sizeof) would need testing, > > > > Does this section differ from the September 7th draft in any way? > > I don't know. I now see that this draft really was rather old. I can now refer to N1570 (April 12, 2011) and will use that, instead. Apologies for the noise, there -- I will redo my list of amendments to the draft using N1570 instead. > > > Presumably this keyword can be applied to an array at function prototype > > > scope whose size is explicitly or implicitly [*], though nothing useful > > > can be done with the results, as with [*]? (Cf. gcc.dg/vla-5.c.) > > > > I'm not sure I quite understand the meaning of an implicit [*]. Does that > > just mean __array_size(foo) with an int foo[*] as another parameter? > > Implicit [*] is e.g. > > void f (int a, int (*b)[a], int (*c)[__array_size (*b)]); > > where the VLA *b is at function prototype scope and so gets treated as [*] > - and then __array_size (*) effectively means "an indeterminate value of > type size_t" (but since that value only ever gets used in ways that end up > with it being discarded, possibly through another implicit conversion to > [*] as here, manipulating such indeterminate values is never a problem). Yes, I can see no reason for this to differ in this regard to sizeof, and I will make sure that I include this in my tests. Unfortunately, I do find that TYPE_MAX_VALUE (TYPE_DOMAIN (type)) is unset in that scope so your example results in a compilation failure. I imagine this is possibly as it would get treated as [*] as you say. TYPE_SIZE_UNIT is set, which is why this works when using sizeof. However, I will follow your advice, and try not to focus too much on the implementation just yet, but will instead assume we can deal with this at a later stage. -- Thanks, Stuart Brady