[cfe-commits] r39413 - 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:06 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:44:06 2007
New Revision: 39413

URL: http://llvm.org/viewvc/llvm-project?rev=39413&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
Refactored code that deals with float/complex conversions (the previous commit).

- Removed 6 predicates that identify the built-in float/complex types.
- Added two helper functions GetFloatingRank() & ConvertFloatingRankToComplexType().
At present, these are static functions in SemaExpr.cpp. Conceptually, they would be nice
to move to Type, however there are layering problems with that (i.e. no ASTContext).
Another possibility is to move them to ASTContext?
- Simplified the logic in UsualArithmeticConversions() considerably.

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=39413&r1=39412&r2=39413&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:06 2007
@@ -409,109 +409,103 @@
   return t;
 }
 
+/// GetFloatingRank - Helper function for UsualArithmeticConversions().
+static inline int GetFloatingRank(QualType t) {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+    switch (BT->getKind()) {
+    case BuiltinType::Float:
+    case BuiltinType::FloatComplex:
+      return 1;
+    case BuiltinType::Double:
+    case BuiltinType::DoubleComplex:
+      return 2;
+    case BuiltinType::LongDouble:
+    case BuiltinType::LongDoubleComplex:
+      return 3;
+    default:
+      assert(0 && "getFloatingPointRank(): not a floating type");
+    }
+  }
+  return 0;
+}
+
+/// ConvertFloatingRankToComplexType - Another helper for converting floats.
+static inline QualType ConvertFloatingRankToComplexType(int rank, 
+                                                        ASTContext C) {
+  switch (rank) {
+  case 1:
+    return C.FloatComplexTy;
+  case 2:
+    return C.DoubleComplexTy;
+  case 3:
+    return C.LongDoubleComplexTy;
+  default:
+    assert(0 && "convertRankToComplex(): illegal value for rank");
+  }
+}
+
 /// UsualArithmeticConversions - Performs various conversions that are common to 
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
 /// routine returns the first non-arithmetic type found. The client is 
 /// responsible for emitting appropriate error diagnostics.
 QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
-  t1 = UsualUnaryConversion(t1);
-  t2 = UsualUnaryConversion(t2);
+  QualType lhs = UsualUnaryConversion(t1);
+  QualType rhs = UsualUnaryConversion(t2);
   
   // if either operand is not of arithmetic type, no conversion is possible.
-  if (!t1->isArithmeticType())
-    return t1;
-  else if (!t2->isArithmeticType())
-    return t2;
+  if (!lhs->isArithmeticType())
+    return lhs;
+  else if (!rhs->isArithmeticType())
+    return rhs;
     
   // if both operands have the same type, no conversion is needed.
-  if (t1 == t2) 
-    return t1;
+  if (lhs == rhs) 
+    return lhs;
   
-  // at this point, we have two different arithmetic types. Handle the
-  // 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;
+  // at this point, we have two different arithmetic types. 
+  
+  // Handle complex types first (C99 6.3.1.8p1).
+  if (lhs->isComplexType() || rhs->isComplexType()) {
+    // if we have an integer operand, the result is the complex type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    // the following code handles three different combinations:
+    // complex/complex, complex/float, float/complex.
+    int lhsRank = GetFloatingRank(lhs);
+    int rhsRank = GetFloatingRank(rhs);
+    
+    if (lhsRank >= rhsRank)
+      return ConvertFloatingRankToComplexType(lhsRank, Context);
+    else
+      return ConvertFloatingRankToComplexType(rhsRank, Context);
+  }
+  // Now handle "real" floating types (i.e. float, double, long double).
+  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
+    // if we have an integer operand, the result is the real floating type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    // we have two real floating types, float/complex combos were handled above.
+    if (GetFloatingRank(lhs) >= GetFloatingRank(rhs))
+      return lhs;
+    else
+      return rhs;
   }
-  bool t1Unsigned = t1->isUnsignedIntegerType();
-  bool t2Unsigned = t2->isUnsignedIntegerType();
+  // Lastly, handle two integers.
+  bool t1Unsigned = lhs->isUnsignedIntegerType();
+  bool t2Unsigned = rhs->isUnsignedIntegerType();
   
   if (t1Unsigned && t2Unsigned)
-    return t1; // FIXME: return the unsigned type with the greatest rank
+    return lhs; // FIXME: return the unsigned type with the greatest rank
   else if (!t1Unsigned && !t2Unsigned)
-    return t1; // FIXME: return the signed type with the greatest rank
+    return lhs; // FIXME: return the signed type with the greatest rank
   else 
