Author: rsmith Date: Sun Oct 6 11:50:40 2019 New Revision: 373866 URL: http://llvm.org/viewvc/llvm-project?rev=373866&view=rev Log: Implements CWG 1601 in [over.ics.rank/4.2]
Summary: The overload resolution for enums with a fixed underlying type has changed in the C++14 standard. This patch implements the new rule. Patch by Mark de Wever! Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65695 Modified: cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/CXX/drs/dr16xx.cpp cfe/trunk/test/CXX/drs/dr6xx.cpp cfe/trunk/www/cxx_dr_status.html Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=373866&r1=373865&r2=373866&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Oct 6 11:50:40 2019 @@ -3765,6 +3765,34 @@ isBetterReferenceBindingKind(const Stand !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue); } +enum class FixedEnumPromotion { + None, + ToUnderlyingType, + ToPromotedUnderlyingType +}; + +/// Returns kind of fixed enum promotion the \a SCS uses. +static FixedEnumPromotion +getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) { + + if (SCS.Second != ICK_Integral_Promotion) + return FixedEnumPromotion::None; + + QualType FromType = SCS.getFromType(); + if (!FromType->isEnumeralType()) + return FixedEnumPromotion::None; + + EnumDecl *Enum = FromType->getAs<EnumType>()->getDecl(); + if (!Enum->isFixed()) + return FixedEnumPromotion::None; + + QualType UnderlyingType = Enum->getIntegerType(); + if (S.Context.hasSameType(SCS.getToType(1), UnderlyingType)) + return FixedEnumPromotion::ToUnderlyingType; + + return FixedEnumPromotion::ToPromotedUnderlyingType; +} + /// 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). @@ -3806,6 +3834,20 @@ CompareStandardConversionSequences(Sema ? 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. + FixedEnumPromotion FEP1 = getFixedEnumPromtion(S, SCS1); + FixedEnumPromotion FEP2 = getFixedEnumPromtion(S, SCS2); + if (FEP1 != FixedEnumPromotion::None && FEP2 != FixedEnumPromotion::None && + FEP1 != FEP2) + return FEP1 == FixedEnumPromotion::ToUnderlyingType + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + // C++ [over.ics.rank]p4b2: // // If class B is derived directly or indirectly from class A, Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr16xx.cpp?rev=373866&r1=373865&r2=373866&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr16xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr16xx.cpp Sun Oct 6 11:50:40 2019 @@ -23,6 +23,18 @@ namespace std { } // std #endif +namespace dr1601 { // dr1601: 10 +enum E : char { e }; +#if __cplusplus < 201103L + // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} +#endif +void f(char); +void f(int); +void g() { + f(e); +} +} // namespace dr1601 + namespace dr1611 { // dr1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; Modified: cfe/trunk/test/CXX/drs/dr6xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr6xx.cpp?rev=373866&r1=373865&r2=373866&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr6xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr6xx.cpp Sun Oct 6 11:50:40 2019 @@ -987,14 +987,19 @@ namespace dr684 { // dr684: sup 1454 } #endif -#if __cplusplus >= 201103L namespace dr685 { // dr685: yes enum E : long { e }; +#if __cplusplus < 201103L + // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} +#endif void f(int); int f(long); int a = f(e); enum G : short { g }; +#if __cplusplus < 201103L + // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} +#endif int h(short); void h(long); int b = h(g); @@ -1007,11 +1012,11 @@ namespace dr685 { // dr685: yes 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 namespace dr686 { // dr686: yes void f() { Modified: cfe/trunk/www/cxx_dr_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=373866&r1=373865&r2=373866&view=diff ============================================================================== --- cfe/trunk/www/cxx_dr_status.html (original) +++ cfe/trunk/www/cxx_dr_status.html Sun Oct 6 11:50:40 2019 @@ -9421,7 +9421,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg1601">1601</a></td> <td>C++14</td> <td>Promotion of enumeration with fixed underlying type</td> - <td class="none" align="center">Unknown</td> + <td class="svn" align="center">SVN</td> </tr> <tr class="open" id="1602"> <td><a href="http://wg21.link/cwg1602">1602</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits