Mordante updated this revision to Diff 215736.
Mordante marked an inline comment as done.
Mordante edited the summary of this revision.
Mordante added a comment.

Implemented the changes requested by @rsmith.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65695/new/

https://reviews.llvm.org/D65695

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/drs/dr16xx.cpp
  clang/test/CXX/drs/dr6xx.cpp

Index: clang/test/CXX/drs/dr6xx.cpp
===================================================================
--- clang/test/CXX/drs/dr6xx.cpp
+++ clang/test/CXX/drs/dr6xx.cpp
@@ -987,14 +987,19 @@
 }
 #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 @@
   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() {
Index: clang/test/CXX/drs/dr16xx.cpp
===================================================================
--- clang/test/CXX/drs/dr16xx.cpp
+++ clang/test/CXX/drs/dr16xx.cpp
@@ -23,6 +23,18 @@
 } // 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; };
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -3751,6 +3751,34 @@
           !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue);
 }
 
+enum class FixedEnumPromotion {
+  None,
+  ToUnderlyingType,
+  ToPromotedUnderlyingType
+};
+
+/// Returns kind of fixed enum promotion the \a SCS uses.
+static FixedEnumPromotion
+getFixedEnumPromtion(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 (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).
@@ -3792,6 +3820,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.
+  FixedEnumPromotion FEP1 = getFixedEnumPromtion(SCS1);
+  FixedEnumPromotion FEP2 = getFixedEnumPromtion(SCS2);
+  if (FEP1 != FixedEnumPromotion::None && FEP2 != FixedEnumPromotion::None) {
+    if (FEP1 == FixedEnumPromotion::ToUnderlyingType &&
+        FEP2 == FixedEnumPromotion::ToPromotedUnderlyingType)
+      return ImplicitConversionSequence::Better;
+    else if (FEP1 == FixedEnumPromotion::ToPromotedUnderlyingType &&
+             FEP2 == FixedEnumPromotion::ToUnderlyingType)
+      return ImplicitConversionSequence::Worse;
+  }
+
   // C++ [over.ics.rank]p4b2:
   //
   //   If class B is derived directly or indirectly from class A,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D65695: I... Mark de Wever via Phabricator via cfe-commits
    • [PATCH] D656... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D656... Mark de Wever via Phabricator via cfe-commits
    • [PATCH] D656... Mark de Wever via Phabricator via cfe-commits
    • [PATCH] D656... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D656... Mark de Wever via Phabricator via cfe-commits

Reply via email to