forked from OSchip/llvm-project
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). llvm-svn: 39412
This commit is contained in:
parent
1926c836bb
commit
bf223ba1fa
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue