Discussion:
[std-discussion] Possible bug in visual studio c++ compiler
Anders Granlund
2015-07-03 01:09:43 UTC
Permalink
According to my current understanding of the c++ standard, the following
program should be well-formed:

namespace X {
class A;
}

namespace Y {
using X::A;
class A {};
}

int main() {}

Visual studios c++ compiler does not agree with me on this. When trying to
compile this program I get the following diagnostic message:

error C2888: 'X::A': symbol cannot be defined within namespace 'Y'

Looking at the description of error C2888
at https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
but they are not formulating it in the correct way:

7.3.1.2 p2 ( http://eel.is/c++draft/namespace.memdef#2 ):
Members of a named namespace can also be defined outside that namespace
by explicit qualification ([namespace.qual]) of the name being defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.

My example program is not violating this rule however, since i'm not even
using explicit qualification when I define the class A.

Is there any other rule of the standard that I have missed that my example
program is violating?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-07-03 01:48:17 UTC
Permalink
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
Litmus test: if two declarations in a namespace are independent, their order
doesn't matter. So what happens if we invert the last two statements?

namespace Y {
class A {};
using X::A;
}

Should the above be allowed? I'd say no, since Y::A already exists.

GCC: error: ‘A’ is already declared in this scope
Clang: error: target of using declaration conflicts with declaration already in
scope
ICC: error: "A" has already been declared in the current scope
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-03 02:30:09 UTC
Permalink
You changed the order of two declarations and got a program that is
non-well-formed. What do you conclude from that?
Post by Thiago Macieira
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
Litmus test: if two declarations in a namespace are independent, their order
doesn't matter. So what happens if we invert the last two statements?
namespace Y {
class A {};
using X::A;
}
Should the above be allowed? I'd say no, since Y::A already exists.
GCC: error: ‘A’ is already declared in this scope
Clang: error: target of using declaration conflicts with declaration already in
scope
ICC: error: "A" has already been declared in the current scope
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-07-03 04:10:30 UTC
Permalink
Post by Anders Granlund
You changed the order of two declarations and got a program that is
non-well-formed. What do you conclude from that?
My point is that if the two declarations were independent, the program would
have continued to be well-formed after the swap. It clearly isn't, which means
the two declarations are not independent.

With that in mind, I concluded that the unswapped version also looks ill-
formed because it is declaring the same identifier of the same type twice in
the namespace.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-03 08:37:38 UTC
Permalink
In my example program: The name A denotes the same entity in the
declaration class A; and in the definition class A { ... }; There is
nothing wrong with that. Have you heard about forward declarations of
classes?
Post by Thiago Macieira
Post by Anders Granlund
You changed the order of two declarations and got a program that is
non-well-formed. What do you conclude from that?
My point is that if the two declarations were independent, the program would
have continued to be well-formed after the swap. It clearly isn't, which means
the two declarations are not independent.
With that in mind, I concluded that the unswapped version also looks ill-
formed because it is declaring the same identifier of the same type twice in
the namespace.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-07-05 08:05:29 UTC
Permalink
Post by Anders Granlund
In my example program: The name A denotes the same entity in the
declaration class A; and in the definition class A { ... }; There is
nothing wrong with that. Have you heard about forward declarations of
classes?
So you're implementing class X::A in namespace Y?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-05 10:53:58 UTC
Permalink
Seems like it depends on what compiler I use. GCC and Clang thinks im doing
that and they are ok with it. Visual studio thinks they are two independent
classes. I asked this on stack overflow and it seems that the example
program is ill-formed and that GCC and Clang are the compilers with the bug
and not visual studio. Apparently you cannot redeclare something via a
using-declaration:

http://stackoverflow.com/questions/31220154/class-declaration-in-same-scope-as-using-declaration-compiles-in-gcc-but-not-msv
Post by Thiago Macieira
Post by Anders Granlund
In my example program: The name A denotes the same entity in the
declaration class A; and in the definition class A { ... }; There is
nothing wrong with that. Have you heard about forward declarations of
classes?
So you're implementing class X::A in namespace Y?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-07-05 13:17:27 UTC
Permalink
Not quite. GCC and Clang merely allow the declaration in Y to hide the using declaration, as if the name were visible through a using namespace directive.

Perhaps the rule most clearly being violated is [namespace.udecl] §7.3.3/13. MSVC provides the required diagnosis.
Seems like it depends on what compiler I use. GCC and Clang thinks im doing that and they are ok with it.
So you're implementing class X::A in namespace Y?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-05 13:49:40 UTC
Permalink
Hmm I can agree with you on that when it comes to Clang, but try to use
X::A in main in a way that requires a complete type. GCC will think it is
complete, but Clang will not:

This compiles in gcc (turn off warnings):

namespace X {
class A;
}

namespace Y {
using X::A;
class A {};
}

int main() { X::A a; }

This does not compile in clang (complains that X::A is not a complete type):

namespace X {
class A;
}

namespace Y {
using X::A;
class A {};
}

int main() { X::A a; }

So GCC thinks i'm implementing class X::A in namespace Y and is ok with it.
Post by David Krauss
Not quite. GCC and Clang merely allow the declaration in Y to hide the
using declaration, as if the name were visible through a using namespace
directive.
Perhaps the rule most clearly being violated is [namespace.udecl]
§7.3.3/13. MSVC provides the required diagnosis.
Seems like it depends on what compiler I use. GCC and Clang thinks im
doing that and they are ok with it.
Post by Thiago Macieira
So you're implementing class X::A in namespace Y?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-05 13:53:10 UTC
Permalink
The funny thing is that clang isn't even consistent between different kinds
of entities in its behaviour (the first program below compiles the second
gives redefinition error):

namespace X {
struct i {};}
namespace Y {
using X::i;
struct i {};}
int main() {}

namespace X {
int i;}
namespace Y {
using X::i;
int i;}
int main() {}
Post by Anders Granlund
Hmm I can agree with you on that when it comes to Clang, but try to use
X::A in main in a way that requires a complete type. GCC will think it is
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() { X::A a; }
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() { X::A a; }
So GCC thinks i'm implementing class X::A in namespace Y and is ok with it.
Post by David Krauss
Not quite. GCC and Clang merely allow the declaration in Y to hide the
using declaration, as if the name were visible through a using namespace
directive.
Perhaps the rule most clearly being violated is [namespace.udecl]
§7.3.3/13. MSVC provides the required diagnosis.
Seems like it depends on what compiler I use. GCC and Clang thinks im
doing that and they are ok with it.
Post by Thiago Macieira
So you're implementing class X::A in namespace Y?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Johannes Schaub' via ISO C++ Standard - Discussion
2015-07-03 09:24:49 UTC
Permalink
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
The rule is somewhere at chapter 3 and says that if two names that are the
same are declared in the same declarative region, they must either all
declare the same entity, one must hide others or they must all declare
functions and/or function templates.

In your case none of those cases match but the two names refer to different
classes.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Rodríguez Ibeas
2015-07-03 09:51:22 UTC
Permalink
My understanding is that the 7.3.1.2 is, like Bo says, about:

namespace A { class B; }
class A::B {};

Note that the quote explicitly mentions "explicit qualification", and
"enclosing namespace", none of which hold in the original code in this
thread.

It seems that there is a divide in the interpretation of different
compilers:

namespace A {
struct S;
class X {
friend class S; // ::A::S
static const int k = 1;
};
}
using A::S;
struct S {
void f() {
int array[::A::X::k];
}
};
int main() {
S s; s.f();
}

The test attempts to determine whether the definition of 'S' refers to
::A::S or to ::S, or to a different type. This is the result of different
compilers:

icc 13.0.1, gcc 5.1.0, cl 10.00.40219.01, Solaris CC 12.3 all accept the
code, the definition refers to ::A::S and has access to ::A::X due to the
friend declaration.

clang 3.6: fails, the definition is of a new type ::S, that is not a friend
of ::A::X. The definition does not cause a conflict with the using
declaration, but the attempt to use it in 'main' is considered ambiguous (2
errors)

xlC 11.01: fails, considers the definition to be ::S and that declaration
to be conflicting with the using declaration.

It seems that it might be worth clarifying what the expected result should
be and notify the vendors...

David

On Fri, Jul 3, 2015 at 10:24 AM, 'Johannes Schaub' via ISO C++ Standard -
Post by 'Johannes Schaub' via ISO C++ Standard - Discussion
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
The rule is somewhere at chapter 3 and says that if two names that are the
same are declared in the same declarative region, they must either all
declare the same entity, one must hide others or they must all declare
functions and/or function templates.
In your case none of those cases match but the two names refer to
different classes.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-03 19:08:13 UTC
Permalink
David: Do you want to make the report about this ambiguity to the c++
standard group, or should I do that? You have probably more credibility
than me in this matter.
Post by David Rodríguez Ibeas
namespace A { class B; }
class A::B {};
Note that the quote explicitly mentions "explicit qualification", and
"enclosing namespace", none of which hold in the original code in this
thread.
It seems that there is a divide in the interpretation of different
namespace A {
struct S;
class X {
friend class S; // ::A::S
static const int k = 1;
};
}
using A::S;
struct S {
void f() {
int array[::A::X::k];
}
};
int main() {
S s; s.f();
}
The test attempts to determine whether the definition of 'S' refers to
::A::S or to ::S, or to a different type. This is the result of different
icc 13.0.1, gcc 5.1.0, cl 10.00.40219.01, Solaris CC 12.3 all accept the
code, the definition refers to ::A::S and has access to ::A::X due to the
friend declaration.
clang 3.6: fails, the definition is of a new type ::S, that is not a
friend of ::A::X. The definition does not cause a conflict with the using
declaration, but the attempt to use it in 'main' is considered ambiguous (2
errors)
xlC 11.01: fails, considers the definition to be ::S and that declaration
to be conflicting with the using declaration.
It seems that it might be worth clarifying what the expected result should
be and notify the vendors...
David
On Fri, Jul 3, 2015 at 10:24 AM, 'Johannes Schaub' via ISO C++ Standard -
Am 03.07.2015 03:09 schrieb "Anders Granlund" <
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
The rule is somewhere at chapter 3 and says that if two names that are
the same are declared in the same declarative region, they must either all
declare the same entity, one must hide others or they must all declare
functions and/or function templates.
In your case none of those cases match but the two names refer to
different classes.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-03 09:51:57 UTC
Permalink
Johannes: Are you thinking about 3.3.1 p4 (
http://eel.is/c++draft/basic.scope.declarative#4 ). I am not violating that
rule, since the entities are the same in my case.

Also if you are correct and I am in fact violating 3.3.1 p4, how come that
gcc doesn't give an error message for my example program? At least with
have a bug in gcc then.



2015-07-03 11:24 GMT+02:00 'Johannes Schaub' via ISO C++ Standard -
Post by 'Johannes Schaub' via ISO C++ Standard - Discussion
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
The rule is somewhere at chapter 3 and says that if two names that are the
same are declared in the same declarative region, they must either all
declare the same entity, one must hide others or they must all declare
functions and/or function templates.
In your case none of those cases match but the two names refer to
different classes.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-07-05 23:42:01 UTC
Permalink
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying to
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like they
are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that namespace
by explicit qualification ([namespace.qual]) of the name being defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not even
using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my example
program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which is
marked as also being resolved by 1838. I've filed a core issue to get the
wording here tweaked to actually address issue 1021.]

Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
And then your program is ill-formed under [basic.scope.declarative]p4:
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-06 01:05:49 UTC
Permalink
Thanks for the clarification. I thought it would be a good idea to try to
find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.

If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.

namespace N {

struct A;
}
using N::A;
struct A { };

int main() {}



struct S;

namespace A {
using ::S;
struct S { };
}

int main() {}

So this means that the compilers needs to be fixed to emit a
diagnostic message for these situations?

I guess we can conclude that using-declarations should be opaque when
it comes to redeclarations, ie redeclarations doesn't work at all via
using-declarations?

I guess we also could conclude that redeclarations can never be made
across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that namespace
by explicit qualification ([namespace.qual]) of the name being defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not even
using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which
is marked as also being resolved by 1838. I've filed a core issue to get
the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-06 01:49:32 UTC
Permalink
Richard, I think your reply fully solves the following questions that I
posted earlier on stack overflow. If you want to answer them feel free to
do so. Otherwise I'll answer them later.

http://stackoverflow.com/questions/31230903/redefinition-inconsistency-in-clang-between-struct-and-int

http://stackoverflow.com/questions/31232186/compile-error-when-defining-a-member-function-but-only-in-gcc

http://stackoverflow.com/questions/31220154/class-declaration-in-same-scope-as-using-declaration-compiles-in-gcc-but-not-msv
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try to
find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
I guess we also could conclude that redeclarations can never be made across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which
is marked as also being resolved by 1838. I've filed a core issue to get
the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-07-06 04:57:14 UTC
Permalink
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try to
find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
namespace N { using ::S; }
struct N::S {};

GCC, MSVC, and Clang accept this, EDG rejects. And this:

extern int n;
namespace N { using ::n; }
int N::n;

GCC accepts this, Clang and EDG reject. MSVC crashes.

The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
Post by Anders Granlund
I guess we also could conclude that redeclarations can never be made across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the following
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which
is marked as also being resolved by 1838. I've filed a core issue to get
the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-06 09:26:10 UTC
Permalink
Hmm, you are right, things are more complicated.

I like those new examples you gave. Compiling modified versions of your
first example gives some interesting observations. The results confused me.
I used GCC and Clang from http://melpon.org/wandbox with HEAD (trunc) and
c++ 03.

*Your first example:*

struct S;
namespace N { using ::S; }
struct N::S {};

*Lets try clang first:*

By compiling it with int main() { ::S s; } we see from the compiler error
that ::S is not a complete type in main. This indicates that the names
introduced by the declarations struct S; and struct N::S {}; denotes
two different entities.

Shouldn't this be a violation of [basic.scope.declarative]p4? Clang still
accept this program. Why?

Regardless of this problem lets continue.

Now let's try int main() { N::S s; } Then we get name-lookup ambiguity
error. This is expected since we have introduced two identical names
denoting different entities in the declarative region of the namespace ::N.

Lets try something more advanced, lets try this variant of the example:

struct S {};
namespace N { int S = 1; using ::S; }

int main() { N::S = 2; }

It compiles fine. This is because of [basic.scope.hiding]p2. Now let's try
the following instead:

struct S;
namespace N { int S = 1; using ::S; }
struct N::S {};

int main() { N::S = 2; }

The result is name-lookup ambiguity! This contradicts
[basic.scope.hiding]p2. Why is this?

*Lets try gcc now:*

By compiling the first example with int main() { ::S s; } we see from
the successful compilation that ::S is a complete type in main. So here gcc
and clang behave differently. This suggests that the names introduced by
struct S; and struct N::S {}; denotes the same entity in the case of
gcc.
On Sun, Jul 5, 2015 at 6:05 PM, Anders Granlund <
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try to
find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
Post by Anders Granlund
I guess we also could conclude that redeclarations can never be made across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which
is marked as also being resolved by 1838. I've filed a core issue to get
the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-07-06 21:40:25 UTC
Permalink
Post by Anders Granlund
Hmm, you are right, things are more complicated.
I like those new examples you gave. Compiling modified versions of your
first example gives some interesting observations. The results confused me.
I used GCC and Clang from http://melpon.org/wandbox with HEAD (trunc) and
c++ 03.
*Your first example:*
struct S;
namespace N { using ::S; }
struct N::S {};
*Lets try clang first:*
By compiling it with int main() { ::S s; } we see from the compiler
error that ::S is not a complete type in main. This indicates that the
names introduced by the declarations struct S; and struct N::S {};
denotes two different entities.
I don't see that; I think this was fixed when I fixed the other issues with
redeclaring a using-declaration. Clang trunk accepts this, and treats
'struct N::S {}' as a definition of ::S.

Shouldn't this be a violation of [basic.scope.declarative]p4? Clang still
Post by Anders Granlund
accept this program. Why?
Regardless of this problem lets continue.
Now let's try int main() { N::S s; } Then we get name-lookup ambiguity
error. This is expected since we have introduced two identical names
denoting different entities in the declarative region of the namespace ::N.
struct S {};
namespace N { int S = 1; using ::S; }
int main() { N::S = 2; }
It compiles fine. This is because of [basic.scope.hiding]p2. Now let's try
struct S;
namespace N { int S = 1; using ::S; }
struct N::S {};
int main() { N::S = 2; }
The result is name-lookup ambiguity! This contradicts
[basic.scope.hiding]p2. Why is this?
You reached an "impossible" state (under [basic.scope.declarative]p4), so
all bets are off.

*Lets try gcc now:*
Post by Anders Granlund
By compiling the first example with int main() { ::S s; } we see from
the successful compilation that ::S is a complete type in main. So here gcc
and clang behave differently. This suggests that the names introduced by
struct S; and struct N::S {}; denotes the same entity in the case of
gcc.
On Sun, Jul 5, 2015 at 6:05 PM, Anders Granlund <
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try
to find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
Post by Anders Granlund
I guess we also could conclude that redeclarations can never be made across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021
which is marked as also being resolved by 1838. I've filed a core issue to
get the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-06 22:07:32 UTC
Permalink
Thanks for the quick issue fixes and explanation. I'll check out clang
trunc.
On Mon, Jul 6, 2015 at 2:26 AM, Anders Granlund <
Post by Anders Granlund
Hmm, you are right, things are more complicated.
I like those new examples you gave. Compiling modified versions of your
first example gives some interesting observations. The results confused me.
I used GCC and Clang from http://melpon.org/wandbox with HEAD (trunc)
and c++ 03.
*Your first example:*
struct S;
namespace N { using ::S; }
struct N::S {};
*Lets try clang first:*
By compiling it with int main() { ::S s; } we see from the compiler
error that ::S is not a complete type in main. This indicates that the
names introduced by the declarations struct S; and struct N::S {};
denotes two different entities.
I don't see that; I think this was fixed when I fixed the other issues
with redeclaring a using-declaration. Clang trunk accepts this, and treats
'struct N::S {}' as a definition of ::S.
Shouldn't this be a violation of [basic.scope.declarative]p4? Clang still
Post by Anders Granlund
accept this program. Why?
Regardless of this problem lets continue.
Now let's try int main() { N::S s; } Then we get name-lookup ambiguity
error. This is expected since we have introduced two identical names
denoting different entities in the declarative region of the namespace ::N.
struct S {};
namespace N { int S = 1; using ::S; }
int main() { N::S = 2; }
It compiles fine. This is because of [basic.scope.hiding]p2. Now let's
struct S;
namespace N { int S = 1; using ::S; }
struct N::S {};
int main() { N::S = 2; }
The result is name-lookup ambiguity! This contradicts
[basic.scope.hiding]p2. Why is this?
You reached an "impossible" state (under [basic.scope.declarative]p4), so
all bets are off.
*Lets try gcc now:*
Post by Anders Granlund
By compiling the first example with int main() { ::S s; } we see from
the successful compilation that ::S is a complete type in main. So here gcc
and clang behave differently. This suggests that the names introduced by
struct S; and struct N::S {}; denotes the same entity in the case of
gcc.
On Sun, Jul 5, 2015 at 6:05 PM, Anders Granlund <
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try
to find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
Post by Anders Granlund
I guess we also could conclude that redeclarations can never be made across different declarative regions?
On Thu, Jul 2, 2015 at 6:09 PM, Anders Granlund <
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021
which is marked as also being resolved by 1838. I've filed a core issue to
get the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-15 23:42:01 UTC
Permalink
Post by Richard Smith
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try to
find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
Post by Richard Smith
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
Aren't the programs above ill-formed according to the c++ standard? (See [std-discussion]
Inconsistency between structs and functions when defining them via
using-declaration)
Post by Richard Smith
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
I guess we also could conclude that redeclarations can never be made across different declarative regions?
Post by Richard Smith
Post by Anders Granlund
Post by Richard Smith
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When trying
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021 which
is marked as also being resolved by 1838. I've filed a core issue to get
the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
.
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-17 03:02:34 UTC
Permalink
Nevermind my last reply reffering to (See [std-discussion] Inconsistency
between structs and functions when defining them via using-declaration). *Here
comes the correct reply:*

