Effective types of union members

F

Francis Moreau

Hello,

6.5p6 gives a definition of effective type.

However I can't find an answer to this question: What's the effective
type of union's members.

For example:

union u {
int a;
float b;
};

What's the effective type of 'u.a' and 'u.b' members ?

I would say int and float respectively.

But after this:

u.b = 1.23;

does the effective type of 'u.i' is still int ?

Thanks
 
M

Mark Bluemel

Hello,

6.5p6 gives a definition of effective type.

However I can't find an answer to this question: What's the effective
type of union's members.

What do you mean by "effective type"?
For example:

union u {
int a;
float b;
};

What's the effective type of 'u.a' and 'u.b' members ?

What are they declared as?
I would say int and float respectively.


But after this:

u.b = 1.23;

does the effective type of 'u.i' is still int ?

How would an assignment change a declaration?
 
M

Mark Bluemel

What do you mean by "effective type"?

OK - I missed the reference to 6.5p6. But that says the effective type
of an object is the type it was declared with.
 
B

Ben Bacarisse

Francis Moreau said:
6.5p6 gives a definition of effective type.

However I can't find an answer to this question: What's the effective
type of union's members.

For example:

union u {
int a;
float b;
};

What's the effective type of 'u.a' and 'u.b' members ?

I would say int and float respectively.

So would I.
But after this:

u.b = 1.23;

does the effective type of 'u.i' is still int ?

(you mean, presumably, u.a)

Yes. 6.5p6 seems clear on that point. Is there some wording there that
makes you think otherwise?
 
F

Francis Moreau

Hello Ben,

Ben Bacarisse said:
So would I.


(you mean, presumably, u.a)

Yes sorry for the typo.
Yes. 6.5p6 seems clear on that point. Is there some wording there
that makes you think otherwise?

Well a recent discussion I have on gcc-help mailing list about GCC's
strict aliasing stuff confused me about this point. Please have a look
to

Message-ID: <[email protected]>

if you're interested.

Basically GCC's man page gives an example of code which might not work
as expected if '-fstrict-aliasing' switch is passed. Here's the piece of
code taken from my recent discussion:

> Looking again at the second example:
>
> union a_union {
> int i;
> double d;
> };
>
> int f() {
> union a_union t;
> int* ip;
> t.d = 3.0;
> ip = &t.i;
> return *ip;
> }
>

We agreed that this invokes undefined behaviour, but I think the reasons
why are different.

My reason was because it's reinterpreting a double as an int which gives
undefined behaviour.

The other reason is I _think_ because of aliasing issue (again taken
from the discussion):

> could you tell me what the effective type of 't.i' object ?

int, if you can say that object exists at all: it does not have a stored
value. The stored value of t is a double with value 3.0 . You can
take its address and access it via that as "double" (or "char"), or you
can access it as the union it is. You can not access it as "int".

which actually doesn't answer to the question.
 
B

Ben Bacarisse

Francis Moreau said:
Ben Bacarisse <[email protected]> writes:

Well a recent discussion I have on gcc-help mailing list about GCC's
strict aliasing stuff confused me about this point. Please have a look
to

Message-ID: <[email protected]>

if you're interested.

Basically GCC's man page gives an example of code which might not work
as expected if '-fstrict-aliasing' switch is passed. Here's the piece of
code taken from my recent discussion:

> Looking again at the second example:
>
> int i;
> double d;
> };
>
> int f() {
> union a_union t;
> int* ip;
> t.d = 3.0;
> ip = &t.i;
> return *ip;
> }
>

We agreed that this invokes undefined behaviour, but I think the reasons
why are different.

My reason was because it's reinterpreting a double as an int which gives
undefined behaviour.

That may or may not be undefined. If the implementation's int type has
no trap representations then all bit patterns are valid int values. In
fact the gcc manual has an example a couple of lines before this one of
re-interpreting the double as an int (by not using pointers) and it
declares that the fragment is not undefined. The gcc doc are well
placed to say this since the authors will know if there can be any trap
representations. I know this not the key issue with this code fragment
but it's important: if the aliasing rules permit the above code, then it
won't be undefined (as far as gcc is concerned) due to the
re-interpretation.
The other reason is I _think_ because of aliasing issue (again taken
from the discussion):


