Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Comeau and G++ disagree. Compiler bug?

Reply
Thread Tools

Comeau and G++ disagree. Compiler bug?

 
 
Alan Woodland
Guest
Posts: n/a
 
      08-12-2007
Hi,

I was trying to come up with obscure C++ questions in the style of GoTW
and ran across this unexpected difference between G++ and comeau. Can
anyone point me in the direction of the correct result for this program?


#include <iostream>

namespace A {
class Foo { };
struct f {
public:
f(const Foo& f) { std::cout << "ctor" << std::endl; }
};
}

template <typename T>
void f(const T& t) { std::cout << "Template ref" << std::endl; }

void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }

int main() {
f(A::Foo());
return 0;
}

G++ doesn't accept it and says:
test.cc: In function 'int main()':
test.cc:5: error: 'struct A::f' is not a function,
test.cc:14: error: conflict with 'void f(A::Foo&)'
test.cc:17: error: in call to 'f'
G++ version was:
g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Whereas Comeau allows it (I only tried it online, so I don't for certain
know what f(A::Foo()); actually resolved to. Comeau version was:
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

Thanks,
Alan
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      08-12-2007
Alan Woodland wrote:
> I was trying to come up with obscure C++ questions in the style of
> GoTW and ran across this unexpected difference between G++ and
> comeau. Can anyone point me in the direction of the correct result
> for this program?
>
>
> #include <iostream>
>
> namespace A {
> class Foo { };
> struct f {
> public:
> f(const Foo& f) { std::cout << "ctor" << std::endl; }
> };
> }
>
> template <typename T>
> void f(const T& t) { std::cout << "Template ref" << std::endl; }
>
> void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }
>
> int main() {
> f(A::Foo());
> return 0;
> }
>
> G++ doesn't accept it and says:
> test.cc: In function 'int main()':
> test.cc:5: error: 'struct A::f' is not a function,
> test.cc:14: error: conflict with 'void f(A::Foo&)'
> test.cc:17: error: in call to 'f'
> G++ version was:
> g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
> Copyright (C) 2006 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There
> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
>
> Whereas Comeau allows it (I only tried it online, so I don't for
> certain know what f(A::Foo()); actually resolved to. Comeau version
> was:
> Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
> Copyright 1988-2007 Comeau Computing. All rights reserved.
> MODE:strict errors C++ noC++0x_extensions


AFAICT, G++ is mistaken. It cannot be a construction of a temporary
of type 'f', types are not found using ADL for this syntax. In order
to look 'f' up using ADL, it has to be deemed a function call. By the
time ADL is employed, the syntax 'f(A::Foo())' cannot be "explicit type
conversion (functional notation)". It only can be "type conversion" if
'f' is already deduced as a type, which it cannot be since 'A::f' type
is not visible.

That aside, it cannot be 'f(A::Foo&)' since the reference to a non-const
'A::Foo' cannot be bound to a temporary ('A::Foo()'), which leaves the
only choice: the template. Now, if you change the "plain ref" function
to

void f(A::Foo const&);

then it will be chosen over the template since in rules of the overload
resolution a non-template function is always preferred over a template
instantiation.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
Alan Woodland
Guest
Posts: n/a
 
      08-12-2007
Victor Bazarov wrote:
> Alan Woodland wrote:
>> #include <iostream>
>>
>> namespace A {
>> class Foo { };
>> struct f {
>> public:
>> f(const Foo& f) { std::cout << "ctor" << std::endl; }
>> };
>> }
>>
>> template <typename T>
>> void f(const T& t) { std::cout << "Template ref" << std::endl; }
>>
>> void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }
>>
>> int main() {
>> f(A::Foo());
>> return 0;
>> }
>>
>> G++ doesn't accept it and says:
>> test.cc: In function 'int main()':
>> test.cc:5: error: 'struct A::f' is not a function,
>> test.cc:14: error: conflict with 'void f(A::Foo&)'
>> test.cc:17: error: in call to 'f'
>> G++ version was:
>> g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
>> Copyright (C) 2006 Free Software Foundation, Inc.
>> This is free software; see the source for copying conditions. There
>> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
>> PARTICULAR PURPOSE.

