[cfe-commits] r39412 - in /cfe/cfe/trunk: AST/SemaExpr.cpp AST/Type.cpp Sema/SemaExpr.cpp include/clang/AST/Type.h

Steve Naroff snaroff at apple.com
Wed Jul 11 09:44:05 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:44:05 2007
New Revision: 39412

URL: http://llvm.org/viewvc/llvm-project?rev=39412&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
-Lot's of detail work in UsualArithmeticConversion(). Needed to expand
the code for dealing with floating types. This code still has a couple
of FIXME's and could be refactored a bit.
-Added a bunch of Type predicates to simplify the float conversions.
Used the opportunity to convert a bunch of predicates to dyn_cast (it's cleaner
when just dealing with Builtin types).

Modified:
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/AST/Type.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/include/clang/AST/Type.h

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39412&r1=39411&r2=39412&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:05 2007
@@ -428,13 +428,81 @@
     return t1;
   
   // at this point, we have two different arithmetic types. Handle the
-  // real floating types first (C99 6.3.1.8p1). If either operand is float,
-  // double, or long double, the result is float, double, or long double.
-  if (t1->isRealFloatingType()) 
-    return t1;
-  else if (t2->isRealFloatingType())
-    return t2;
-    
+  // six floating types first (C99 6.3.1.8p1). 
+  if (t1->isFloatingType() || t2->isFloatingType()) {
+    if (t1->isRealFloatingType() && t2->isRealFloatingType()) {
+      // types are homogeneous, return the type with the greatest precision
+      if (t1->isLongDoubleType())
+        return t1;
+      else if (t2->isLongDoubleType())
+        return t2;
+      if (t1->isDoubleType())
+        return t1;
+      else if (t2->isDoubleType())
+        return t2;
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    } else if (t1->isComplexType() && t2->isComplexType()) {
+      // types are homogeneous, return the type with the greatest precision
+      if (t1->isLongDoubleComplexType())
+        return t1;
+      else if (t2->isLongDoubleComplexType())
+        return t2;
+      if (t1->isDoubleComplexType())
+        return t1;
+      else if (t2->isDoubleComplexType())
+        return t2;
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    // type are heterogeneous, handle various permutations.
+    if (t1->isRealFloatingType()) {
+      if (t2->isIntegerType())
+        return t1;
+        
+      // return the complex type with the greatest precision (across domains).
+      if (t2->isComplexType()) {
+        if (t1->isLongDoubleType()) {
+          if (t2->isLongDoubleComplexType())
+            return t2;
+          else
+            return t1; // FIXME: need to return "long double _Complex"?
+        } else if (t1->isDoubleType()) {
+          if (t2->isLongDoubleComplexType() || t2->isDoubleComplexType())
+            return t2;
+          else
+            return t1; // FIXME: need to return "double _Complex"?
+        } else {
+          // t1 is a float, there is no need to promote t2 (the complex type).
+          return t2;
+        }
+      } 
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    if (t1->isComplexType()) {
+      if (t2->isIntegerType())
+        return t1;
+        
+      if (t2->isRealFloatingType()) {
+        // return the complex type with the greatest precision (across domains).
+        if (t2->isLongDoubleType()) {
+          if (t1->isLongDoubleComplexType())
+            return t1;
+          else
+            return t2; // FIXME: need to return "long double _Complex"?
+        } else if (t2->isDoubleType()) {
+          if (t1->isLongDoubleComplexType() || t1->isDoubleComplexType())
+            return t1;
+          else
+            return t2; // FIXME: need to return "double _Complex"?
+        } else {
+          // t2 is a float, there is no need to promote t1 (the complex type).
+          return t1;
+        }
+      } 
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    if (t1->isIntegerType())
+      return t2;
+  }
   bool t1Unsigned = t1->isUnsignedIntegerType();
   bool t2Unsigned = t2->isUnsignedIntegerType();
   

Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39412&r1=39411&r2=39412&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:05 2007
@@ -87,43 +87,67 @@
 }
 
 bool Type::isSignedIntegerType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::SChar &&
            BT->getKind() <= BuiltinType::LongLong;
-  }
+  return false;
 }
 
 bool Type::isUnsignedIntegerType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::UChar &&
            BT->getKind() <= BuiltinType::ULongLong;
-  }
+  return false;
 }
 
 bool Type::isFloatingType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Float &&
            BT->getKind() <= BuiltinType::LongDoubleComplex;
-  }
+  return false;
+}
+
+bool Type::isFloatType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::Float;
+  return false;
+}
+
+bool Type::isDoubleType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::Double;
+  return false;
+}
+
+bool Type::isLongDoubleType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::LongDouble;
+  return false;
+}
+
+bool Type::isFloatComplexType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::FloatComplex;
+  return false;
+}
+
+bool Type::isDoubleComplexType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::DoubleComplex;
+  return false;
+}
+
+bool Type::isLongDoubleComplexType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() == BuiltinType::LongDoubleComplex;
+  return false;
 }
 
 bool Type::isRealFloatingType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Float &&
            BT->getKind() <= BuiltinType::LongDouble;