-    return t1; // FIXME: we have a mixture...
+    return lhs; // FIXME: we have a mixture...
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(

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

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:06 2007
@@ -107,42 +107,6 @@
   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 {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Float &&

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:06 2007
@@ -409,109 +409,103 @@
   return t;
 }
 
+/// GetFloatingRank - Helper function for UsualArithmeticConversions().
+static inline int GetFloatingRank(QualType t) {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(t.getCanonicalType())) {
+    switch (BT->getKind()) {
+    case BuiltinType::Float:
+    case BuiltinType::FloatComplex:
+      return 1;
+    case BuiltinType::Double:
+    case BuiltinType::DoubleComplex:
+      return 2;
+    case BuiltinType::LongDouble:
+    case BuiltinType::LongDoubleComplex:
+      return 3;
+    default:
+      assert(0 && "getFloatingPointRank(): not a floating type");
+    }
+  }
+  return 0;
+}
+
+/// ConvertFloatingRankToComplexType - Another helper for converting floats.
+static inline QualType ConvertFloatingRankToComplexType(int rank, 
+                                                        ASTContext C) {
+  switch (rank) {
+  case 1:
+    return C.FloatComplexTy;
+  case 2:
+    return C.DoubleComplexTy;
+  case 3:
+    return C.LongDoubleComplexTy;
+  default:
+    assert(0 && "convertRankToComplex(): illegal value for rank");
+  }
+}
+
 /// UsualArithmeticConversions - Performs various conversions that are common to 
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
 /// routine returns the first non-arithmetic type found. The client is 
 /// responsible for emitting appropriate error diagnostics.
 QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
-  t1 = UsualUnaryConversion(t1);
-  t2 = UsualUnaryConversion(t2);
+  QualType lhs = UsualUnaryConversion(t1);
+  QualType rhs = UsualUnaryConversion(t2);
   
   // if either operand is not of arithmetic type, no conversion is possible.
-  if (!t1->isArithmeticType())
-    return t1;
-  else if (!t2->isArithmeticType())
-    return t2;
+  if (!lhs->isArithmeticType())
+    return lhs;
+  else if (!rhs->isArithmeticType())
+    return rhs;
     
   // if both operands have the same type, no conversion is needed.
-  if (t1 == t2) 
-    return t1;
+  if (lhs == rhs) 
+    return lhs;
   
-  // at this point, we have two different arithmetic types. Handle the
-  // 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;
+  // at this point, we have two different arithmetic types. 
+  
+  // Handle complex types first (C99 6.3.1.8p1).
+  if (lhs->isComplexType() || rhs->isComplexType()) {
+    // if we have an integer operand, the result is the complex type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    // the following code handles three different combinations:
+    // complex/complex, complex/float, float/complex.
+    int lhsRank = GetFloatingRank(lhs);
+    int rhsRank = GetFloatingRank(rhs);
+    
+    if (lhsRank >= rhsRank)
+      return ConvertFloatingRankToComplexType(lhsRank, Context);
+    else
+      return ConvertFloatingRankToComplexType(rhsRank, Context);
+  }
+  // Now handle "real" floating types (i.e. float, double, long double).
+  if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
+    // if we have an integer operand, the result is the real floating type.
+    if (rhs->isIntegerType())
+      return lhs;
+    if (lhs->isIntegerType())
+      return rhs;
+
+    // we have two real floating types, float/complex combos were handled above.
+    if (GetFloatingRank(lhs) >= GetFloatingRank(rhs))
+      return lhs;
+    else
+      return rhs;
   }
-  bool t1Unsigned = t1->isUnsignedIntegerType();
-  bool t2Unsigned = t2->isUnsignedIntegerType();
+  // Lastly, handle two integers.
+  bool t1Unsigned = lhs->isUnsignedIntegerType();
+  bool t2Unsigned = rhs->isUnsignedIntegerType();
   
   if (t1Unsigned && t2Unsigned)
-    return t1; // FIXME: return the unsigned type with the greatest rank
+    return lhs; // FIXME: return the unsigned type with the greatest rank
   else if (!t1Unsigned && !t2Unsigned)
-    return t1; // FIXME: return the signed type with the greatest rank
+    return lhs; // FIXME: return the signed type with the greatest rank
   else 
-    return t1; // FIXME: we have a mixture...
+    return lhs; // FIXME: we have a mixture...
 }
 
 Action::ExprResult Sema::CheckMultiplicativeOperands(

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=39413&r1=39412&r2=39413&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:44:06 2007
@@ -213,15 +213,6 @@
   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