[LLVMbugs] [Bug 10609] New: poor diagnostic on ambiguous implicit conversion

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon Aug 8 09:23:33 PDT 2011


http://llvm.org/bugs/show_bug.cgi?id=10609

           Summary: poor diagnostic on ambiguous implicit conversion
           Product: clang
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: richard-llvm at metafoo.co.uk
                CC: llvmbugs at cs.uiuc.edu, dgregor at apple.com


The following cut-down test case is accepted by g++ and rejected by clang++:

template<typename T> class A {
public:
  T val;
  operator const T &() const { return val; }
};
class B : public A<int> {};
class C : public B {
public:
  enum Value { None, ThingA, ThingB };
  operator bool() const { return val != None; }
};
bool Check(const C &c) { return C::ThingB == c; }

It's not clear to me whether clang is correct in rejecting this; the 'const C
lvalue -> const int lvalue -> int rvalue' conversion sequence for the RHS looks
like it should be unambiguously the best. Assuming clang is correct, its error
message is poor:

/home/richards/test.cpp:13:43: error: use of overloaded operator '==' is
ambiguous (with operand types 'C::Value' and 'const C')
bool Check(const C &c) { return C::ThingB == c; }
                                ~~~~~~~~~ ^  ~
/home/richards/test.cpp:13:43: note: because of ambiguity in conversion of
'const C' to 'float'                                                            
/home/richards/test.cpp:10:3: note: candidate function
  operator bool() const { return val != None; }
  ^
/home/richards/test.cpp:4:3: note: candidate function                           
  operator const T &() const { return val; }
  ^
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, float)  
bool Check(const C &c) { return C::ThingB == c; }
                                          ^
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, double) 
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, long
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(int, long
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, long double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
long double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, long double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long long, float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, long double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
long, float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(unsigned
int, unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double, long
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double, long
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(double,
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float, long
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float, long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float, long
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float,
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long, float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long, long
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(float,
float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long, int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long, long
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long,
double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long long,
float)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
unsigned long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
unsigned long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
unsigned int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
long long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
long)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
int)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
long double)
/home/richards/test.cpp:13:43: note: built-in candidate operator==(long double,
double)


In particular, this note is wrong:

  /home/richards/test.cpp:13:43: note: because of ambiguity in conversion of
'const C' to 'float'

'const C' has user-defined conversions to 'const int &' and 'bool', and the
conversion to 'float' for both of those is a worse standard conversion sequence
than the promotion (or identity conversion) to 'int'. So the ambiguous
conversion from 'const C' to 'float' is irrelevant to the problem.


/home/richards/test.cpp:10:3: note: candidate function
  operator bool() const { return val != None; }
  ^
/home/richards/test.cpp:4:3: note: candidate function
  operator const T &() const { return val; }
  ^

In the code from which this testcase was extracted, it is nontrivial to
determine what type is produced by this candidate function. It'd be great if
clang told us.

Finally, the long list of viable functions should be pruned to only list those
for which there is no better viable function.

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list