Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -3751,6 +3751,26 @@ !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue); } +/// Returns the underlaying type of a fixed enum of the \a SCS's \c FromType +/// if the \a SCS uses an integral promotion. Upon failure an empty type is +/// returned. +static QualType +getFixedEnumUnderlayingType(const StandardConversionSequence &SCS) { + + if (SCS.Second != ICK_Integral_Promotion) + return QualType(); + + QualType FromType = SCS.getFromType(); + if (!FromType->isEnumeralType()) + return QualType(); + + EnumDecl *Enum = FromType->getAs()->getDecl(); + if (!Enum->isFixed()) + return QualType(); + + return Enum->getIntegerType(); +} + /// CompareStandardConversionSequences - Compare two standard /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). @@ -3792,6 +3812,23 @@ ? ImplicitConversionSequence::Better : ImplicitConversionSequence::Worse; + // C++14 [over.ics.rank]p4b2: + // This is retroactively applied to C++11 by CWG 1601. + // + // A conversion that promotes an enumeration whose underlying type is fixed + // to its underlying type is better than one that promotes to the promoted + // underlying type, if the two are different. + QualType UnderlayingType1 = getFixedEnumUnderlayingType(SCS1); + QualType UnderlayingType2 = getFixedEnumUnderlayingType(SCS2); + if (!UnderlayingType1.isNull() && !UnderlayingType2.isNull()) { + if (SCS1.getToType(1) == UnderlayingType1 && + SCS2.getToType(1) != UnderlayingType2) + return ImplicitConversionSequence::Better; + else if (SCS1.getToType(1) != UnderlayingType1 && + SCS2.getToType(1) == UnderlayingType2) + return ImplicitConversionSequence::Worse; + } + // C++ [over.ics.rank]p4b2: // // If class B is derived directly or indirectly from class A, Index: clang/test/CXX/drs/dr16xx.cpp =================================================================== --- clang/test/CXX/drs/dr16xx.cpp +++ clang/test/CXX/drs/dr16xx.cpp @@ -23,6 +23,17 @@ } // std #endif +namespace dr1601 { // dr1601: 10 c++11 +#if __cplusplus >= 201103L +enum E : char { e }; +void f(char); +void f(int); +void g() { + f(e); +} +#endif +} // namespace dr1601 + namespace dr1611 { // dr1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; Index: clang/test/CXX/drs/dr6xx.cpp =================================================================== --- clang/test/CXX/drs/dr6xx.cpp +++ clang/test/CXX/drs/dr6xx.cpp @@ -1007,9 +1007,10 @@ void j(long); // expected-note {{candidate}} int d = j(g); // expected-error {{ambiguous}} - int k(short); // expected-note {{candidate}} - void k(int); // expected-note {{candidate}} - int x = k(g); // expected-error {{ambiguous}} + // Valid per dr1601 + int k(short); + void k(int); + int x = k(g); } #endif