Compiler Problem

G

Guest

I recently decided to do the right thing & write accessor functions for my
class member variables instead of having them public and introduced a rather
nasty bug. The class below shows the error - basically if you forget to add
the parenthesis in the call to function X() then the program compiles ok with
no warnings but gives the wrong answer :(

I'm using VS2005 Prof edition v2.0.50727

The answer seems to be that if you are writing accessor functions then don't
use overloaded functions - maybe use setX & getX instead - or make sure you
don't forget the parenthesis! It seems to think I want a function pointer(?)
but I think it should at least give a warning.

class Test {
public:
Test() : m_Num(10) {}

void X(const double val) {m_Num = val;}

double X(void) {return m_Num;};

private:
double m_Num;
};

int _tmain(int argc, _TCHAR* argv[])
{
Test t;
double y = 5.0;
double z;

// z = t.X // this will generate an error
z = t.X * y; // this will generate no error or warning but won't call t.X()

return 0;
}

I've googled for this but am surprised I've not seen more issues with this
 
T

Tamas Demjen

murphman said:
class Test {
public:
Test() : m_Num(10) {}

void X(const double val) {m_Num = val;}

double X(void) {return m_Num;};

private:
double m_Num;
};

int _tmain(int argc, _TCHAR* argv[])
{
Test t;
double y = 5.0;
double z;

// z = t.X // this will generate an error
z = t.X * y; // this will generate no error or warning but won't call t.X()

This is a compiler bug, this code shouldn't compile, it's definitely an
error, not even a warning. If I remove one of the "X" overloads, I
properly get the error message. I went to dinkumware.com, and tried to
compile it online. The EDG front-end gives an error. Heck, even VC++ 7.1
gives an error. My Borland C++Builder 6.0 doesn't want to compile it
either. No compiler should. The overload somehow confuses VC++ 8.

Can you file a bug report at MS?

P.S. I haven't tried VC++ 2006 (Beta 1). It may be fixed there, I can't
verify it.

Tom
 
G

Guest

Thanks - I'll file a bug report
Cheers
Joe

Tamas Demjen said:
murphman said:
class Test {
public:
Test() : m_Num(10) {}

void X(const double val) {m_Num = val;}

double X(void) {return m_Num;};

private:
double m_Num;
};

int _tmain(int argc, _TCHAR* argv[])
{
Test t;
double y = 5.0;
double z;

// z = t.X // this will generate an error
z = t.X * y; // this will generate no error or warning but won't call t.X()

This is a compiler bug, this code shouldn't compile, it's definitely an
error, not even a warning. If I remove one of the "X" overloads, I
properly get the error message. I went to dinkumware.com, and tried to
compile it online. The EDG front-end gives an error. Heck, even VC++ 7.1
gives an error. My Borland C++Builder 6.0 doesn't want to compile it
either. No compiler should. The overload somehow confuses VC++ 8.

Can you file a bug report at MS?

P.S. I haven't tried VC++ 2006 (Beta 1). It may be fixed there, I can't
verify it.

Tom
 
D

Doug Harrison [MVP]

murphman said:
class Test {
public:
Test() : m_Num(10) {}

void X(const double val) {m_Num = val;}

double X(void) {return m_Num;};

private:
double m_Num;
};

int _tmain(int argc, _TCHAR* argv[])
{
Test t;
double y = 5.0;
double z;

// z = t.X // this will generate an error
z = t.X * y; // this will generate no error or warning but won't call t.X()

This is a compiler bug, this code shouldn't compile, it's definitely an
error, not even a warning. If I remove one of the "X" overloads, I
properly get the error message. I went to dinkumware.com, and tried to
compile it online. The EDG front-end gives an error. Heck, even VC++ 7.1
gives an error. My Borland C++Builder 6.0 doesn't want to compile it
either. No compiler should. The overload somehow confuses VC++ 8.

Yep, t.X has no meaning in Standard C++, but earlier versions allowed it to
mean pointer to member. MS fixed this in VC7, but it looks like VC8 has
suffered a regression here.
 
T

Tamas Demjen

Doug said:
Yep, t.X has no meaning in Standard C++, but earlier versions allowed it to
mean pointer to member. MS fixed this in VC7, but it looks like VC8 has
suffered a regression here.

Only when there's an overload. If I remove either one of the X
functions, the compiler shows an error as expected, just like VC7. It
looks like an overloaded function declaration causes the compiler to
accept the object.Method expression without an error.

Tom
 
B

Ben Voigt

Tamas Demjen said:
Only when there's an overload. If I remove either one of the X functions,
the compiler shows an error as expected, just like VC7. It looks like an
overloaded function declaration causes the compiler to accept the
object.Method expression without an error.

That's perhaps not the problem so much as that the compiler finds a multiply
operator for it... there should at least be an error such as "Can't find any
operator* overload for parameters of [method group] and double".
 
D

Doug Harrison [MVP]

That's perhaps not the problem so much as that the compiler finds a multiply
operator for it... there should at least be an error such as "Can't find any
operator* overload for parameters of [method group] and double".

The line in question was this:

The sequence of tokens "t.X" has no meaning in Standard C++, so the
compiler should stop right there and report this as the error. I've
shortened the OP's example a bit, and it's interesting to see how VC8
handles a couple more permutations.

struct Test
{
void X(double val); // 1
double X(void);
};

int main()
{
Test t;
double z;

z = t.X; // 2
z = t.X * 2; // 3
}

***** (A) Line (3) commented out:

a.cpp(12) : error C2440: '=' : cannot convert from 'overloaded-function' to
'double'

***** (B) Line (2) commented out:

No error.

***** (C) Lines (1, 3) commented out:

a.cpp(12) : error C3867: 'Test::X': function call missing argument list;
use '&Test::X' to create a pointer to member
a.cpp(12) : error C2440: '=' : cannot convert from 'double (__thiscall
Test::* ) (void)' to 'double'

***** (D) Lines (1, 2) commented out:

a.cpp(13) : error C3867: 'Test::X': function call missing argument list;
use '&Test::X' to create a pointer to member
a.cpp(13) : error C2296: '*' : illegal, left operand has type 'double
(__thiscall Test::* )(void)'

All four of these should cause error C3867 and only that error. Cases (C)
and (D) indicate that even in the absence of overloading, the compiler is
letting its internal notion(?) of what "t.X" means slip through to the user
level, where it has no meaning whatsoever. IOW, error messages C2440 and
C2296 are completely bogus in this context. Note also the compiler didn't
report the real error for case (A).
 
A

Andre Kaufmann

Tamas said:
murphman wrote:

[...]
P.S. I haven't tried VC++ 2006 (Beta 1). It may be fixed there, I can't
verify it.

It seems to be fixed in VC++ 2006. It's a mess to program in a Virtual
PC remotely and I had to retype the sample char by char.

Andre
 
C

Carl Daniel [VC++ MVP]

Andre said:
Tamas said:
murphman wrote:

[...]
P.S. I haven't tried VC++ 2006 (Beta 1). It may be fixed there, I
can't verify it.

It seems to be fixed in VC++ 2006. It's a mess to program in a Virtual
PC remotely and I had to retype the sample char by char.

There's no such thing as VC++ 2006. Are you referring to VC 2005 SP1 or an
Orcas preview build?

-cd
 
C

Carl Daniel [VC++ MVP]

murphman said:
I recently decided to do the right thing & write accessor functions
for my class member variables instead of having them public and
introduced a rather nasty bug. The class below shows the error -
basically if you forget to add the parenthesis in the call to
function X() then the program compiles ok with no warnings but gives
the wrong answer :(

I'm using VS2005 Prof edition v2.0.50727

The answer seems to be that if you are writing accessor functions
then don't use overloaded functions - maybe use setX & getX instead -
or make sure you don't forget the parenthesis! It seems to think I
want a function pointer(?) but I think it should at least give a
warning.

VC 2005 SP1 final reports this error:

bug111106.cpp(20) : error C3867: 'Test::X': function call missing argument
list;
use '&Test::X' to create a pointer to member

-cd
 
A

Andre Kaufmann

Carl said:
Andre said:
Tamas said:
murphman wrote:

[...]
P.S. I haven't tried VC++ 2006 (Beta 1). It may be fixed there, I
can't verify it.
It seems to be fixed in VC++ 2006. It's a mess to program in a Virtual
PC remotely and I had to retype the sample char by char.

There's no such thing as VC++ 2006. Are you referring to VC 2005 SP1 or an
Orcas preview build?

I referred to the same as my pre-poster ;-)
Yes - the Orcas preview build, which might either be named VC++ 2006/9.0
or rather VC++ 2007/9.0.

Andre
 
C

Carl Daniel [VC++ MVP]

David said:
It's finished? Where is it?

It's not shipped yet, but I'm led to believe that the system I tried it on
is supposed to be the final SP1 bits.

-cd
 

Ask a Question

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

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

Ask a Question

Top