Re: Proposed semantics for attributes in C++ (and in C?)
Geoffrey Keating wrote: A typedef declaration which adds semantic attributes to a non-class type is valid, but again creates an entirely new type. 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'. Good point! 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. Right. And, since there seems to be consensus that you shouldn't be able to apply semantic attributes to class types, packed is a bad example there too. (If you applied packed at the point of declaration of S, then S has a different layout than it otherwise would, but we don't need to do anything regarding mangling, etc.) Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Proposed semantics for attributes in C++ (and in C?)
On Mon, 16 Oct 2006, Jason Merrill wrote: Mark Mitchell wrote: Yes, I would be happy to explicitly ignore semantic attributes in typedefs as well, with a warning (or even an error). However, I had not realized that we ever did that; I'm surprised that the change that instituted this is so recent. I suppose that explains why we're suddenly seeing a rash of such problems. Jason, as you made this change, do you have any comments on the proposal? I don't think my patch changed the handling of class typedefs; certainly my intent was only to change how we handle class __attribute ((foo)) C Previously we rejected it, now we apply the attributes to the class. I was referring to the change in extend.texi -the closing brace. It is ignored if the content of the structure, union -or enumerated type is not defined in the specifier in which the -attribute specifier list is used---that is, in usages such as [EMAIL PROTECTED] __attribute__((foo)) bar} with no following opening brace. +the closing brace. The former syntax is preferred. (note that r115086 changed extend.texi but extend.texi doesn't appear to be mentioned in the log message). The old text only covered some of the problem cases, but the statement that attributes were ignored in such cases was still removed. -- Joseph S. Myers [EMAIL PROTECTED]
Re: Proposed semantics for attributes in C++ (and in C?)
Jason Merrill wrote: I don't think my patch changed the handling of class typedefs; certainly my intent was only to change how we handle class __attribute ((foo)) C Previously we rejected it, now we apply the attributes to the class. OK, that certainly makes sense. (That's one of the items in the proposal I wrote up: that you can apply attributes at the point of declaration of a class.) Which PRs are you referring to? One example is: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28558 However, this is a problem with non-semantic attributes, and not related to your patch. So, I apologize for any aspersions cast. But, it does motivate for writing something down about what we want semantics we want. Here, what I think we want is (as per the proposal) to create a new anonymous typedef for __attribute__((unused)) A, but consider that the same type as A. I was pretty sure there were other PRs, but I'm not able to find them now, so perhaps I was dreaming. I thought there were also PRs about typeid and mangling failing (and/or doing the wrong thing) for types with attributes (including scalars with attributes). I'd be inclined to prohibit semantic attributes on typedefs in general. That's certainly simpler. I'm happy to be talked out of that idea. :-) Extending the type system to handle attribute types seems excessively complicated. I think we should define a set of attributes which prevent us from taking the address of a variable with that attribute (packed...anything else?) and check for them at the same places we check for taking the address of a bitfield. That seems like a good idea to me. However, one consequence is that a packed class cannot have member functions (since you'd never be able to get a this pointer for them); do you think that's OK? -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Proposed semantics for attributes in C++ (and in C?)
Joseph S. Myers wrote: I was referring to the change in extend.texi -the closing brace. It is ignored if the content of the structure, union -or enumerated type is not defined in the specifier in which the -attribute specifier list is used---that is, in usages such as [EMAIL PROTECTED] __attribute__((foo)) bar} with no following opening brace. +the closing brace. The former syntax is preferred. That passage has nothing to do with typedefs. The change is that previously, if we saw class __attribute ((visibility (hidden))) C; we would ignore the attribute, now we record it. My change to the previous paragraph now seems excessive, however: -You may specify the @code{aligned} and @code{transparent_union} -attributes either in a @code{typedef} declaration or just past the -closing curly brace of a complete enum, struct or union type [EMAIL PROTECTED] and the @code{packed} attribute only past the closing -brace of a definition. +You may specify type attributes either in a @code{typedef} declaration +or in an enum, struct or union type declaration or definition. I didn't notice the distinction this passage was trying to make between packed and other attributes, just that it was an incomplete list. In removing the incomplete list I also removed the useful separation. Jason
Re: Proposed semantics for attributes in C++ (and in C?)
Mark Mitchell [EMAIL PROTECTED] 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*,
Re: Proposed semantics for attributes in C++ (and in C?)
On Sun, 15 Oct 2006, Mark Mitchell wrote: 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; I was happy with the state before r115086 (i.e. with it being documented that such attributes on typedefs are ignored). But given that we are now attempting to honour them, the proposed semantics seem reasonable. The proposal requires documentation for each (type) attribute of whether it is semantic or non-semantic. In general the documentation of attribute semantics needs cleaning up to make clear just when each attribute can be used and what exactly it means (and the code needs cleaning up to follow sensible documented semantics) - for example, attributes with documentation split and duplicated because they apply to more than one of functions, variables and types. (The syntax documentation is cleaner, and I think accurate for C, but it does include some speculative future possibilities that seemed nice when I first wrote it but I no longer think would be a good idea.) -- Joseph S. Myers [EMAIL PROTECTED]
Re: Proposed semantics for attributes in C++ (and in C?)
Joseph S. Myers wrote: On Sun, 15 Oct 2006, Mark Mitchell wrote: 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; I was happy with the state before r115086 (i.e. with it being documented that such attributes on typedefs are ignored). But given that we are now attempting to honour them, the proposed semantics seem reasonable. Yes, I would be happy to explicitly ignore semantic attributes in typedefs as well, with a warning (or even an error). However, I had not realized that we ever did that; I'm surprised that the change that instituted this is so recent. I suppose that explains why we're suddenly seeing a rash of such problems. Jason, as you made this change, do you have any comments on the proposal? -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Proposed semantics for attributes in C++ (and in C?)
On Oct 15, 2006, at 3:12 PM, Mark Mitchell wrote: 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.) Note that this is an ABI change for any code that uses these. I agree that it seems cleaner to just disallow this practice entirely, particularly if it is a recent invention. In any case, having the compiler reject code that does not or will not work is a much better position to be in than silently miscompiling code. -Chris
Re: Proposed semantics for attributes in C++ (and in C?)
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. You might want to take a look at the Ada concept of freeze point. That's one approach to a similar problem.