int, if you can say that object exists at all: it does not have a
stored value. The stored value of t is a double with value 3.0 .
You can take its address and access it via that as "double" (or
"char"), or you can access it as the union it is. You can not
access it as "int".

which actually doesn't answer to the question.

I think the problem relates to what constitutes "the object" for the
purposes of 6.5 paragraphs 6-7.

Clearly the person you are talking to thinks that t.i might not be
considered "an object" at least not one that can be accessed via an
lvalue expression of type int at this point in the code. They consider
"the object" being accessed to be t.d since that is what is stored in
the union.

This does not conflict with the previous example in the manual which is:

| union a_union {
| int i;
| double d;
| };
|
| int f() {
| union a_union t;
| t.d = 3.0;
| return t.i;
| }
|
| The practice of reading from a different union member than the one
| most recently written to (called "type-punning") is common. Even
| with -fstrict-aliasing, type-punning is allowed, provided the
| memory is accessed through the union type. So, the code above will
| work as expected.

Here, if the "the object" being accessed is t.d, then access via t.i is
valid since it is an access to "the object" (t.d) via a union that
includes, as one of its members, the effective type (double) of that
object. In the pointer case, the lvalue expression used (*ip) is not an
aggregate or union that includes double as one of its members, nor is a
lvalue expression with a type compatible with that of the "the object"
being accessed (double).

This is my best analysis of what is being claimed from what you present
here (I don't know how to access gmane via anything by the crudest
web-based interface and I have therefore not bothered to read the other
thread -- sorry).

The flip-side of the argument (which I don't hold) is that "the object"
being accessed in both examples is t.i and, since that has a declared
type (and hence effective type) of int, accessing it via t.i and *ip are
both fine.

Until I hear other arguments, I'm going with the gcc documentation
partly because they are smart people who put these examples there
after careful consideration, but mainly because the intent of the
standard seems to be that a union "holds" only one object at a time.

Another argument is this: the aliasing rules would hardly permit any
conclusions at all unless my interpretation of what is being said is
correct. A function taking

void g(int *ip, double *dp);

could not conclude that *ip and *dp don't alias storage because we could
pass

g(&t.i, &t.u);
 
F

Francis Moreau

Hello Ben,

Ben Bacarisse said:
That may or may not be undefined. If the implementation's int type has
no trap representations then all bit patterns are valid int values. In
fact the gcc manual has an example a couple of lines before this one of
re-interpreting the double as an int (by not using pointers) and it
declares that the fragment is not undefined. The gcc doc are well
placed to say this since the authors will know if there can be any trap
representations. I know this not the key issue with this code fragment
but it's important: if the aliasing rules permit the above code, then it
won't be undefined (as far as gcc is concerned) due to the
re-interpretation.

Ok, so such type-punning is implementation defined and in this case it's
defined so only the aliasing rules is problematic.
I think the problem relates to what constitutes "the object" for the
purposes of 6.5 paragraphs 6-7.

Yes I think so.

Now, I would think that 't.i' and 't.d' are accessing both the same
object 't' whose effective type is union a_union.
Clearly the person you are talking to thinks that t.i might not be
considered "an object" at least not one that can be accessed via an
lvalue expression of type int at this point in the code. They consider
"the object" being accessed to be t.d since that is what is stored in
the union.

Ok I can buy this but why doesn't the standard state this clearly ?

This strong assumption is only made for being 'nice' with aliasing.
This does not conflict with the previous example in the manual which is:

| union a_union {
| int i;
| double d;
| };
|
| int f() {
| union a_union t;
| t.d = 3.0;
| return t.i;
| }
|
| The practice of reading from a different union member than the one
| most recently written to (called "type-punning") is common. Even
| with -fstrict-aliasing, type-punning is allowed, provided the
| memory is accessed through the union type. So, the code above will
| work as expected.

Here, if the "the object" being accessed is t.d, then access via t.i is
valid since it is an access to "the object" (t.d) via a union that
includes, as one of its members, the effective type (double) of that
object.

ok this kind of type-punning (using a union and its members) is defined
by the standard so all is fine so far.
In the pointer case, the lvalue expression used (*ip) is not an
aggregate or union that includes double as one of its members, nor is
a lvalue expression with a type compatible with that of the "the
object" being accessed (double).

AFAIK, there's nothing in the standard that says that the effective type
of a union object can be changed according to its last stored value, is
there ?

I would say that the effective type of the object being accessed is
always 'union a_union'.

[me reading again, again and again 6.5p[67] ...]

But there is very something wrong here...

Suppose we have this:

union A { int m1; } a;
a.m1 = 1;

this simply doesn't fit with 6.5p7, which is obviously something that
should be defined:

Let say that the effective type of the object being accessed 'a'
through its member m1 is union A. Actually with your reasoning, I
can't say what would be the effective type since the union object has
not been initialized yet.

The type of the lvalue 'a.m1' is int.

1/ Is 'int' compatible with 'union A' => NO
2/ same with qualified version => NO
3/ same with signed/unsigned => NO
4/ same with signed/unsigned and qualified version of union A => NO
5/ Is 'int' an aggregate or union type => NO
6/ Is 'int' a character type => NO

So the effective type of 'a' object can't be union... and my reasoning
doesn't hold...

Therefore you're probably right but still 6.5p6 claims:

The effective type of an object for an access to its stored value is
the declared type of the object, if any.

I hate C standard ;)
This is my best analysis of what is being claimed from what you present
here (I don't know how to access gmane via anything by the crudest
web-based interface and I have therefore not bothered to read the other
thread -- sorry).