I just realised one thing now and it indicates *a bug in clang*. The
following example you gave (the same hold for you other example also, but
lets take one of them to be concrete) *is actually ill-formed:*

struct S;
namespace N { using ::S; }
struct N::S {};

I'll explain later in the reply why it is ill-formed. It compiles however
on clang (just as you said earlier), so this seems to indicate a bug in
clang.

Your point about using-declaration not beeing opaque to redeclaration is
still correct however (this is because as you say that qualified
definitions of namespace members works like normal qualified lookup in
terms of finding the target declaration that we are redeclaring with the
definition. And also because qualified name lookup propagates via
using-delcarations). The first example you gave can be saved like this:

namespace P {
struct S;
}
namespace N {
using P::S;
}
struct N::S {};

Now it is well-defined, and still proves your point.

Now, why is your original example ill-formed? Well the reason is simple:

struct N::S {}; is a qualified namespace member definition and it is a
redeclaration of struct S; just as you said earlier yourself. However this
is the problem. Remember that there are only two ways of defining a
namespace member:

* Either you use an *unqualified* definition in the declarative region of
the namespace. (We don't have this case here since we have a qualified
instead of an unqualified namespace member definition here):
This case is [namespace.memdef]p1 in the c++ standard:
http://eel.is/c++draft/namespace.memdef#1

