[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