namespace A{
int i;
}
int main(){
using A::i;
using A::i;
}
VS2010 - compiles fine
gcc (ideone) - compiles fine
Comeau - gives error ""ComeauTest.c", line 10: error: "i" has already been declared in the current scope
using A::i;"
$7.3.3/8 - "A using-declaration is a
declaration and can therefore be used
repeatedly where (and only where)
multiple declarations are allowed."
The example right there indicates that the code is indeed ill-formed.
So, is this a bug in GCC and VS2010?
EDIT 2:
Remove the multiple using directives as it was unrelated to the query on hand.
The example you refer to is known to be inconsistent. The committee hasn't yet fixed this.
So, is this a bug in GCC and VS2010?
I don't think it's a bug in either of GCC/VS2010/Clang or Comeau. It appears to be a bug in the C++ Standard. In these cases, compile writers have to make up their mind on what is most viable. If you remove the example in question, then 3.3/4 states the example is valid: "Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, ... they shall all refer to the same entity, or all refer to functions and function templates; or ...".
The question arises, as discussed in the linked issue, what 7.3.3/8 refers to when it says "declarations", which the committee didn't reach consensus about. And so, until then 3.3/4 applies for GCC/VS2010 and Clang, while Comeau chooses to use some other semantics.
Yes you are right. This is indeed a bug in g++, MSVC++ and Clang. Comeau has got it correct.
As you said 7.3.3/8 says
A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed
The following code snippet is also given.
void f()
{
using A::i;
using A::i; //error: double declaration
}
Similarly your code is ill-formed too.
Related
I installed Visual Studio 2015 and found that some of my code (that hadn't any problems in VS 2013) now has got some errors indicated by green squiggles (which are supposed to be a new productivity feature). Yet the code still compiles successfully.
Here's a quick example:
namespace
{
void test1(); // what once was OK in VS 2013,
void test2(); // is now marked with squiggles in VS 2015
}
namespace named
{
void test3(); // OK, no problem
}
void test1() { /*...*/ }
void ::test2() { /*...*/ }
void named::test3() { /*...*/ }
int main() { /*...*/ }
Theese are the squiggles in question
Moving the mouse over them tells me that
Function definition for 'test1' not found
Function definition for 'test2' not found
Somehow it turns out that only functions declared inside unnamed namespace trigger the squiggles.
How is it supposed to be resolved?
The green squiggles don't tell you that there's an error, they tell you that there's an opportunity for the new refactoring tools to do something. (Red squiggles indicate an error.) In this case, they're informing you that there is no definition matching the declaration of test2, so the IDE is offering to generate one.
This happens to point out an error that was always there in the code, although Visual Studio might be behaving in a non-conforming manner.
So what happens? The problem is that the declarations in the unnamed namespace do not declare the same functions that you later define in the global namespace. The refactoring tools recognize this and offer to generate a definition for the declared functions.
However, the whole thing still compiles, due to the Microsoft compiler accepting two strictly illegal pieces of code. First, using the namespace prefix on the first declaration of a function is not allowed. The code in main then presumably calls the functions. As Alex M showed in his answer, GCC won't accept this either, since the call is ambiguous. The Microsoft compiler appears to accept it, either treating the definition as a definition matching the declaration in the unnamed namespace (remember, the tools of the IDE, IntelliSense and the refactory, used the more compliant EDG front-end, not the parser the actual compiler uses, which means that the refactory can say that the declaration has no definition, while the compiler treats the definition as matching the declaration), or just preferring the global version to the namespaced version.
It's easy to distinguish the two cases, by the way. Rearrange the code so that main comes before the function definitions. This will resolve the ambiguity in GCC, because only the namespaced function is declared (and not defined, so you should get a linker error). It will also lead to a linker error in the Microsoft compiler, if it just prefers the global version, but will still compile if it treats the declaration and definition as matching.
The solution to all this is very simple: when defining functions declared in the unnamed namespace, just reopen the namespace instead of trying to define the functions outside.
This compiles OK, with the light bulb you mentioned:
namespace
{
void func();
}
void ::func() //Will not compile if 'void func()'
{}
int main()
{
func();
}
But IntelliSense also outputs (in both cases):
Error (active) more than one instance of overloaded function "func"
matches the argument list:
function "func()"
function "<unnamed>::func()"
Is this really what you want to do though? As n4527 at § 7.3.1.1 states:
An unnamed-namespace-definition behaves as if it were replaced by
inline(opt) namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body }
where inline appears if and only if it appears in the
unnamed-namespace-definition and all occurrences of unique in a translation unit are replaced by the same identifier, and this
identifier differs from all other identifiers in the translation unit.
Which makes it clear why there are ambiguities going on. Just define your methods within your unnamed namespace, as they're different from anything else outside it.
For the record, GCC 5.2.0 and clang 3.6.0 won't agree to compile the code that MSVC compiled.
I ran across some legacy code that's failing to build on a newer compiler. The boiled down example:
int x;
extern "C" { int x }; // conflicts with C++ linkage above
// note: without the braces it would've been equivalent to:
// extern "C" { extern int x; }
//
// for reference, see the notes section here:
// http://en.cppreference.com/w/cpp/language/language_linkage#notes
The older compilers weren't flagging it, but both gcc (as of 4.1.2) and clang flag it.
Clang's output:
error: declaration of 'x' has different language linkage
GCC's output:
error: previous declaration of 'int x' with 'C++' linkage
error: conflicts with new declaration with 'C' linkage
This surprised me because the compiler doesn't mangle x in any special way, and as far as I can tell nothing is different about the object file other than debug information (based on my admittedly shallow test with objdump/readelf)
My question: why is this an error if there's no functional difference?
As an aside, I'm not averse to changing the code; I wanted to know whether there was something more going on than just "the standard says this is ill formed".
I looked through the various *stack sites and mostly found questions on this topic relating to functions with conflicting linkage specifications.
I found my [first] answer in the gcc bugzilla database:
The standard says in 7.5/5: "If two declarations of the same function or object specify different linkage-specifications [...] the program is ill-formed if the declarations appear in the same translation unit [...]". That is why code like that in comment 6 is now rejected.
Whether my supposition is correct (about the functional difference between C/C++ linkage for POD variables) or not, it appears the error is intended to prevent bad style.
Then I found this article about storage class specifiers and one about language linkage. I didn't see anything in those articles conflicting with what I've learned so far; the 2nd one says:
Likewise, two variables in the same namespace cannot have two different language linkages.
Is the following program well-formed or ill-formed according to the c++ standard?
namespace X { int i; }
namespace Y { using X::i; }
int main() { using X::i; using Y::i; }
I'm getting different results with different compilers:
MSVS: Compiles ( http://webcompiler.cloudapp.net/ )
Clang: Compiles ( http://melpon.org/wandbox/permlink/KloDufJ5h1DalK4v )
GCC: Compile error ( http://melpon.org/wandbox/permlink/IKuuQGE1THofuUTr )
I don't want to fix this program to make it compile on GCC. I just want to know what the c++ standard says about this and why the three compilers behave differently. Also I want to if this is a result of a bug in any of these compilers.
The program should not compile because it declares X::i twice in the same block scope.
C++14 §7.3.3/10:
” A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple
declarations are allowed. [Example:
namespace A {
int i;
}
namespace A1 {
using A::i;
using A::i; // OK: double declaration
}
void f() {
using A::i;
using A::i; // error: double declaration
}
Edit: The non-normative comment quoted above, and which I thought answered the question, was there originally in C++98 and has survived through Technical Corrigendum 1 (C++03), C++11 and C++14. But apparently it's wrong. Richard Smith in his answer cites core issue 36 about it, first raised by Andrew Koenig on 2nd August 1998 (less than a month after ANSI approval of the first standard), which apparently means that a known incorrect comment can survive three revisions of the standard.
Citing the core issue itself about that:
C++ Standard Core Language Active Issues, issue 36:
” Notes from 04/00 meeting:
The core language working group was unable to come to consensus over what kind of declaration a using-declaration should emulate. In a straw poll, 7 members favored allowing using-declarations wherever a non-definition declaration could appear, while 4 preferred to allow multiple using-eclarations only in namespace scope (the rationale being that the permission for multiple using-declarations is primarily to support its use in multiple header files, which are seldom included anywhere other than namespace scope). John Spicer pointed out that friend declarations can appear multiple times in class scope and asked if using-declarations would have the same property under the "like a declaration" resolution.
As a result of the lack of agreement, the issue was returned to "open" status.
The general discussion of multiple declarations of the same name is in §3.3.1/4 in both C++98 and C++14. As far as I can see the C++14 text is verbatim identical to the original C++98 text. And by itself it allows declaring the same name multiple times in the same declarative region in a number of cases, one of which is that all the declarations refer to the same entity:
C++14 §3.3.1/4:
” Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,
they shall all refer to the same entity, or all refer to functions and function templates; or
exactly one declaration shall declare a class name or enumeration name that is not a typedef name
and the other declarations shall all refer to the same variable or enumerator, or all refer to functions
and function templates; in this case the class name or enumeration name is hidden (3.3.10). [Note: A
namespace name or a class template name must be unique in its declarative region (7.3.2, Clause 14). —end note]
However, the wording here only says what is not directly invalid. A declaration can be disallowed by other rules even if it's not disallowed by this one. For example, there is such a restriction for class member declarations:
C++14 §9.2/1:
” […] A member shall not be declared twice in the member-
specification, except that a nested class or member class template can be declared and then later defined,
and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared
with an enum-specifier.
I fail to find such a restriction that supports the apparently incorrect comment in C++14 §7.3.3/10 quoted at the start above, i.e. I fail to find any special treatment of block scopes or namespace scopes, and so a tentative conclusion (keeping in mind the comment's survival in spite of being contested already in 1998) is that the contested comment actually is wrong and that this question's code, where two declarations in the same declarative region refer to the same entity, is valid and should be accepted by all compilers.
Clang and MSVC are correct; this code is valid. As Alf notes, [namespace.udecl] (7.3.3)/10 says
A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed.
However, there is no restriction on multiple declarations of the same entity in block scope, so the original example is valid. A corresponding case not involving using-declarations is:
int n;
void f() {
extern int n;
extern int n;
}
This is valid (and is accepted by GCC, EDG, Clang, and MSVC), therefore (by the above-quoted rule) the original example is also valid.
It is worth noting that the example in [namespace.udecl] (7.3.3)/10 contains an error. It says:
namespace A {
int i;
}
void f() {
using A::i;
using A::i; // error: double declaration
}
... but the comment is not correct; there is no error on the second declaration. See the discussion in core issue 36. I've removed the example from the standard so that it won't confuse more people.
namespace A{
int i;
}
int main(){
using A::i;
using A::i;
}
VS2010 - compiles fine
gcc (ideone) - compiles fine
Comeau - gives error ""ComeauTest.c", line 10: error: "i" has already been declared in the current scope
using A::i;"
$7.3.3/8 - "A using-declaration is a
declaration and can therefore be used
repeatedly where (and only where)
multiple declarations are allowed."
The example right there indicates that the code is indeed ill-formed.
So, is this a bug in GCC and VS2010?
EDIT 2:
Remove the multiple using directives as it was unrelated to the query on hand.
The example you refer to is known to be inconsistent. The committee hasn't yet fixed this.
So, is this a bug in GCC and VS2010?
I don't think it's a bug in either of GCC/VS2010/Clang or Comeau. It appears to be a bug in the C++ Standard. In these cases, compile writers have to make up their mind on what is most viable. If you remove the example in question, then 3.3/4 states the example is valid: "Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, ... they shall all refer to the same entity, or all refer to functions and function templates; or ...".
The question arises, as discussed in the linked issue, what 7.3.3/8 refers to when it says "declarations", which the committee didn't reach consensus about. And so, until then 3.3/4 applies for GCC/VS2010 and Clang, while Comeau chooses to use some other semantics.
Yes you are right. This is indeed a bug in g++, MSVC++ and Clang. Comeau has got it correct.
As you said 7.3.3/8 says
A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed
The following code snippet is also given.
void f()
{
using A::i;
using A::i; //error: double declaration
}
Similarly your code is ill-formed too.
I'm trying to figure out whether to file a bug report against Clang, GCC, or both (I've tested against Clang trunk and GCC 4.7.2: if someone could verify this against GCC trunk that would be helpful):
Basically, the following code three-line file compiles fine with -fsyntax-only, in default and C++11 modes:
class A {
friend void f();
};
Note that there's no prior declaration of f(), but this is explicitly OK.
However, Clang (but not GCC) rejects the following:
class A {
friend void ::f();
};
The error from Clang is "no function named 'f' with type 'void ()' was found in the specified scope", but I can't find any justification in the standard for treating this case differently than the previous one, so I think it's a bug; I might be wrong though (I'm reading from N3242, however, which AFAIK is the last public draft before C++11).
This next example, however, is rejected by GCC rather than Clang:
void f() { }
void g()
{
class A {
friend void ::f();
};
}
The error from GCC is "friend declaration ‘void f()’ in local class without prior declaration", which doesn't seem to make sense since void ::f() should refer to the f() in the global namespace, which is declared. (Never mind that friend-ing a global function from a local class is nonsensical, it doesn't seem to be illegal...)
Finally, this last example is rejected both by Clang and GCC:
void g()
{
class A {
friend void ::f();
};
}
The errors are "friend declaration ‘void f()’ in local class without prior declaration" and "no function named 'f' with type 'void ()' was found in the specified scope", respectively. Now, there does appear to be some justification for rejecting a friend declaration of a previously undeclared function in a local class, from 11.4p11, but the paragraph actually reads:
If a friend declaration appears in a local class (9.8) and the name specified is an unqualified name, a prior
declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope.
For a friend function declaration, if there is no prior declaration, the program is ill-formed...
The illegality of this declaration apparently is based on the second sentence in this paragraph, but it's unclear to me whether the sentence should apply in the case of a qualified name as well, as is used in this case. (Arguably, it could be that the entire paragraph applies to the "local class" case regardless of whether or not an "unqualified name" is used, and the "and the name specified is an unqualified name" clause only applies to the lookup described in the first sentence, but it seems like a stretch...the only reason I'm imagining this as a possibility is because both compilers reject it.)
Anyway, so from what I can tell, all four of these cases (regardless of how sensible they are or not) should be legal; even if not, at least one of Clang and GCC is wrong in the second and third cases. Can anyone find an error in my logic?
The third and fourth cases are admittedly nonsensical; but I can see the second case breaking someone's valid and useful code so I'm somewhat surprised it's never been caught, if it is indeed a bug.
I think this sentence from 8.3/1 is relevant:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1)) or to a specialization thereof; the member shall not merely have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id.
The paragraph is talking about declarators in general, in any type of declaration. So I think examples 2 and 4 are ill-formed, clang is correct, and gcc is wrong.
(Example 3 might become more realistic if the global declaration were a template function. It might be useful to friend a global function template or a specialization from a local class. And if that's allowed, your example 3 as written might as well be legal for consistency.)