* Or you use a *qualified* definition *outside *the namespace *in an
enclosing namespace . *We almost have this case in your example, but the
problem is that the qualified namespace member definition struct N::S {}; is
in the *same* namespace (the global namespace) as struct S; and *not
outside it in an enclosing namespace *(not even possible since the global
namespace is the outermost one).
This case is [namespace.memdef]p2 in the c++ standard:
http://eel.is/c++draft/namespace.memdef#2

See the discussion "[std-discussion] Qualified definition of namespace
member in the same namespace as the declaration" for something similar, but
in that case a normal namespace instead of the global namespace and no
middle landing in another namespace in the qualified name-lookup. Otherwise
the same.

Do you agree?
Post by David Rodríguez Ibeas
Post by Richard Smith
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try
to find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
Post by Richard Smith
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
Aren't the programs above ill-formed according to the c++ standard? (See [std-discussion]
Inconsistency between structs and functions when defining them via
using-declaration)
Post by Richard Smith
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
I guess we also could conclude that redeclarations can never be made across different declarative regions?
Post by Richard Smith
Post by Anders Granlund
Post by Richard Smith
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021
which is marked as also being resolved by 1838. I've filed a core issue to
get the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Anders Granlund
2015-07-22 20:54:05 UTC
Permalink
Hmm

