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).

llvm-svn: 39412
This commit is contained in:
Steve Naroff 2007-04-24 20:56:26 +00:00
parent 1926c836bb
commit bf223ba1fa
4 changed files with 209 additions and 44 deletions

View File

@ -428,13 +428,81 @@ QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
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();

View File

@ -87,43 +87,67 @@ bool Type::isIntegerType() const {
}
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::isRealType() const {
}
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 {

View File

@ -428,13 +428,81 @@ QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
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();

View File

@ -208,9 +208,20 @@ public:
/// 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