This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/14318] New: sizeof() does too much


I appreciate that some may not consider this a bug, but the code below is an 
Alexandrescu style method of determining convertibility which fails on GCC v3.4 
and v3.2.2. It does not fail on MSVC7.1 and I would assume other compilers Loki 
runs on. It does not fail on GCC when the type is not a 64 bit integer (this 
smells fishy).

[ned@katey TClient]$ g++ test1.cpp
test1.cpp: In function `int main()':
test1.cpp:48: conversion from `Foo' to `long int' is ambiguous
test1.cpp:9: candidates are: Foo::operator long long int&()
test1.cpp:10:                 Foo::operator long long int() const
test1.cpp:11:                 Foo::operator double()
test1.cpp:12:                 Foo::operator double() const
test1.cpp:13:                 Foo::operator bool()
test1.cpp:14:                 Foo::operator bool() const
test1.cpp: At global scope:
test1.cpp: In instantiation of `convertible<long unsigned int, Foo>':
test1.cpp:53:   instantiated from here
test1.cpp:53: warning: cannot pass objects of non-POD type `class Foo' through
   `...'; call will abort at runtime

Here's the code:

/* Test for implicit conversion bug */
#include <stdio.h>

class Foo
{
	long long int data;	// Works fine if is "long int" or "short int" etc
public:
	Foo(long long int a) : data(a) { }
	operator long long int &() throw() { return data; }
	operator long long int() const throw() { return data; }
	operator double() throw() { return (double) data; }
	operator double() const throw() { return (double) data; }
	operator bool() throw() { return data!=0; }
	operator bool() const throw() { return data!=0; }
};

namespace convertiblePrivate {
	template<typename to, typename from> struct impl
	{
		struct TwoChar { char foo[2]; };
		static from &makeFrom();
		static TwoChar test(...);
		static char test(to);
	};
}

/*! \struct convertible
\ingroup generic
\brief Returns true if \em from can become \em to
*/
template<typename to, typename from> struct convertible
{
private:
	typedef convertiblePrivate::impl<to, from> impl;
public:
	enum { value=sizeof(impl::test(impl::makeFrom()))==sizeof(char) };
};
template<typename T> struct convertible<void, T> { enum { value=false }; };
template<typename T> struct convertible<T, void> { enum { value=false }; };
template<> struct convertible<void, void> { enum { value=true }; };

int main(void)
{
	long int a;
	double b;
	bool c;
	Foo f(5);
	a=f;
	b=f;
	c=f;
	printf("a=%ld, b=%lf, c=%d\n", a, b, c);
	
	c=convertible<unsigned long int, Foo>::value;
	return 0;
}

The trouble is that the metaprogramming code to determine convertibility gets 
tripped up when asked if it can convert to a nearly similar type but ONLY when 
it's either a signed long long or an unsigned long long. This does NOT affect 
normal integers.

In this case, I don't care. The code is to determine convertibility so I can 
/avoid/ compiling bad code via specialisation. The fact it trips up on the test 
negates the whole point of the exercise!

If sizeof() did less, it also wouldn't raise the warning about POD types going 
through ... - this doesn't matter as no actual code actually does this here (it 
being inside a sizeof().

Thoughts?

Cheers,
Niall

-- 
           Summary: sizeof() does too much
           Product: gcc
           Version: 3.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: s_gccbugzilla at nedprod dot com
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14318


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]