This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++0x] implementing forward declarations for enums
On 10/06/2010 09:42 AM, Rodrigo Rivas wrote:
On Wed, Oct 6, 2010 at 6:35 AM, Jason Merrill<jason@redhat.com> wrote:
Do you really need to do the variant fixup for opaque enums? It's not clear
to me how you could get a variant with the wrong values unless you had a
forward declaration with a different underlying type, which would only
happen with GCC forward declarations, not with C++0x opaque enums.
I'm afraid I don't really understand this variant stuff or when they
are created, so I just did it safely.
Variants are e.g. const-qualified, typedef'd, or attributed versions of
types. We can't have any variants of a type before it is first
declared, so we should never need to copy_type_enum to variants; since
we don't have C-like forward declarations with unspecified underlying
type, there's no way to create a variant before the underlying type is
set. I suppose the code that was doing that before was a relic of when
the C++ front end forked from the C front end.
Let's try removing that call and instead asserting that when we're
setting the underlying type, there are no variants.
This way the debugging information for an opaque enumerator will lack
the enumeration list, but that's hard to avoid.
It doesn't seem that hard; we just need to indicate incompleteness to the
back end in some way other than not setting TYPE_SIZE. There are lots of
free flags still.
But then, should I modify the debuggers back end? I think that's overkilling!
I don't think it's overkill at all. If we don't have the enumeration
list, then we don't have enough information for complete debug info.
I'd suggest reversing the sense of ENUM_HAS_VALUE_LIST_P so that it's only
set on opaque enums, and then moving it to use base.private_flag instead of
lang_flag_2.
I don't think we want to do rest_of_type_compilation for opaque decls,
either; only for the actual definition.
rest_of_type_compilation just emits the debugging information for the
type, right?
Yes.
But the opaque-enum *are* definitions: a opaque enum is a complete
type. You may not have an enumerator list in this compilation unit
while you may have variables of this type:
enum class E;
E e;
/* EOF */
If I don't emit debugging information for the opaque-enum, then the
variable e will lack debugging information.
It should work the same way as a use of an incomplete class:
class A *ap;
When the debugging back end sees a use of a type, it emits it if it
hasn't already been emitted.
template<typename T>
struct S
{
enum class E;
};
enum class S<int>::E { a, b, c };
enum class S<double>::E { d, e, f };
Interesting. Yes, it makes sense for that to work, though perhaps they
should have "template<>" at the beginning. I'll bring this up with the
committee.
template<> makes sense if you see this as a template specialization
I see it as two opaque enum listings that happen to be into two class
template instantiations.
Yes, but the convention is that we use template<> for definitions of
members of template instantiations as well:
template <typename T>
struct S
{
static T t;
};
template<> int S<int>::t = 42;
template<> double S<double>::t = 3.1415;
BTW, let's improve the diagnostic for "enum E;" in C++0x mode to let the
user know that either "enum E: int;" or "enum class E;" would be OK.
Hmmm, as it happens "enum E;" is parsed without diagnostics in C++98
if the enumeration is already defined.
It emits the error "use of E without a previous definition" because it
parses it as an elaborated_type_specifier.
Right, we can just give a different error at the same place in C++0x mode.
This test complains about mismatching underlying types for
enum A { e };
enum A { e };
which is incorrect.
Is is because the parser sees something like that.
enum A : unique_type1 { e };
enum A : unique_type2 { e };
Where unique_typeN is created after the list of enumerators.
So the first error it sees it that the underlying types are different.
Admittedly, the message is misleading, but correct, from a certain
point of view ;-)
The only solution I can think of is to add yet another flag to the
enumeration tree to signal whether an enum has an explicit underlying
type. Checking this flag we can ignore this particular error and it
will stump upon the multiple definition error.
Couldn't we just wait to give this error until finish_enum?
template<class T>
struct A
{
enum E: int;
};
template<class T>
enum A<T>::E { e1 };
This certainly does the wrong thing, but I don't think it should even compile!
According to 14.1 (templ):
"
The declaration in a template-declaration shall
- declare or define a function or a class, or
- define a member function, a member class or a static data member of
a class template or of a class
nested within a class template, or
- define a member template of a class or class template, or
- be an alias-declaration.
"
So an "enum template" does not exist. It would be a nice gnu++0x
extension, though (too late to try to get it in the draft...).
I'm not so sure it's too late to get it in; it seems like a simple
oversight to me. I am trying to get it into the draft, for which a
working implementation would help...:)
Jason