On Mon, Apr 14, 2025 at 1:56 PM Qing Zhao <qing.z...@oracle.com> wrote:
>
> Hi, Bill,
>
> Thanks for your new proposal.
>
> If I understand correctly, this new proposal basically is back to one of our 
> previous proposal:
>
> Adding a new structure scoping for counted_by attribute into C;
>
> With this approach, there is one new structure scoping added to C, and this 
> new scope
> will shadow other scopes in the current  C.
>
> The identifiers inside the counted_by attribute will be looked up within this 
> new structure scope first.
> Conflicted local or global variables need to be prefixed with special builtin 
> to explicitly specify its scope.
>
> Is this understanding correctly?
>
Yes, in a sense. I called it a "pseudo" struct scope, because it's not
fully fleshed out and is limited to very specific instances with very
specific behavior.

> My opinion on this:
>
> 1. Personally, as I mentioned multiple times, I think that this might be the 
> cleanest solution;
>     If other people agree on this, I am happy to go with this.  -:)
>
:-)

> 2. However, my understanding from our previous long discussion is:
>    Adding a new structure scope to C (even it’s only for counted_by 
> attribute) should not be done without
>    Having a clear specification and support from WG14.
>
> Please refer to the following:
>
> https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679922.html.
> https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679923.html.
>
> Martin and Joseph, what’s your opinion on this proposal?
>
I should point out that using the forward declaration syntax could
cause errors with macro expansions. For example,

#define FOO (len + 42)
struct A {
  int *buf __counted_by_expr(size_t len; len << FOO);
  int len;
};

The 'len' from the macro expansion will use the 'len' in the struct,
which may not be what was intended, but would nevertheless be quietly
accepted.

-bw

> Thanks.
>
> Qing
> > On Apr 14, 2025, at 13:12, Bill Wendling <isanb...@gmail.com> wrote:
> >
> > Soooo....After being on a mini-vacation and thinking about this more,
> > I'm a bit less satisfied with the current proposal. The main issue is
> > that we have seemingly two lookup rules based on which attribute is
> > used (counted_by vs. counted_by_expr).
> >
> >  1. counted_by: We expect an expression that's a lone identifier.
> > Here, we use a pseudo-struct scope to resolve that identifier.
> > ("Pseudo" because it's not fully defined in the standard but created
> > for this feature alone.)
> >
> >  2. counted_by_expr: Any identifiers that appear in the struct need
> > to be forward declared. If they aren't, the normal lookup rules apply.
> >
> > Now, I don't think this will be necessarily confusing to the
> > programmer, but it's inconsistent. In other words, either 'counted_by'
> > *must* forward declare the in-structure identifier or neither must.
> >
> > It's also probable that most expressions will use in-structure
> > identifiers, with the occasional enum or macro. (I'm going off of
> > Yeoul's assertion that they've implemented this successfully on large
> > code bases and haven't had to make allowances for global identifiers.)
> >
> > My counter proposal then is to do something like this:
> >
> > 1. The syntax needs to be unambiguous.
> > 2. Identifier lookup must be consistent between the two attribute forms.
> > 3. The common use case should take the least amount of code to write.
> > (More of a "nice to have".)
> >
> > Therefore, I suggest the following rules, that are more-or-less the
> > reverse of the current proposal's rules:
> >
> > - All untagged identifiers are assumed to be within the structure. If
> > they aren't found in the struct, it's an error.
> > - All globals (i.e. identifiers not in the struct) must be referenced
> > via a special tag or a builtin (e.g. __builtin_global_ref()). The tag
> > or builtin follow current scoping rules---i.e. it may pick up a shadow
> > variable rather than the global.
> >
> > Examples:
> >
> > [Assume a builtin called '__builtin_global_ref' that takes an
> > expression where every identifier within that expression is assumed
> > "global".]
> >
> > struct A {
> >  int *buf __counted_by(len); // 'len' *must* be in the struct.
> >  int len;
> > };
> >
> > constexpr int len = 42;
> > struct B {
> >  int *buf __counted_by(__builtin_global_ref(len)); // 'len' is a global.
> > };
> >
> > enum { PADDING = 42 };
> > struct C {
> >  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING));
> >  int len;
> > };
> >
> > #define PADDING_EXPR __builtin_gloal_ref(len) + 42
> > struct D {
> >  int *buf __counted_by_expr(len * PADDING_EXPR);
> >    // PADDING_EXPR is expanded and that 'len' is not in the structure.
> >  int len;
> > };
> >
> > #define PADDING_EXPR len + 42
> > struct E {
> >  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING_EXPR));
> >    // PADDING_EXPR is expanded and that 'len' is not in the structure.
> >  int len;
> > };
> >
> > There is the issue that the __builtin_global_ref() in 'struct E' may
> > appear to cause the sub-expression to have a higher affinity than the
> > multiplication but it doesn't. That may or may not be a programmer
> > error, but one to be aware of nonetheless.
> >
> > -bw
>

Reply via email to