On 10 Mar 2025, at 18:30, Martin Uecker wrote: > Am Montag, dem 10.03.2025 um 16:45 -0400 schrieb John McCall: >>> On 10 Mar 2025, at 15:34, Martin Uecker wrote: >>>>> Am Montag, dem 10.03.2025 um 15:00 -0400 schrieb John McCall: >>>>>>> That said, my preference is still to just give preference to the field >>>>>>> name, >>>>>>> which sidesteps any need for disambiguation syntax and avoids this whole >>>>>>> problem where structs can be broken by just adding a global variable >>>>>>> that >>>>>>> happens to collide with a field. >>>>> >>>>> I don't think it is a good idea when the 'n' in 'buf' refers to the >>>>> previous global 'n' coming before and the 'n' in attribute >>>>> refers to a member 'n' coming later in the following example. >>> >>> I agree. I think compilers ought to diagnose this with a warning, and >>> arguably it should be invalid under the standard. > > The problem is that you want to introduce new rules > that work differently that what the language currently says. > A new warning could mitigate the damage, but wouldn't it be > better to do something which is unambigous from the > beginning? > > ... >>> >>> Fortunately, this sort of thing is largely theoretical in actual code >>> today. Unfortunately, it is not even slightly theoretical with >>> bounds-safety attributes. >>> >>>>> And neither global names nor struct members may always be under >>>>> the control of the programmer. >>> >>> A programmer adding an attribute to a struct field can certainly >>> declare a new global constant immediately before the struct. > >>> >>>>> Also that simply bringing >>>>> a new identifier into scope can break code elsewhere worries me. >>> >>> Yes, but this is only a problem if we diagnose an ambiguity. There is >>> no such problem with just preferring a struct field, unless you’re >>> equally concerned about shadowing whenever you create a local >>> variable. > > So do you want a warning or not? > >>> >>>>> Finally, the following does not even compile in C++. >>>>> >>>>> struct foo { >>>>> char buf[n]; >>>>> const static int n = 2; >>>>> }; >>> >>> And I am not suggesting that it should. Anything that would change >>> the type of a declaration really has to continue to be processed >>> immediately. But code being invalid does not create inconsistency. >>> Non-constant array bounds are invalid in structs, but that is not >>> inconsistent, it’s a limitation in expressivity. What’s important >>> is that code be consistently interpreted everywhere it is valid. > > What is important is not to confuse the programmer with > inconsistent rules. > >>> >>>>> While the next example is also ok in C++. >>>>> >>>>> constexpr int n = 2; >>>>> >>>>> struct foo { >>>>> char buf[n]; >>>>> }; >>>>> >>>>> With both declarations of 'n' the example has UB in C++. >>>>> So I am not convinced the proposed rules make a lot >>>>> of sense for C++ either. >>> >>> If C required a diagnostic in your first example, it would actually >>> put a fair amount of pressure on the C++ committee to get rid of >>> this spurious UB rule. > > Why would C want a diagnostic here?
When I said “your first example”, Martin, I did actually mean your first example: struct foo { char *p [[gnu::counted_by(n)]]; char buf[n]; int n; }; But I think it’s clear that you and I just differ on some basic design philosophy, so let’s just end the conversation here. John. >>>>> I still think one could use designator syntax, i.e. '.n', which >>>>> would be clearer and intuitive for both C and C++ programmers. >>> >>> This doesn’t really solve the ambiguity problem. If n is a field name, >>> a programmer who writes __counted_by(n) almost certainly means to name >>> the field. “The proper syntax is .n” is the cause of the bug, not its >>> solution. > > Field names in C are in a different namespace. So far, when you write > 'n' this *never* refers to field member in any context. And I have > never seen anybody request a warning for the examples above. So, no, > "a programmer almost certainly means this" can not possible be true. > > Martin