diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-12 00:15:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-12 00:15:05 +0000 |
commit | 78ca74d81d9351e54677810ccbbedc6f0cfc4387 (patch) | |
tree | 77ba24717c60f71f1664062806f6e9b9524761d4 /clang/lib/Sema/SemaOverload.cpp | |
parent | f6d609a22722fb47389b5da80b5d84a8cace6d4f (diff) | |
download | bcm5719-llvm-78ca74d81d9351e54677810ccbbedc6f0cfc4387.tar.gz bcm5719-llvm-78ca74d81d9351e54677810ccbbedc6f0cfc4387.zip |
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).
llvm-svn: 64343
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e1939d329e9..48d31056a79 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -39,6 +39,9 @@ GetConversionCategory(ImplicitConversionKind Kind) { ICC_Qualification_Adjustment, ICC_Promotion, ICC_Promotion, + ICC_Promotion, + ICC_Conversion, + ICC_Conversion, ICC_Conversion, ICC_Conversion, ICC_Conversion, @@ -63,6 +66,9 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { ICR_Exact_Match, ICR_Promotion, ICR_Promotion, + ICR_Promotion, + ICR_Conversion, + ICR_Conversion, ICR_Conversion, ICR_Conversion, ICR_Conversion, @@ -86,9 +92,12 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "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 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, 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 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, 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 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, 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 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) /// 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, |