Introduce _Complex conversions into the function overloading
system. Since C99 doesn't have overloading and C++ doesn't have
_Complex, there is no specification for this. Here's what I think
makes sense.
Complex conversions come in several flavors:
- Complex promotions: a complex -> complex conversion where the
underlying real-type conversion is a floating-point promotion. GCC
seems to call this a promotion, EDG does something else. This is
given "promotion" rank for determining the best viable function.
- Complex conversions: a complex -> complex conversion that is
not a complex promotion. This is given "conversion" rank for
determining the best viable function.
- Complex-real conversions: a real -> complex or complex -> real
conversion. This is given "conversion" rank for determining the
best viable function.
These rules are the same for C99 (when using the "overloadable"
attribute) and C++. However, there is one difference in the handling
of floating-point promotions: in C99, float -> long double and double
-> long double are considered promotions (so we give them "promotion"
rank), while C++ considers these conversions ("conversion" rank).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64343 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index e1939d3..48d3105 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -39,6 +39,9 @@
ICC_Qualification_Adjustment,
ICC_Promotion,
ICC_Promotion,
+ ICC_Promotion,
+ ICC_Conversion,
+ ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
@@ -63,6 +66,9 @@
ICR_Exact_Match,
ICR_Promotion,
ICR_Promotion,
+ ICR_Promotion,
+ ICR_Conversion,
+ ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
@@ -86,9 +92,12 @@
"Qualification",
"Integral promotion",
"Floating point promotion",
+ "Complex promotion",
"Integral conversion",
"Floating conversion",
+ "Complex conversion",
"Floating-integral conversion",
+ "Complex-real conversion",
"Pointer conversion",
"Pointer-to-member conversion",
"Boolean conversion",
@@ -552,6 +561,11 @@
SCS.Second = ICK_Floating_Promotion;
FromType = ToType.getUnqualifiedType();
}
+ // Complex promotion (Clang extension)
+ else if (IsComplexPromotion(FromType, ToType)) {
+ SCS.Second = ICK_Complex_Promotion;
+ FromType = ToType.getUnqualifiedType();
+ }
// Integral conversions (C++ 4.7).
// FIXME: isIntegralType shouldn't be true for enums in C++.
else if ((FromType->isIntegralType() || FromType->isEnumeralType()) &&
@@ -564,6 +578,11 @@
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
}
+ // Complex conversions (C99 6.3.1.6)
+ else if (FromType->isComplexType() && ToType->isComplexType()) {
+ SCS.Second = ICK_Complex_Conversion;
+ FromType = ToType.getUnqualifiedType();
+ }
// Floating-integral conversions (C++ 4.9).
// FIXME: isIntegralType shouldn't be true for enums in C++.
else if ((FromType->isFloatingType() &&
@@ -574,6 +593,12 @@
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
}
+ // Complex-real conversions (C99 6.3.1.7)
+ else if ((FromType->isComplexType() && ToType->isArithmeticType()) ||
+ (ToType->isComplexType() && FromType->isArithmeticType())) {
+ SCS.Second = ICK_Complex_Real;
+ FromType = ToType.getUnqualifiedType();
+ }
// Pointer conversions (C++ 4.10).
else if (IsPointerConversion(From, FromType, ToType, FromType,
IncompatibleObjC)) {
@@ -756,14 +781,42 @@
/// An rvalue of type float can be converted to an rvalue of type
/// double. (C++ 4.6p1).
if (const BuiltinType *FromBuiltin = FromType->getAsBuiltinType())
- if (const BuiltinType *ToBuiltin = ToType->getAsBuiltinType())
+ if (const BuiltinType *ToBuiltin = ToType->getAsBuiltinType()) {
if (FromBuiltin->getKind() == BuiltinType::Float &&
ToBuiltin->getKind() == BuiltinType::Double)
return true;
+ // C99 6.3.1.5p1:
+ // When a float is promoted to double or long double, or a
+ // double is promoted to long double [...].
+ if (!getLangOptions().CPlusPlus &&
+ (FromBuiltin->getKind() == BuiltinType::Float ||
+ FromBuiltin->getKind() == BuiltinType::Double) &&
+ (ToBuiltin->getKind() == BuiltinType::LongDouble))
+ return true;
+ }
+
return false;
}
+/// \brief Determine if a conversion is a complex promotion.
+///
+/// A complex promotion is defined as a complex -> complex conversion
+/// where the conversion between the underlying real types is a
+/// floating-point conversion.
+bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
+ const ComplexType *FromComplex = FromType->getAsComplexType();
+ if (!FromComplex)
+ return false;
+
+ const ComplexType *ToComplex = ToType->getAsComplexType();
+ if (!ToComplex)
+ return false;
+
+ return IsFloatingPointPromotion(FromComplex->getElementType(),
+ ToComplex->getElementType());
+}
+
/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from
/// the pointer type FromPtr to a pointer to type ToPointee, with the
/// same type qualifiers as FromPtr has on its pointee type. ToType,