This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Prefix attributes vs. grammar



> Start from the principle that the corresponding program without attributes
> must be well-formed if the program with attributes is to be well-formed.

That probably already breaks some usages.  People seem to expect that
types with different attributes are different types, for example.

Concretely, your example isn't a description of what G++ currently
accepts; G++ 3.0 accepts:

void f (int __attribute__((__mode__(__DI__))) x) {}
void f (long long x) {}

which it should not if the attribute makes the type equivalent to long
long.  So, perhaps the exception you offerred is not required?

Your rule, without the exception, would be a very good start.

> x;".)  Given an example where problems arise, a listing of all relevant
> paragraphs of ISO 14882 and an explanation of how they interact and how
> attributes cause problems, I'll attempt to work out a plausible answer.

You're being helpful, but I know that you understand that this is the
upside-down way from how it is supposed to go.  Both you and I agree
that this stuff should be worked out first, not afterwards.

Just for fun, here's a question.  Consider:

  template <typename T> size_t f() { return sizeof (T); }

What does `f<int __attribute__((__mode__(__DI__))>' return?
What about `f<int>'?  (Use a `typedef' if you think that attributes
require a declarator to which to bind.)

Without the attributes:

int g() {
  return f<int> () * f<int> ();
}

is certainly legal and returns 2 * sizeof (int).  This, however, doesn't
make sense with attributes.  So, we have two choices: this is ill-formed
(no diagnostic required, the functions might be in different translation
units), or this is well-formed.  If well-formed, we need to invent
manglings for attributes.  If ill-formed, people get very subtly burned;
the linker will merge the two versions of `f', but only one call-site
will get the value it expected.  Neat, because this can happen even if
one definition is in a library, so you can unit-test your code all you
want, and still have it fail when linking with someone else's code due
to this issue.

> Given an understanding of the standard declarator syntax (i.e., having
> memorised the relevant parts of the standard's syntax and description of
> semantics), the meaning of attributes as part of nested declarators (as
> opposed to prefix and postfix attributes on declarations) is natural and
> obvious.

Not to me, and I'm pretty standards-fluent.

For example, is it an invariant that attributes in a declaration always 
apply to the declarator, and not to some part of the type of the 
declarator?  If so, then there are types that you can only talk about with 
typedefs (because trying to name them any other way yields modification of 
the declarator).  If not, then `void (stdcall * f) ()' and `void (*stdcall 
f)' are different (where `stdcall' is shorthand for the appropriate 
attribute stuff).  According to Stan's proposal, these mean the same thing, 
which is OK with me, but certainly not obvious!

Can you cast to a type that involves attributes?  If not, why not?  That
would be an example where the declarator is abstract.

It is a huge mistake to implement these things without working through the 
issues first.  We end up having to support things for backwards 
compatibility without even knowing what they mean.  I wish I had known
about this before its release; then I would have argued to remove this 
functionality until we figured out what it meant.  Now we are stuck,
according to Stan, who believes there to be lots of code using these
features.

-- 
Mark Mitchell                mark@codesourcery.com
CodeSourcery, LLC            http://www.codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]