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]
Other format: [Raw text]

Re: Proposed semantics for attributes in C++ (and in C?)


Mark Mitchell <mark@codesourcery.com> writes:

> We have a number of C++ PRs open around problems with code like this:
> 
>    struct S {
>      void f();
>      virtual void g();
>    };
> 
>    typedef __attribute__((...)) struct S T;
> 
> If the attribute makes any substantive change to S (e.g., changes its
> size, alignment, etc.) then bad things happen.  For example, the
> member functions of "S" have expectations about the layout of "S" that
> are not satisfied if they are called with a "T".  Depending on the
> attribute and circumstances, we do all manner of bad things, including
> ICE, generate wrong code, etc.
> 
> For a while now, I've been promising to propose semantics for these
> constructs.  Here is a sketch of the semantics that I think we should
> have.  (I say a sketch because I have not attempted to write
> standardese.)
> 
> All attributes must be classified as either "semantic" or
> "non-semantic" attributes.  A "semantic" attribute is one which might
> affect code-generation in any way.  A "non-semantic" attribute cannot
> affect code-generation.  For example, "used" and "deprecated" are
> non-semantic attributes; there is no way to observe, by looking at an
> object file, whether or not a class has been marked with one of these
> attributes.  In contrast, "packed" is a semantic attribute; the size
> of a class is different depending on whether or not it is "packed".
> 
> Any attribute may be applied at the point of definition of a
> class. These attributes (whether semantic or non-semantic) apply to
> the class. For example, if the class is packed, then the member
> functions expect the "this" pointer to point to the packed class.
> 
> A typedef declaration which adds only non-semantic attributes is
> always valid.  As with other typedefs, the typedef declaration creates
> a new name for an existing type.  The type referred to by that name is
> the same type as the original type.  However, the *name* has
> additional properties, implied by the (non-semantic) attributes.  For
> example, using a "deprecated" name for a type results in a deprecation
> warning. But, a function declared to take a parameter with the
> non-deprecated name may be passed a parameter with the "deprecated"
> name.
> 
> A typedef declaration which adds semantic attributes to a class type,
> other than POD classes with no explicitly declared members other than
> data members, to arrays of such classes, to arrays of such arrays,
> etc., is invalid. (POD-ness alone is not satisfactory, as PODs may
> contain function members, and I think dealing with static data members
> and typedef members is not worth the trouble.)
> 
> A typedef declaration which adds semantic attributes to a POD class
> type with no function members is valid, but creates an entirely new
> type, different from all other types except others formed by adding
> the same combination of semantic attributes to the same original class
> type.  In the example above, if the typedef adds a semantic attribute,
> you may not pass an "S" to a function expecting a "T" or vice versa.
> Neither may you pass an "S*" to a function expecting a "T*", without
> an explicit reinterpret_cast.  The name of "T", for linkage purposes,
> is "T", and there is no implicit "T::S" type; instead, however, there
> is a "T::T" type.  (Various consequences follow; for example,
> typeid(T) gives you a type_info object that indicates that the name of
> the type is "T".) References to the original type from within the
> types of the members of the class still refer to the original class.
> For example, in:
> 
>    struct S {
>      char c;
>      S* next;
>    };
>    typedef __attribute__((packed)) S T;
> 
> the data member T::next has type "S*", not "T*".
> 
> A typedef declaration which adds semantic attributes to a non-class
> type is valid, but again creates an entirely new type.  (We might want
> a special exception to the "entirely new type" rule for the "mode"
> attribute, declaring that "typedef __attribute__((mode(DI))) int LL"
> is equivalent to "typedef long long LL;" on platforms where "long
> long" has DImode.) So,
> 
>    typedef S* P;
>    typedef __attribute__((...)) P Q;
> 
> creates a type "Q" that is incompatible with "S*" if the attribute is
> semantic.  However, the type of "*Q" is still "S".  It is invalid to
> do anything that would require either type_info or a mangled name for
> "Q", including using it as an argument to typeid, thowing an exception
> of a type involving "Q", or declaring a template to take a parameter
> of a type involving "Q".  (We could relax some of these restrictions
> in future, if we add mangling support for attributes.)

Declaring a function which takes a 'Q' also requires the mangled name of 'Q'.

> A variable declaration involving attributes, like:
> 
>    __attribute__((...)) S v;
> 
> is treated as syntactic sugar for:
> 
>    typedef __attribute__((...)) S T;
>    T v;
> 
> where T is some invented type name different from all others in the program.
> 
> For example given:
> 
>    __attribute__((packed)) S v;
> 
> the type of "&v" is "__attribute__((packed)) S *", and cannot be
> passed to a function expecting an "S*", but can of course be passed to
> a function expecting an "__attribute__((packed)) S *", or a typedef
> for such a type.

... except that there can't be any such functions.  You could assign
it to another variable of the same type, or a field of a class with
that type.


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