summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-06 18:50:40 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-06 18:50:40 +0000
commit1c3c183da3437d9580a66c719a1cb54522d530ee (patch)
treef8dd946dfae80a58fb17727fbbf311c35f1be2c3 /lib/Sema/SemaOverload.cpp
parentc059e0ac05e9795b065bbbe18159f52fdf1f7086 (diff)
downloadclang-1c3c183da3437d9580a66c719a1cb54522d530ee.tar.gz
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373866 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 3db8e3d2e5..80bd3562bc 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3765,6 +3765,34 @@ isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
!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 &S, SourceLocation Loc,
? 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,