[LLVMbugs] [Bug 8934] New: GCC ignores conversion function template specializatons if a derived class' conversion function converts to the same type

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Sat Jan 8 15:01:02 PST 2011


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

           Summary: GCC ignores conversion function template
                    specializatons if a derived class' conversion function
                    converts to the same type
           Product: clang
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: schaub.johannes at googlemail.com
                CC: llvmbugs at cs.uiuc.edu, dgregor at apple.com


Unless I'm missing something, the following is ambiguous:

template<typename T1, typename T2>
struct A { };

struct base {
  template<typename T2, typename T1>
  operator A<T1, T2>();
};

struct derived : base {
  template<typename T1, typename T2>
  operator A<T1, T2>();
};

int main() {
  derived().operator A<int, int>();
}

However, clang always wants to take the derived class version. 

The reason for ambiguity is:

A<param-#1#1, param-#1#2> is another type than A<param-#1#2, param-#1#1> (prior
to deduction. When collecting candidates, 14.5.2/6 says:

  "A specialization of a conversion function template is not found by name 
  lookup. Instead, any conversion function templates visible in the context of
  the use are considered. For each such operator, if argument deduction
succeeds
  (14.8.2.3), the resulting specialization is used as if found by name lookup."

In the context of the use, both functions templates are visible, so both are
sent to argument deduction. Deduction will succeed, so *the specialization is
used as if found by name lookup*. Name lookup cannot find declarations that are
hidden, so this quite clearly requires the above to be ambiguous, and doesn't
allow the base-class version to be "filtered out" later on. Hiding only takes
place prior to deduction:

template<typename T1, typename T2>
struct A { };

struct base {
  template<typename T1, typename T2>
  operator A<T1, T2>();
};

struct derived : base {
  template<typename T1, typename T2>
  operator A<T1, T2>();
};

int main() {
  derived().operator A<int, int>();
}

Now that is not ambiguous anymore, and will call the derived class version,
because in the context of the use, the base-class version is hidden (12.3/5 and
3/8).

Note that by constructing cases making the base-class version more specialized
than the derived class version, we could actually make this a rejects-valid
bug:

template<typename T1, typename T2>
struct A { };

struct base {
  template<typename T1, typename T2>
  operator A<T1*, T2>();
};

struct derived : base {
private:
  template<typename T1, typename T2>
  operator A<T1, T2>();
};

int main() {
  derived().operator A<int*, int>();
}

Comeau accepts this one just fine, while clang/GCC rejects it, thinking the
base-version is hidden.

-- 
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