Just subscribe to this group using news.gmane.org server, no ?
The flip-side of the argument (which I don't hold) is that "the object"
being accessed in both examples is t.i and, since that has a declared
type (and hence effective type) of int, accessing it via t.i and *ip are
both fine.

Until I hear other arguments, I'm going with the gcc documentation
partly because they are smart people who put these examples there
after careful consideration, but mainly because the intent of the
standard seems to be that a union "holds" only one object at a time.

Are there any plan to clarify these points in the future version ?

Thanks
 
B

Ben Bacarisse

Ok, so such type-punning is implementation defined and in this case it's
defined so only the aliasing rules is problematic.

Sorry to nit-pick but "implementation defined" is a technical term with
an exact meaning in the C standard and it does not quite apply here. The
type punning is entirely well-defined -- the bit are re-interpreted --
but whether there are any trap representations is implementation
defined.
Yes I think so.

Now, I would think that 't.i' and 't.d' are accessing both the same
object 't' whose effective type is union a_union.

As you go on to discover, this can't be the case.
Ok I can buy this but why doesn't the standard state this clearly ?

Maybe it is all much clearer than either of us think. In general on
Usenet silence implies agreement, so for the moment I'll assume, rather
boldly, that all the respected posters here agree with me, but I'd be
happier to see some more opinions.
This strong assumption is only made for being 'nice' with aliasing.


ok this kind of type-punning (using a union and its members) is defined
by the standard so all is fine so far.


AFAIK, there's nothing in the standard that says that the effective type
of a union object can be changed according to its last stored value, is
there ?

No, and I did not say it could be! The effective type of the object t
is the union type; that of t.d, double; and that to t.i, int. These
don't change. The question is, does t.i exist at all? The abstract
view of a C union seems to that of a container that can hold one of
several objects at once. After t.d = 3.0; there is no t.i. Accessing
t.i re-interprets the bits of t.d as an int even though there is no
object t.i.

Therefore you're probably right but still 6.5p6 claims:

The effective type of an object for an access to its stored value is
the declared type of the object, if any.

Yes, but the point is what object is being accessed? It can't be as
simple as the apparent object -- i.e. the one whose lvalue is being used
to do the access. If so, there'd be no strict aliasing at all!

The claim being made in that thread (and it's being made by me also) is
that the object being accessed via *ip is actually t.d, and that breaks
the rules of 6.5 p7.
I hate C standard ;)

I think it could be clearer and I certainly welcome another opinion.
Just subscribe to this group using news.gmane.org server, no ?

I could have guess, I suppose, that gmane would offer an NTTP interface
but I still doubt that I'll go join int. I spend too much time here as
it is!

<snip>
 
F

Francis Moreau

Ben Bacarisse said:
Ok, so such type-punning is implementation defined and in this case it's
defined so only the aliasing rules is problematic.

Sorry to nit-pick but "implementation defined" is a technical term with
an exact meaning in the C standard and it does not quite apply here. The
type punning is entirely well-defined -- the bit are re-interpreted --
but whether there are any trap representations is implementation
defined.
Agreed.


[...]

Maybe it is all much clearer than either of us think. In general on
Usenet silence implies agreement, so for the moment I'll assume, rather
boldly, that all the respected posters here agree with me, but I'd be
happier to see some more opinions.

Again that's a strong assumption.

[...]
No, and I did not say it could be! The effective type of the object t
is the union type; that of t.d, double; and that to t.i, int. These
don't change. The question is, does t.i exist at all? The abstract
view of a C union seems to that of a container that can hold one of
several objects at once. After t.d = 3.0; there is no t.i. Accessing
t.i re-interprets the bits of t.d as an int even though there is no
object t.i.

It's a bit weird:

t.d = 3.0;
i = t.i; /* t.i exists */
ip = &t.i; /* t.i doesn't exist anymore */

isn't it ?
Yes, but the point is what object is being accessed? It can't be as
simple as the apparent object -- i.e. the one whose lvalue is being used
to do the access. If so, there'd be no strict aliasing at all!

Well, we're talking only about union here.

Thanks
 
J

Johannes Schaub (litb)

Francis said:
Hello,

6.5p6 gives a definition of effective type.

However I can't find an answer to this question: What's the effective
type of union's members.

For example:

union u {
int a;
float b;
};

What's the effective type of 'u.a' and 'u.b' members ?

I would say int and float respectively.

Yes, I would say so too. They are declared subobjects.
But after this:

u.b = 1.23;

does the effective type of 'u.i' is still int ?

Yes, u.i is always effectively int, and u.b is always effectively a float.
saying "u.b = 1.23" overwrites all or part of the memory of "u.a". However,
saying "u.a" afterwards does not contradict strict aliasing because the
lvalue is of type int, and the effective is also of type int.

So the only thing you need to be aware of is the value representation and
trapping bits in an int. If you read u.a and it turns out to be a trap,
behavior is undefined.

This is notably different in C++. In C++, "u.a" and "u.b" do have lvalues of
type int and float respectively. But the rules in C++ are not based on
effective type, but on dynamic types. The dynamic type changes with an
assignment: u.b reuses the memory of u.a, and make the object accessed by
both u.a and u.b of type float. In C++ it is an aliasing violation to say
u.a afterwards.

In both C++ and C you can copy the union as a whole because the object
keeping the stored value is a member of that union type, and as such the
union type is allowed to alias the object keeping the stored value.
 
B

Ben Bacarisse

For context:

[I've taken the liberty of editing my words to reduce the appalling
type density.]
It's a bit weird:

t.d = 3.0;
i = t.i; /* t.i exists */
ip = &t.i; /* t.i doesn't exist anymore */

isn't it ?

I don't think that i = t.i makes t.i exist, and I hope i did not imply
that is does. All it does is re-interpret the bits in t.d. t.i does
not exist until that member is "put into" the union -- by assigning to
that member. This seems clear and only very slightly weird.
Well, we're talking only about union here.

I don't follow what your objection is.
 
B

Ben Bacarisse

Johannes Schaub (litb) said:
Francis Moreau wrote:

Yes, I would say so too. They are declared subobjects.


Yes, u.i is always effectively int, and u.b is always effectively a float.
saying "u.b = 1.23" overwrites all or part of the memory of "u.a". However,
saying "u.a" afterwards does not contradict strict aliasing because the
lvalue is of type int, and the effective is also of type int.

I don't think is can be so simple. What about:

u.b = 1.23;
int *ip = &u.a;
int i = *ip;

Is the access via *ip valid under strict aliasing rules? This is the
example in the gcc man page that is declared invalid, yet it seems to me
your requirements: "the lvalue is of type int, and the effective is also
of type int".

<snip>
 
J

Johannes Schaub (litb)

Ben said:
I don't think is can be so simple. What about:

u.b = 1.23;
int *ip = &u.a;
int i = *ip;

Is the access via *ip valid under strict aliasing rules? This is the
example in the gcc man page that is declared invalid, yet it seems to me
your requirements: "the lvalue is of type int, and the effective is also
of type int".

Yes, i think it is valid in C. "*ip" refers to an object whose effective
type is int. The C99 TC3 draft seems to agree with me:

"If the member used to access the contents of a union object is not the same
as the member last used to store a value in the object, the appropriate part
of the object representation of the value is reinterpreted as an object
representation in the new type as described in 6.2.6 (a process sometimes
called "type punning"). This might be a trap representation."

While this does not say that it constitutes no alias violation, it
definitely hints at it. And I can't find why it would be an alias violation.
 
B

Ben Bacarisse

Johannes Schaub (litb) said:
Yes, i think it is valid in C. "*ip" refers to an object whose effective
type is int. The C99 TC3 draft seems to agree with me:

"If the member used to access the contents of a union object is not the same
as the member last used to store a value in the object, the appropriate part
of the object representation of the value is reinterpreted as an object
representation in the new type as described in 6.2.6 (a process sometimes
called "type punning"). This might be a trap representation."

Yes, *if* the access is permitted by 6.5 p6 and p7 then it is simply a
re-interpretation, but is it permitted? I think not.
While this does not say that it constitutes no alias violation, it
definitely hints at it. And I can't find why it would be an alias violation.

The reason is outlined in my other replies in this thread, but let me
take another tack... Consider this:

int f(int *ip, double *dp)
{
int i = *ip;
*dp = 0.3;
return i - *ip;
}

As I understand it, the aliasing rules are supposed to allow the
compiler to assume that the result will be zero (gcc certainly makes
this assumption at some optimisation levels). But after

union { int a; double b; } u;
u.b = 1.23;

what happens when we call f(&u.a, &u.b)? Are the accesses to *ip valid?
 
J

Johannes Schaub (litb)

Ben said:
Yes, *if* the access is permitted by 6.5 p6 and p7 then it is simply a
re-interpretation, but is it permitted? I think not.

If that access is not permitted what sense would the foot-note make at all?
It would talk about something that has undefined behavior anyway.
The reason is outlined in my other replies in this thread, but let me
take another tack... Consider this:

int f(int *ip, double *dp)
{
int i = *ip;
*dp = 0.3;
return i - *ip;
}

As I understand it, the aliasing rules are supposed to allow the
compiler to assume that the result will be zero (gcc certainly makes
this assumption at some optimisation levels). But after

union { int a; double b; } u;
u.b = 1.23;

what happens when we call f(&u.a, &u.b)? Are the accesses to *ip valid?

This is a known issue. The aliasing rules in presence of unions is broken.
C++ has the same issue. The C issue is at http://www.open-
std.org/jtc1/sc22/wg14/www/docs/dr_236.htm, and C++'s one is at
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#636 .

The committee says "Example 2 violates the aliasing rules in 6.5 paragraph
7", but I don't think so. C99 just says that an union lvalue can be used to
access an object if the effective type of the object is the type of one of
the members of the union. However in "u.b" you don't use an union lvalue to
access the object. The type of the lvalue is of non-union "double" type. The
union lvalue just appears as a sub-expression in the member selection.
 
B

Ben Bacarisse

Johannes Schaub (litb) said:
If that access is not permitted what sense would the foot-note make at all?
It would talk about something that has undefined behavior anyway.

It's purpose is to explain the behaviour of accesses that *are*
permitted. There is no doubt at all that u.a is allowed after setting
u.b so the meaning needs to be explained.
This is a known issue. The aliasing rules in presence of unions is broken.

I don't know what you mean by "broken". Are you saying that the rules
are wrong, i.e. that the example is indeed UB but that you think it
should not be? If you mean that the situation could be clearer, then I
agree.
C++ has the same issue. The C issue is at http://www.open-
std.org/jtc1/sc22/wg14/www/docs/dr_236.htm, and C++'s one is at
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#636 .
The committee says "Example 2 violates the aliasing rules in 6.5 paragraph
7", but I don't think so. C99 just says that an union lvalue can be used to
access an object if the effective type of the object is the type of one of
the members of the union.

That's not (exactly) what it says and since the devil is in the details,
the wording matters.
However in "u.b" you don't use an union lvalue to
access the object. The type of the lvalue is of non-union "double" type. The
union lvalue just appears as a sub-expression in the member
selection.

I presume that "accessed by" (in 6.5 p7) includes the use of u even
though the full expression (u.b) has a non-union type. I don't see any
other sane way to read it.
 
T

Tim Rentsch

Ben Bacarisse said:
Sorry to nit-pick but "implementation defined" is a technical term with
an exact meaning in the C standard and it does not quite apply here. The
type punning is entirely well-defined -- the bit are re-interpreted --
but whether there are any trap representations is implementation
defined.


As you go on to discover, this can't be the case.


Maybe it is all much clearer than either of us think. In general on
Usenet silence implies agreement, so for the moment I'll assume, rather
boldly, that all the respected posters here agree with me, but I'd be
happier to see some more opinions.


No, and I did not say it could be! The effective type of the object t
is the union type; that of t.d, double; and that to t.i, int. These
don't change. The question is, does t.i exist at all?

Yes. A union type is "an overlapping nonempty set of member objects".
Each of the objects in a union always exists as long as the
union itself does; they just overlap.
The abstract
view of a C union seems to that of a container that can hold one of
several objects at once.

This follows from the fact that the objects overlap -- if you
store into one, all the others are trashed. But they don't
go out of existence; they just don't have their previous (if any)
stored value.
After t.d = 3.0; there is no t.i. Accessing
t.i re-interprets the bits of t.d as an int even though there is no
object t.i. [snip]

There still is a t.i object, and this is more obvious if
sizeof t.i < sizeof t.d. The expression 't.i' always accesses
the 'i' member object of the union object 't', regardless of
whether t.d or t.i has been stored into last.
 
T

Tim Rentsch

Ben Bacarisse said:
I don't think is can be so simple. What about:

u.b = 1.23;
int *ip = &u.a;
int i = *ip;

Is the access via *ip valid under strict aliasing rules? This is the
example in the gcc man page that is declared invalid, yet it seems to me
your requirements: "the lvalue is of type int, and the effective is also
of type int".

Do you mean under effective type rules, or under strict aliasing
rules? As far as I know 'strict aliasing' is defined by GNU/FSF
as part of gcc, and is more restrictive than the effective type
rules of C99 -- in other words, under 'strict aliasing' rules some
programs that are defined under the ISO standard would behave
other than as the ISO standard requires. So it's important
to know which one you are asking about.
 
F

Francis Moreau

Tim Rentsch said:
[...]
I don't think is can be so simple. What about:

u.b = 1.23;
int *ip = &u.a;
int i = *ip;

Is the access via *ip valid under strict aliasing rules? This is the
example in the gcc man page that is declared invalid, yet it seems to me
your requirements: "the lvalue is of type int, and the effective is also
of type int".

Do you mean under effective type rules, or under strict aliasing
rules? As far as I know 'strict aliasing' is defined by GNU/FSF
as part of gcc, and is more restrictive than the effective type
rules of C99 -- in other words, under 'strict aliasing' rules some
programs that are defined under the ISO standard would behave
other than as the ISO standard requires. So it's important
to know which one you are asking about.

Ok so it looks like we agree that the example given by GCC's man page
which is the same as the above one _is_ defined by the standard as a
valid alias case.

However it looks like the Standard doesn't handle the union special case
correctly when it comes to aliasing, since unions remove all
optimisations based on type:

union u { int a; double b; };

/* at that point int can alias double */
int *i;
double *d;

void foo(int *pi, double *pd) { ... }

int main (void)
{
union u u;
i = &u.a;
d = &u.b;
foo(i, d);
}

So 'strict aliasing' seems the correct thing to do.
 
F

Francis Moreau

Johannes Schaub (litb) said:
Ben Bacarisse wrote:

[...]
The reason is outlined in my other replies in this thread, but let me
take another tack... Consider this:

int f(int *ip, double *dp)
{
int i = *ip;
*dp = 0.3;
return i - *ip;
}

As I understand it, the aliasing rules are supposed to allow the
compiler to assume that the result will be zero (gcc certainly makes
this assumption at some optimisation levels). But after

union { int a; double b; } u;
u.b = 1.23;

what happens when we call f(&u.a, &u.b)? Are the accesses to *ip valid?

This is a known issue. The aliasing rules in presence of unions is broken.
C++ has the same issue. The C issue is at http://www.open-
std.org/jtc1/sc22/wg14/www/docs/dr_236.htm, and C++'s one is at
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#636 .

Interesting.

The dr had been submitted 10 years ago, and it doesn't seem to be fixed
yet.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top