-  }
+  return false;
 }
 
 bool Type::isRealType() const {
@@ -143,23 +167,17 @@
 }
 
 bool Type::isComplexType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::FloatComplex &&
            BT->getKind() <= BuiltinType::LongDoubleComplex;
-  }
+  return false;
 }
 
 bool Type::isArithmeticType() const {
-  switch (CanonicalType->getTypeClass()) {
-  default: return false;
-  case Builtin:
-    const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType.getTypePtr());
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
            BT->getKind() <= BuiltinType::LongDoubleComplex;
-  }
+  return false;
 }
 
 bool Type::isScalarType() const {

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39412&r1=39411&r2=39412&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:05 2007
@@ -428,13 +428,81 @@
     return t1;
   
   // at this point, we have two different arithmetic types. Handle the
-  // real floating types first (C99 6.3.1.8p1). If either operand is float,
-  // double, or long double, the result is float, double, or long double.
-  if (t1->isRealFloatingType()) 
-    return t1;
-  else if (t2->isRealFloatingType())
-    return t2;
-    
+  // six floating types first (C99 6.3.1.8p1). 
+  if (t1->isFloatingType() || t2->isFloatingType()) {
+    if (t1->isRealFloatingType() && t2->isRealFloatingType()) {
+      // types are homogeneous, return the type with the greatest precision
+      if (t1->isLongDoubleType())
+        return t1;
+      else if (t2->isLongDoubleType())
+        return t2;
+      if (t1->isDoubleType())
+        return t1;
+      else if (t2->isDoubleType())
+        return t2;
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    } else if (t1->isComplexType() && t2->isComplexType()) {
+      // types are homogeneous, return the type with the greatest precision
+      if (t1->isLongDoubleComplexType())
+        return t1;
+      else if (t2->isLongDoubleComplexType())
+        return t2;
+      if (t1->isDoubleComplexType())
+        return t1;
+      else if (t2->isDoubleComplexType())
+        return t2;
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    // type are heterogeneous, handle various permutations.
+    if (t1->isRealFloatingType()) {
+      if (t2->isIntegerType())
+        return t1;
+        
+      // return the complex type with the greatest precision (across domains).
+      if (t2->isComplexType()) {
+        if (t1->isLongDoubleType()) {
+          if (t2->isLongDoubleComplexType())
+            return t2;
+          else
+            return t1; // FIXME: need to return "long double _Complex"?
+        } else if (t1->isDoubleType()) {
+          if (t2->isLongDoubleComplexType() || t2->isDoubleComplexType())
+            return t2;
+          else
+            return t1; // FIXME: need to return "double _Complex"?
+        } else {
+          // t1 is a float, there is no need to promote t2 (the complex type).
+          return t2;
+        }
+      } 
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    if (t1->isComplexType()) {
+      if (t2->isIntegerType())
+        return t1;
+        
+      if (t2->isRealFloatingType()) {
+        // return the complex type with the greatest precision (across domains).
+        if (t2->isLongDoubleType()) {
+          if (t1->isLongDoubleComplexType())
+            return t1;
+          else
+            return t2; // FIXME: need to return "long double _Complex"?
+        } else if (t2->isDoubleType()) {
+          if (t1->isLongDoubleComplexType() || t1->isDoubleComplexType())
+            return t1;
+          else
+            return t2; // FIXME: need to return "double _Complex"?
+        } else {
+          // t2 is a float, there is no need to promote t1 (the complex type).
+          return t1;
+        }
+      } 
+      assert(0 && "UsualArithmeticConversions(): floating point conversion");
+    }
+    if (t1->isIntegerType())
+      return t2;
+  }
   bool t1Unsigned = t1->isUnsignedIntegerType();
   bool t2Unsigned = t2->isUnsignedIntegerType();
   

Modified: cfe/cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Type.h?rev=39412&r1=39411&r2=39412&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:44:05 2007
@@ -208,9 +208,20 @@
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs.
   bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
+  
+  /// Floating point categories.
   bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
   bool isComplexType() const;      // C99 6.2.5p11 (complex)
   bool isFloatingType() const;     // C99 6.2.5p11 (real floating + complex)
+  
+  /// Floating point types.
+  bool isFloatType() const;
+  bool isDoubleType() const;
+  bool isLongDoubleType() const;
+  bool isFloatComplexType() const;
+  bool isDoubleComplexType() const;
+  bool isLongDoubleComplexType() const;
+  
   bool isRealType() const;         // C99 6.2.5p17 (real floating + integer)
   bool isArithmeticType() const;   // C99 6.2.5p18 (integral + floating)
   bool isVoidType() const;         // C99 6.2.5p19





More information about the cfe-commits mailing list