>
> AFAICT, G++ is mistaken. It cannot be a construction of a temporary
> of type 'f', types are not found using ADL for this syntax. In order
> to look 'f' up using ADL, it has to be deemed a function call. By the
> time ADL is employed, the syntax 'f(A::Foo())' cannot be "explicit type
> conversion (functional notation)". It only can be "type conversion" if
> 'f' is already deduced as a type, which it cannot be since 'A::f' type
> is not visible.
>
> That aside, it cannot be 'f(A::Foo&)' since the reference to a non-const
> 'A::Foo' cannot be bound to a temporary ('A::Foo()'), which leaves the
> only choice: the template. Now, if you change the "plain ref" function
> to
>
> void f(A::Foo const&);
>
> then it will be chosen over the template since in rules of the overload
> resolution a non-template function is always preferred over a template
> instantiation.

Thanks,

The non-const reference and temporary was deliberately designed to catch
someone out after a previous question where it had been const and the
version of f in namespace A had been a function to illustrate Koenig
lookup. I wasn't 100% sure it would pick the function over the
constructor for f though.

Am I right in thinking non-const temporary reference binding will be
changing in C++0X? Or am I getting confused? I seem to recall reading
something about it a while back.

I'll be filing a bug against g++ shortly given that g++ (GCC) 4.3.0
20070720 also seems to have this problem.

Alan
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      08-12-2007
Alan Woodland wrote:
> Victor Bazarov wrote:
>> Alan Woodland wrote:
>>> #include <iostream>
>>>
>>> namespace A {
>>> class Foo { };
>>> struct f {
>>> public:
>>> f(const Foo& f) { std::cout << "ctor" << std::endl; }
>>> };
>>> }
>>>
>>> template <typename T>
>>> void f(const T& t) { std::cout << "Template ref" << std::endl; }
>>>
>>> void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }
>>>
>>> int main() {
>>> f(A::Foo());
>>> return 0;
>>> }
>>>
>>> G++ doesn't accept it and says:
>>> test.cc: In function 'int main()':
>>> test.cc:5: error: 'struct A::f' is not a function,
>>> test.cc:14: error: conflict with 'void f(A::Foo&)'
>>> test.cc:17: error: in call to 'f'
>>> G++ version was:
>>> g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
>>> Copyright (C) 2006 Free Software Foundation, Inc.
>>> This is free software; see the source for copying conditions. There
>>> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
>>> PARTICULAR PURPOSE.

>>
>> AFAICT, G++ is mistaken. It cannot be a construction of a temporary
>> of type 'f', types are not found using ADL for this syntax. In order
>> to look 'f' up using ADL, it has to be deemed a function call. By
>> the time ADL is employed, the syntax 'f(A::Foo())' cannot be
>> "explicit type conversion (functional notation)". It only can be
>> "type conversion" if 'f' is already deduced as a type, which it
>> cannot be since 'A::f' type is not visible.
>>
>> That aside, it cannot be 'f(A::Foo&)' since the reference to a
>> non-const 'A::Foo' cannot be bound to a temporary ('A::Foo()'),
>> which leaves the only choice: the template. Now, if you change the
>> "plain ref" function to
>>
>> void f(A::Foo const&);
>>
>> then it will be chosen over the template since in rules of the
>> overload resolution a non-template function is always preferred over
>> a template instantiation.

> Thanks,
>
> The non-const reference and temporary was deliberately designed to
> catch someone out after a previous question where it had been const
> and the version of f in namespace A had been a function to illustrate
> Koenig lookup. I wasn't 100% sure it would pick the function over the
> constructor for f though.
>
> Am I right in thinking non-const temporary reference binding will be
> changing in C++0X? Or am I getting confused? I seem to recall reading
> something about it a while back.