namespace P {
struct S;
}
namespace N {
using P::S;
}
struct N::S {};

is actually ill-formed also (at least I think so:
https://llvm.org/bugs/show_bug.cgi?id=24138 ).

Anyways i'll report a bug for

struct S;
namespace N { using ::S; }
struct N::S {};

also. Its probably better to report the bug and see what happens than to
continue this discussion.
Post by Anders Granlund
Nevermind my last reply reffering to (See [std-discussion] Inconsistency
between structs and functions when defining them via using-declaration). *Here
comes the correct reply:*
I just realised one thing now and it indicates *a bug in clang*. The
following example you gave (the same hold for you other example also, but
lets take one of them to be concrete) *is actually ill-formed:*
struct S;
namespace N { using ::S; }
struct N::S {};
I'll explain later in the reply why it is ill-formed. It compiles however
on clang (just as you said earlier), so this seems to indicate a bug in
clang.
Your point about using-declaration not beeing opaque to redeclaration is
still correct however (this is because as you say that qualified
definitions of namespace members works like normal qualified lookup in
terms of finding the target declaration that we are redeclaring with the
definition. And also because qualified name lookup propagates via
namespace P {
struct S;
}
namespace N {
using P::S;
}
struct N::S {};
Now it is well-defined, and still proves your point.
struct N::S {}; is a qualified namespace member definition and it is a
redeclaration of struct S; just as you said earlier yourself. However
this is the problem. Remember that there are only two ways of defining a
* Either you use an *unqualified* definition in the declarative region of
the namespace. (We don't have this case here since we have a qualified
http://eel.is/c++draft/namespace.memdef#1
* Or you use a *qualified* definition *outside *the namespace *in an
enclosing namespace . *We almost have this case in your example, but the
problem is that the qualified namespace member definition struct N::S {}; is
in the *same* namespace (the global namespace) as struct S; and *not
outside it in an enclosing namespace *(not even possible since the global
namespace is the outermost one).
http://eel.is/c++draft/namespace.memdef#2
See the discussion "[std-discussion] Qualified definition of namespace
member in the same namespace as the declaration" for something similar,
but in that case a normal namespace instead of the global namespace and no
middle landing in another namespace in the qualified name-lookup. Otherwise
the same.
Do you agree?
Post by David Rodríguez Ibeas
Post by Richard Smith
Post by Anders Granlund
Thanks for the clarification. I thought it would be a good idea to try
to find compiler bugs by investigating edge cases in the standard, but it
seems like i'm just finding standard defects/ambiguities that way. I'm a
bit chocked about how ambiguous the c++ standard is. Seems to be a lot of
issues reported. I have some questions on stack overflow. I guess most of
them is answered by some c++ standard issue.
If I understand everything correctly. Because of 1838, the following
programs (taken from 1021) should also be ill-formed for the same reason?
The second of them I have actually tried earlier, and it compiles on GCC,
Clang and MSVS, and as you say both of them compiles on major compilers.
namespace N {
struct A;
}
using N::A;
struct A { };
int main() {}
struct S;
namespace A {
using ::S;
struct S { };
}
int main() {}
So this means that the compilers needs to be fixed to emit a diagnostic message for these situations?
Yes; Clang trunk now rejects both of these.
I guess we can conclude that using-declarations should be opaque when it comes to redeclarations, ie redeclarations doesn't work at all via using-declarations?
struct S;
Post by Richard Smith
namespace N { using ::S; }
struct N::S {};
extern int n;
namespace N { using ::n; }
int N::n;
Aren't the programs above ill-formed according to the c++ standard? (See [std-discussion]
Inconsistency between structs and functions when defining them via
using-declaration)
Post by Richard Smith
GCC accepts this, Clang and EDG reject. MSVC crashes.
The idea, last time we discussed this in CWG, was that unqualified
(non-template-id) non-block-scope declarations always declare the entity to
be within the current namespace/class, and qualified declarations (and
template-ids) are always looked up and must find some existing entity (and
must be in a namespace enclosing that entity's namespace). I don't think
that really answers how these new cases should behave, though.
I guess we also could conclude that redeclarations can never be made across different declarative regions?
Post by Richard Smith
Post by Anders Granlund
Post by Richard Smith
Post by Anders Granlund
According to my current understanding of the c++ standard, the
namespace X {
class A;
}
namespace Y {
using X::A;
class A {};
}
int main() {}
Visual studios c++ compiler does not agree with me on this. When
error C2888: 'X::A': symbol cannot be defined within namespace 'Y'
Looking at the description of error C2888 at
https://msdn.microsoft.com/en-us/library/27zksbks.aspx it looks like
they are referring to the following rule of the c++ standard,
Members of a named namespace can also be defined outside that
namespace by explicit qualification ([namespace.qual]) of the name being
defined,
provided that the entity being defined was already declared in the
namespace and the definition appears after the point of declaration in a
namespace
that encloses the declaration's namespace.
My example program is not violating this rule however, since i'm not
even using explicit qualification when I define the class A.
Is there any other rule of the standard that I have missed that my
example program is violating?
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1838,
which replaces the words you referenced above. [That issue (and its wording
change) doesn't apply to class declarations, but it was intended to -- see
the reference to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1021
which is marked as also being resolved by 1838. I've filed a core issue to
get the wording here tweaked to actually address issue 1021.]
Under issue 1838, because 'class A' in namespace Y is declared with an
unqualified name, it declares a member of Y, rather than redeclaring X::A.
there are two different entities named A within namespace Y.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Loading...