[cfe-commits] r64343 - in /cfe/trunk: lib/AST/Type.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/complex-overload.cpp
Douglas Gregor
dgregor at apple.com
Wed Feb 11 16:15:06 PST 2009
Author: dgregor
Date: Wed Feb 11 18:15:05 2009
New Revision: 64343
URL: http://llvm.org/viewvc/llvm-project?rev=64343&view=rev
Log:
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).
Added:
cfe/trunk/test/SemaCXX/complex-overload.cpp
Modified:
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=64343&r1=64342&r2=64343&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Feb 11 18:15:05 2009
@@ -82,6 +82,10 @@
return TOE->getUnderlyingExpr()->getType();
if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
return TOT->getUnderlyingType();
+ if (const ClassTemplateSpecializationType *Spec
+ = dyn_cast<ClassTemplateSpecializationType>(this))
+ return Spec->getCanonicalTypeInternal();
+
// FIXME: remove this cast.
return QualType(const_cast<Type*>(this), 0);
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=64343&r1=64342&r2=64343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 11 18:15:05 2009
@@ -424,6 +424,7 @@
StandardConversionSequence& SCS);
bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+ bool IsComplexPromotion(QualType FromType, QualType ToType);
bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
QualType& ConvertedType, bool &IncompatibleObjC);
bool isObjCPointerConversion(QualType FromType, QualType ToType,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=64343&r1=64342&r2=64343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 11 18:15:05 2009
@@ -806,9 +806,12 @@
case ICK_Integral_Promotion:
case ICK_Floating_Promotion:
+ case ICK_Complex_Promotion:
case ICK_Integral_Conversion:
case ICK_Floating_Conversion:
+ case ICK_Complex_Conversion:
case ICK_Floating_Integral:
+ case ICK_Complex_Real:
case ICK_Compatible_Conversion:
// FIXME: Go deeper to get the unqualified type!
FromType = ToType.getUnqualifiedType();
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=64343&r1=64342&r2=64343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb 11 18:15:05 2009
@@ -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,
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=64343&r1=64342&r2=64343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Wed Feb 11 18:15:05 2009
@@ -33,9 +33,12 @@
ICK_Qualification, ///< Qualification conversions (C++ 4.4)
ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5)
ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6)
+ ICK_Complex_Promotion, ///< Complex promotions (Clang extension)
ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7)
ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8)
+ ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6)
ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9)
+ ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10)
ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11)
ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12)
Added: cfe/trunk/test/SemaCXX/complex-overload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/complex-overload.cpp?rev=64343&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/complex-overload.cpp (added)
+++ cfe/trunk/test/SemaCXX/complex-overload.cpp Wed Feb 11 18:15:05 2009
@@ -0,0 +1,43 @@
+// RUN: clang -fsyntax-only -verify %s
+char *foo(float); // expected-note 3 {{candidate function}}
+
+void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv);
+ // Note: GCC and EDG reject these two, but they are valid C99 conversions
+ char *cp3 = foo(fc);
+ char *cp4 = foo(dc);
+}
+
+int *foo(float _Complex); // expected-note 3 {{candidate function}}
+
+void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+ int *ip = foo(fc);
+ int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+}
+
+long *foo(double _Complex); // expected-note {{candidate function}}
+
+void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+ int *ip = foo(fc);
+ long *lp = foo(dc);
+}
+
+char *promote_or_convert(double _Complex); // expected-note{{candidate function}}
+int *promote_or_convert(long double _Complex); // expected-note{{candidate function}}
+
+void test_promote_or_convert(float f, float _Complex fc) {
+ char *cp = promote_or_convert(fc);
+ int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}}
+}
+
+char *promote_or_convert2(float);
+int *promote_or_convert2(double _Complex);
+
+void test_promote_or_convert(float _Complex fc) {
+ int *cp = promote_or_convert2(fc);
+}
More information about the cfe-commits
mailing list