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


On Tue, 24 Jul 2001, Mark Mitchell wrote:

> 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?

In this case, it tells me "warning: `__mode__' attribute ignored" - I
don't know why.  (Whereas the C compiler accepts the attribute here.)  
The description I gave is how "mode" works for C.  (In principle we could
have "mode" give C99 extended integer types rather than standard ones -
with benefits for type-based aliasing, providing an 8-bit type without the
special aliasing properties of char, etc. - but then there would be the
problems of working out what name mangling etc. do to these types in C++.)

> 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?

sizeof (int __attribute__((__mode__(__DI__))).

> What about `f<int>'?  (Use a `typedef' if you think that attributes

sizeof (int).

> int g() {
>   return f<int> () * f<int> ();
> }
> 
> is certainly legal and returns 2 * sizeof (int).  This, however, doesn't

sizeof (int) * sizeof (int), rather.

> 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.

If "mode" isn't treated specially, ill-formed, no diagnostic required,
same as violations of the one definition rule across translation units.  
In principle the linker might be enhanced to check both (e.g. associating
some data with linkonce sections, and requiring that data to agree exactly
when merging - whether that data is a (checksum of a) token sequence for
the one definition rule, or details of attributes that aren't part of the
mangled name.

> 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!

They are different - meaning "pointer to stdcall function" and "stdcall
pointer to function" - though the latter doesn't make semantic sense and
valid_machine_attribute will apply the attribute to the function type
having failed to apply it to the pointer.  (Users expect function
attributes applied to pointers to functions to work like this, e.g.
c/3481.)

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

You can cast to such types.

There is a reasonably clean syntax subset - but it isn't the most usual
way in which people use attributes.  It is:

* Attributes which are like storage class specifiers, such as "section",
must appear in declaration specifiers, preferably at the start of them,
like storage class specifiers, and apply to the declaration.

* Attributes which apply to types, such as e.g. "noreturn" (ought to),
must be prefix attributes in a nested declarator, in one of the forms
(using this time the syntax from the C++ standard)

direct-declarator:
	[other standard forms]
	( attributes declarator )

ptr-operator:
	* cv-qualifier-and-attribute-seq[opt]
	&
	::[opt] nested-name-specifier * cv-qualifier-and-attribute-seq[opt]

* Attributes which apply to struct/union/enum types being defined must
appear just after the struct/union/enum keyword.

This syntax subset avoids problems of ambiguity about what binds where.

-- 
Joseph S. Myers
jsm28@cam.ac.uk


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