Not that I know of. There is a new concept being introduced, an rvalue
reference (declaration syntax '&&'). But you can't initialise a regular
reference to non-const object with a temporary, still.

> I'll be filing a bug against g++ shortly given that g++ (GCC) 4.3.0
> 20070720 also seems to have this problem.


I would wait a couple of days... I have a sneaky feeling James Kanze
will want to chime in. <g>

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-13-2007
On Aug 12, 11:06 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:
> Alan Woodland wrote:
> > I was trying to come up with obscure C++ questions in the style of
> > GoTW and ran across this unexpected difference between G++ and
> > comeau. Can anyone point me in the direction of the correct result
> > for this program?


> > #include <iostream>


> > namespace A {
> > class Foo { };
> > struct f {
> > public:
> > f(const Foo& f) { std::cout << "ctor" << std::endl; }
> > };
> > }


> > template <typename T>
> > void f(const T& t) { std::cout << "Template ref" << std::endl; }


> > void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }


> > int main() {
> > f(A::Foo());
> > return 0;
> > }


> > G++ doesn't accept it and says:
> > test.cc: In function 'int main()':
> > test.cc:5: error: 'struct A::f' is not a function,
> > test.cc:14: error: conflict with 'void f(A::Foo&)'
> > test.cc:17: error: in call to 'f'
> > G++ version was:
> > g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
> > Copyright (C) 2006 Free Software Foundation, Inc.
> > This is free software; see the source for copying conditions. There
> > is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> > PARTICULAR PURPOSE.


> > Whereas Comeau allows it (I only tried it online, so I don't for
> > certain know what f(A::Foo()); actually resolved to. Comeau version
> > was:
> > Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
> > Copyright 1988-2007 Comeau Computing. All rights reserved.
> > MODE:strict errors C++ noC++0x_extensions


> AFAICT, G++ is mistaken. It cannot be a construction of a temporary
> of type 'f', types are not found using ADL for this syntax. In order
> to look 'f' up using ADL, it has to be deemed a function call. By the
> time ADL is employed, the syntax 'f(A::Foo())' cannot be "explicit type
> conversion (functional notation)". It only can be "type conversion" if
> 'f' is already deduced as a type, which it cannot be since 'A::f' type
> is not visible.


That may have been the intent---in fact, it probably was, since
the current draft has been changed to state explicitly that ADL
will ignore any names that aren't names of functions. But I'm
not sure that it's that clear in the currently official version
of the standard; it's one of those things which can be
interpreted in different ways. If I interpret the error message
from g++ correctly, it's saying that ADL was applied because
the expression was a function call, and then the results of
function overload resolution meant that it wasn't a function;
the official standard isn't too clear about what to do in this
case, so they treated it as an error.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-13-2007
On Aug 12, 11:57 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:
> Alan Woodland wrote:
> > I'll be filing a bug against g++ shortly given that g++ (GCC) 4.3.0
> > 20070720 also seems to have this problem.


> I would wait a couple of days... I have a sneaky feeling James Kanze
> will want to chime in. <g>


Obviously. In this case, I don't find the standard as clear
as you do (but your interpretation is definitly one possible
one, and probably the intended one), so I wouldn't treat g++ too
harshly; they may just have interpreted the standard
differently. The current draft, however, adds an additional
qualification to ADL which says, literally "All names except
those of (possibly overloaded) functions and function templates
are ignored." So I'm sure that whatever the original reasons
why g++ behaves as it does, they'll want to change it to conform
to what the future standard will say.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
bnonaj
Guest
Posts: n/a
 
      08-13-2007
James Kanze wrote:
> On Aug 12, 11:57 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:
>> Alan Woodland wrote:
>>> I'll be filing a bug against g++ shortly given that g++ (GCC) 4.3.0
>>> 20070720 also seems to have this problem.

>
>> I would wait a couple of days... I have a sneaky feeling James Kanze
>> will want to chime in. <g>

>
> Obviously. In this case, I don't find the standard as clear
> as you do (but your interpretation is definitly one possible
> one, and probably the intended one), so I wouldn't treat g++ too
> harshly; they may just have interpreted the standard
> differently. The current draft, however, adds an additional
> qualification to ADL which says, literally "All names except
> those of (possibly overloaded) functions and function templates
> are ignored." So I'm sure that whatever the original reasons
> why g++ behaves as it does, they'll want to change it to conform
> to what the future standard will say.
>
> --
> James Kanze (GABI Software) email:
> Conseils en informatique orientée objet/
> Beratung in objektorientierter Datenverarbeitung
> 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
>

I think we're all grateful for both Victor and James. They both make a
lot of valuable contributions to this newsgroup. As for the G++ compiler
flagging an error, that is what I would have expected, and I'm indebted
to Victor and James for pointing out the lack of clarity in the current
C++ standard on this point. Keep up the good work, I certainly
appreciate it and hopefully it improves my C++ knowledge reading the
feedback given on this newsgroup.

JB
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      08-13-2007
James Kanze wrote:
> On Aug 12, 11:06 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:
>> Alan Woodland wrote:
>>> I was trying to come up with obscure C++ questions in the style of
>>> GoTW and ran across this unexpected difference between G++ and
>>> comeau. Can anyone point me in the direction of the correct result
>>> for this program?

>
>>> #include <iostream>

>
>>> namespace A {
>>> class Foo { };
>>> struct f {
>>> public:
>>> f(const Foo& f) { std::cout << "ctor" << std::endl; }
>>> };
>>> }

>
>>> template <typename T>
>>> void f(const T& t) { std::cout << "Template ref" << std::endl; }

>
>>> void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }

>
>>> int main() {
>>> f(A::Foo());
>>> return 0;
>>> }

>
>>> G++ doesn't accept it and says:
>>> test.cc: In function 'int main()':
>>> test.cc:5: error: 'struct A::f' is not a function,
>>> test.cc:14: error: conflict with 'void f(A::Foo&)'
>>> test.cc:17: error: in call to 'f'
>>> G++ version was:
>>> g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
>>> Copyright (C) 2006 Free Software Foundation, Inc.
>>> This is free software; see the source for copying conditions. There
>>> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
>>> PARTICULAR PURPOSE.

>
>>> Whereas Comeau allows it (I only tried it online, so I don't for
>>> certain know what f(A::Foo()); actually resolved to. Comeau version
>>> was:
>>> Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for
>>> ONLINE_EVALUATION_BETA1 Copyright 1988-2007 Comeau Computing. All
>>> rights reserved. MODE:strict errors C++ noC++0x_extensions

>
>> AFAICT, G++ is mistaken. It cannot be a construction of a temporary
>> of type 'f', types are not found using ADL for this syntax. In order
>> to look 'f' up using ADL, it has to be deemed a function call. By
>> the time ADL is employed, the syntax 'f(A::Foo())' cannot be
>> "explicit type conversion (functional notation)". It only can be
>> "type conversion" if 'f' is already deduced as a type, which it
>> cannot be since 'A::f' type is not visible.

>
> That may have been the intent---in fact, it probably was, since
> the current draft has been changed to state explicitly that ADL
> will ignore any names that aren't names of functions. But I'm
> not sure that it's that clear in the currently official version
> of the standard; it's one of those things which can be
> interpreted in different ways. If I interpret the error message
> from g++ correctly, it's saying that ADL was applied because
> the expression was a function call, and then the results of
> function overload resolution meant that it wasn't a function;
> the official standard isn't too clear about what to do in this
> case, so they treated it as an error.


According to the new draft, if 'f' were an object with an overloaded
function call operator:

namespace A {
class Foo { };
struct ff {
public:
void operator()(const Foo&)
{ std::cout << "operator()" << std::endl; }
} f;
}

void f(const A::Foo&) { std::cout << "regular func" << std::endl; }

int main() {
f(A::Foo());
return 0;
}

, it wouldn't have been found either, but I am not sure about the
current wording (or GNU folks' interpretation of it). I don't have
G++ to try this one, but VC++ and Comeau online accept it.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
Alan Woodland
Guest
Posts: n/a
 
      08-13-2007
>>> AFAICT, G++ is mistaken. It cannot be a construction of a temporary
>>> of type 'f', types are not found using ADL for this syntax. In order
>>> to look 'f' up using ADL, it has to be deemed a function call. By
>>> the time ADL is employed, the syntax 'f(A::Foo())' cannot be
>>> "explicit type conversion (functional notation)". It only can be
>>> "type conversion" if 'f' is already deduced as a type, which it
>>> cannot be since 'A::f' type is not visible.

>> That may have been the intent---in fact, it probably was, since
>> the current draft has been changed to state explicitly that ADL
>> will ignore any names that aren't names of functions. But I'm
>> not sure that it's that clear in the currently official version
>> of the standard; it's one of those things which can be
>> interpreted in different ways. If I interpret the error message
>> from g++ correctly, it's saying that ADL was applied because
>> the expression was a function call, and then the results of
>> function overload resolution meant that it wasn't a function;
>> the official standard isn't too clear about what to do in this
>> case, so they treated it as an error.

>
> According to the new draft, if 'f' were an object with an overloaded
> function call operator:
>
> namespace A {
> class Foo { };
> struct ff {
> public:
> void operator()(const Foo&)
> { std::cout << "operator()" << std::endl; }
> } f;
> }
>
> void f(const A::Foo&) { std::cout << "regular func" << std::endl; }
>
> int main() {
> f(A::Foo());
> return 0;
> }
>
> , it wouldn't have been found either, but I am not sure about the
> current wording (or GNU folks' interpretation of it). I don't have
> G++ to try this one, but VC++ and Comeau online accept it.


Looks like this one doesn't work either:

g++-4.1 -Wall -std=c++98 /tmp/test.cc

/tmp/test.cc: In function 'int main()':
/tmp/test.cc:9: error: 'A::f' is not a function,
/tmp/test.cc:12: error: conflict with 'void f(const A::Foo&)'
/tmp/test.cc:15: error: in call to 'f'

Alan
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-13-2007
On Aug 13, 2:04 pm, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:

[...]
> According to the new draft, if 'f' were an object with an overloaded
> function call operator:


> namespace A {
> class Foo { };
> struct ff {
> public:
> void operator()(const Foo&)
> { std::cout << "operator()" << std::endl; }
> } f;
> }


> void f(const A::Foo&) { std::cout << "regular func" << std::endl; }


> int main() {
> f(A::Foo());
> return 0;
> }


> , it wouldn't have been found either, but I am not sure about the
> current wording (or GNU folks' interpretation of it). I don't have
> G++ to try this one, but VC++ and Comeau online accept it.


That's a good point. I think that in the current standard, that
is clearly legal. The fact that the draft makes it illegal
could break some code, and possibly wasn't intended. Maybe
someone should raise the point in comp.std.c++. (I'm leaving on
vacation very shortly, and will be off line for close to three
weeks, or I'd do it myself.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is a bug with Comeau or I miss something as Comeau says? Rasmus Johansen C++ 4 10-18-2007 04:43 PM
Where do I download Comeau compiler. Miroslaw Makowiecki C++ 51 08-14-2007 01:05 PM
Where do I download Comeau compiler. Miroslaw Makowiecki C++ 1 08-01-2007 08:37 AM
Compliant compiler? Comeau? nicdude C++ 12 01-04-2006 04:51 PM
Comeau compiler Joe C++ 3 06-04-2005 11:52 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57