[cfe-commits] r139033 - /cfe/trunk/lib/Sema/SemaExpr.cpp
Richard Trieu
rtrieu at google.com
Fri Sep 2 13:58:52 PDT 2011
Author: rtrieu
Date: Fri Sep 2 15:58:51 2011
New Revision: 139033
URL: http://llvm.org/viewvc/llvm-project?rev=139033&view=rev
Log:
Refactor UsualArithmeticConversions() in SemaExpr.cpp into several functions.
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=139033&r1=139032&r2=139033&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Sep 2 15:58:51 2011
@@ -541,311 +541,280 @@
return Owned(E);
}
-/// 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.
-/// FIXME: verify the conversion rules for "complex int" are consistent with
-/// GCC.
-QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr,
- ExprResult &rhsExpr,
- bool isCompAssign) {
- if (!isCompAssign) {
- lhsExpr = UsualUnaryConversions(lhsExpr.take());
- if (lhsExpr.isInvalid())
- return QualType();
+/// \brief Converts an integer to complex float type. Helper function of
+/// UsualArithmeticConversions()
+///
+/// \return false if the integer expression is an integer type and is
+/// successfully converted to the complex type.
+static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &intExpr,
+ ExprResult &complexExpr,
+ QualType intTy,
+ QualType complexTy,
+ bool skipCast) {
+ if (intTy->isComplexType() || intTy->isRealFloatingType()) return true;
+ if (skipCast) return false;
+ if (intTy->isIntegerType()) {
+ QualType fpTy = cast<ComplexType>(complexTy)->getElementType();
+ intExpr = S.ImpCastExprToType(intExpr.take(), fpTy, CK_IntegralToFloating);
+ intExpr = S.ImpCastExprToType(intExpr.take(), complexTy,
+ CK_FloatingRealToComplex);
+ } else {
+ assert(intTy->isComplexIntegerType());
+ intExpr = S.ImpCastExprToType(intExpr.take(), complexTy,
+ CK_IntegralComplexToFloatingComplex);
}
+ return false;
+}
- rhsExpr = UsualUnaryConversions(rhsExpr.take());
- if (rhsExpr.isInvalid())
- return QualType();
-
- // For conversion purposes, we ignore any qualifiers.
- // For example, "const float" and "float" are equivalent.
- QualType lhs =
- Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType();
- QualType rhs =
- Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType();
-
- // If both types are identical, no conversion is needed.
- if (lhs == rhs)
- return lhs;
-
- // If either side is a non-arithmetic type (e.g. a pointer), we are done.
- // The caller can deal with this (e.g. pointer + int).
- if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
- return lhs;
-
- // Apply unary and bitfield promotions to the LHS's type.
- QualType lhs_unpromoted = lhs;
- if (lhs->isPromotableIntegerType())
- lhs = Context.getPromotedIntegerType(lhs);
- QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get());
- if (!LHSBitfieldPromoteTy.isNull())
- lhs = LHSBitfieldPromoteTy;
- if (lhs != lhs_unpromoted && !isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast);
-
- // If both types are identical, no conversion is needed.
- if (lhs == rhs)
- return lhs;
-
- // At this point, we have two different arithmetic types.
-
- // Handle complex types first (C99 6.3.1.8p1).
- bool LHSComplexFloat = lhs->isComplexType();
- bool RHSComplexFloat = rhs->isComplexType();
- if (LHSComplexFloat || RHSComplexFloat) {
- // if we have an integer operand, the result is the complex type.
+/// \brief Takes two complex float types and converts them to the same type.
+/// Helper function of UsualArithmeticConversions()
+static QualType
+handleComplexFloatToComplexFloatConverstion(Sema &S, ExprResult &lhsExpr,
+ ExprResult &rhsExpr, QualType lhs,
+ QualType rhs, bool isCompAssign) {
+ int order = S.Context.getFloatingTypeOrder(lhs, rhs);
- if (!RHSComplexFloat && !rhs->isRealFloatingType()) {
- if (rhs->isIntegerType()) {
- QualType fp = cast<ComplexType>(lhs)->getElementType();
- rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_IntegralToFloating);
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs,
- CK_FloatingRealToComplex);
- } else {
- assert(rhs->isComplexIntegerType());
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs,
- CK_IntegralComplexToFloatingComplex);
- }
- return lhs;
- }
+ if (order < 0) {
+ // _Complex float -> _Complex double
+ if (!isCompAssign)
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs,
+ CK_FloatingComplexCast);
+ return rhs;
+ }
+ if (order > 0)
+ // _Complex float -> _Complex double
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs,
+ CK_FloatingComplexCast);
+ return lhs;
+}
- if (!LHSComplexFloat && !lhs->isRealFloatingType()) {
- if (!isCompAssign) {
- // int -> float -> _Complex float
- if (lhs->isIntegerType()) {
- QualType fp = cast<ComplexType>(rhs)->getElementType();
- lhsExpr = ImpCastExprToType(lhsExpr.take(), fp,
- CK_IntegralToFloating);
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs,
+/// \brief Converts otherExpr to complex float and promotes complexExpr if
+/// necessary. Helper function of UsualArithmeticConversions()
+static QualType handleOtherComplexFloatConversion(Sema &S,
+ ExprResult &complexExpr,
+ ExprResult &otherExpr,
+ QualType complexTy,
+ QualType otherTy,
+ bool convertComplexExpr,
+ bool convertOtherExpr) {
+ int order = S.Context.getFloatingTypeOrder(complexTy, otherTy);
+
+ // If just the complexExpr is complex, the otherExpr needs to be converted,
+ // and the complexExpr might need to be promoted.
+ if (order > 0) { // complexExpr is wider
+ // float -> _Complex double
+ if (convertOtherExpr) {
+ QualType fp = cast<ComplexType>(complexTy)->getElementType();
+ otherExpr = S.ImpCastExprToType(otherExpr.take(), fp, CK_FloatingCast);
+ otherExpr = S.ImpCastExprToType(otherExpr.take(), complexTy,
CK_FloatingRealToComplex);
- } else {
- assert(lhs->isComplexIntegerType());
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs,
- CK_IntegralComplexToFloatingComplex);
- }
- }
- return rhs;
}
+ return complexTy;
+ }
- // This handles complex/complex, complex/float, or float/complex.
- // When both operands are complex, the shorter operand is converted to the
- // type of the longer, and that is the type of the result. This corresponds
- // to what is done when combining two real floating-point operands.
- // The fun begins when size promotion occur across type domains.
- // From H&S 6.3.4: When one operand is complex and the other is a real
- // floating-point type, the less precise type is converted, within it's
- // real or complex domain, to the precision of the other type. For example,
- // when combining a "long double" with a "double _Complex", the
- // "double _Complex" is promoted to "long double _Complex".
- int order = Context.getFloatingTypeOrder(lhs, rhs);
-
- // If both are complex, just cast to the more precise type.
- if (LHSComplexFloat && RHSComplexFloat) {
- if (order > 0) {
- // _Complex float -> _Complex double
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs,
- CK_FloatingComplexCast);
- return lhs;
-
- } else if (order < 0) {
- // _Complex float -> _Complex double
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs,
- CK_FloatingComplexCast);
- return rhs;
- }
- return lhs;
- }
+ // otherTy is at least as wide. Find its corresponding complex type.
+ QualType result = (order == 0 ? complexTy :
+ S.Context.getComplexType(otherTy));
- // If just the LHS is complex, the RHS needs to be converted,
- // and the LHS might need to be promoted.
- if (LHSComplexFloat) {
- if (order > 0) { // LHS is wider
- // float -> _Complex double
- QualType fp = cast<ComplexType>(lhs)->getElementType();
- rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_FloatingCast);
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs,
+ // double -> _Complex double
+ if (convertOtherExpr)
+ otherExpr = S.ImpCastExprToType(otherExpr.take(), result,
CK_FloatingRealToComplex);
- return lhs;
- }
-
- // RHS is at least as wide. Find its corresponding complex type.
- QualType result = (order == 0 ? lhs : Context.getComplexType(rhs));
- // double -> _Complex double
- rhsExpr = ImpCastExprToType(rhsExpr.take(), result,
- CK_FloatingRealToComplex);
+ // _Complex float -> _Complex double
+ if (convertComplexExpr && order < 0)
+ complexExpr = S.ImpCastExprToType(complexExpr.take(), result,
+ CK_FloatingComplexCast);
- // _Complex float -> _Complex double
- if (!isCompAssign && order < 0)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), result,
- CK_FloatingComplexCast);
+ return result;
+}
- return result;
- }
+/// \brief Handle arithmetic conversion with complex types. Helper function of
+/// UsualArithmeticConversions()
+static QualType handleComplexFloatConversion(Sema &S, ExprResult &lhsExpr,
+ ExprResult &rhsExpr, QualType lhs,
+ QualType rhs, bool isCompAssign) {
+ // if we have an integer operand, the result is the complex type.
+ if (!handleIntegerToComplexFloatConversion(S, rhsExpr, lhsExpr, rhs, lhs,
+ /*skipCast*/false))
+ return lhs;
+ if (!handleIntegerToComplexFloatConversion(S, lhsExpr, rhsExpr, lhs, rhs,
+ /*skipCast*/isCompAssign))
+ return rhs;
- // Just the RHS is complex, so the LHS needs to be converted
- // and the RHS might need to be promoted.
- assert(RHSComplexFloat);
-
- if (order < 0) { // RHS is wider
- // float -> _Complex double
- if (!isCompAssign) {
- QualType fp = cast<ComplexType>(rhs)->getElementType();
- lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_FloatingCast);
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs,
- CK_FloatingRealToComplex);
- }
- return rhs;
- }
+ // This handles complex/complex, complex/float, or float/complex.
+ // When both operands are complex, the shorter operand is converted to the
+ // type of the longer, and that is the type of the result. This corresponds
+ // to what is done when combining two real floating-point operands.
+ // The fun begins when size promotion occur across type domains.
+ // From H&S 6.3.4: When one operand is complex and the other is a real
+ // floating-point type, the less precise type is converted, within it's
+ // real or complex domain, to the precision of the other type. For example,
+ // when combining a "long double" with a "double _Complex", the
+ // "double _Complex" is promoted to "long double _Complex".
- // LHS is at least as wide. Find its corresponding complex type.
- QualType result = (order == 0 ? rhs : Context.getComplexType(lhs));
+ bool LHSComplexFloat = lhs->isComplexType();
+ bool RHSComplexFloat = rhs->isComplexType();
- // double -> _Complex double
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), result,
- CK_FloatingRealToComplex);
+ // If both are complex, just cast to the more precise type.
+ if (LHSComplexFloat && RHSComplexFloat)
+ return handleComplexFloatToComplexFloatConverstion(S, lhsExpr, rhsExpr,
+ lhs, rhs, isCompAssign);
+
+ // If only one operand is complex, promote it if necessary and convert the
+ // other operand to complex.
+ if (LHSComplexFloat)
+ return handleOtherComplexFloatConversion(
+ S, lhsExpr, rhsExpr, lhs, rhs, /*convertComplexExpr*/!isCompAssign,
+ /*convertOtherExpr*/ true);
+
+ assert(RHSComplexFloat);
+ return handleOtherComplexFloatConversion(
+ S, rhsExpr, lhsExpr, rhs, lhs, /*convertComplexExpr*/true,
+ /*convertOtherExpr*/ !isCompAssign);
+}
+
+/// \brief Hande arithmetic conversion from integer to float. Helper function
+/// of UsualArithmeticConversions()
+static QualType handleIntToFloatConversion(Sema &S, ExprResult &floatExpr,
+ ExprResult &intExpr,
+ QualType floatTy, QualType intTy,
+ bool convertFloat, bool convertInt) {
+ if (intTy->isIntegerType()) {
+ if (convertInt)
+ // Convert intExpr to the lhs floating point type.
+ intExpr = S.ImpCastExprToType(intExpr.take(), floatTy,
+ CK_IntegralToFloating);
+ return floatTy;
+ }
+
+ // Convert both sides to the appropriate complex float.
+ assert(intTy->isComplexIntegerType());
+ QualType result = S.Context.getComplexType(floatTy);
+
+ // _Complex int -> _Complex float
+ if (convertInt)
+ intExpr = S.ImpCastExprToType(intExpr.take(), result,
+ CK_IntegralComplexToFloatingComplex);
- // _Complex float -> _Complex double
- if (order > 0)
- rhsExpr = ImpCastExprToType(rhsExpr.take(), result,
- CK_FloatingComplexCast);
+ // float -> _Complex float
+ if (convertFloat)
+ floatExpr = S.ImpCastExprToType(floatExpr.take(), result,
+ CK_FloatingRealToComplex);
- return result;
- }
+ return result;
+}
- // Now handle "real" floating types (i.e. float, double, long double).
+/// \brief Handle arithmethic conversion with floating point types. Helper
+/// function of UsualArithmeticConversions()
+static QualType handleFloatConversion(Sema &S, ExprResult &lhsExpr,
+ ExprResult &rhsExpr, QualType lhs,
+ QualType rhs, bool isCompAssign) {
bool LHSFloat = lhs->isRealFloatingType();
bool RHSFloat = rhs->isRealFloatingType();
- if (LHSFloat || RHSFloat) {
- // If we have two real floating types, convert the smaller operand
- // to the bigger result.
- if (LHSFloat && RHSFloat) {
- int order = Context.getFloatingTypeOrder(lhs, rhs);
- if (order > 0) {
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast);
- return lhs;
- }
-
- assert(order < 0 && "illegal float comparison");
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast);
- return rhs;
- }
-
- // If we have an integer operand, the result is the real floating type.
- if (LHSFloat) {
- if (rhs->isIntegerType()) {
- // Convert rhs to the lhs floating point type.
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralToFloating);
- return lhs;
- }
-
- // Convert both sides to the appropriate complex float.
- assert(rhs->isComplexIntegerType());
- QualType result = Context.getComplexType(lhs);
- // _Complex int -> _Complex float
- rhsExpr = ImpCastExprToType(rhsExpr.take(), result,
- CK_IntegralComplexToFloatingComplex);
-
- // float -> _Complex float
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), result,
- CK_FloatingRealToComplex);
-
- return result;
- }
-
- assert(RHSFloat);
- if (lhs->isIntegerType()) {
- // Convert lhs to the rhs floating point type.
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralToFloating);
- return rhs;
+ // If we have two real floating types, convert the smaller operand
+ // to the bigger result.
+ if (LHSFloat && RHSFloat) {
+ int order = S.Context.getFloatingTypeOrder(lhs, rhs);
+ if (order > 0) {
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast);
+ return lhs;
}
- // Convert both sides to the appropriate complex float.
- assert(lhs->isComplexIntegerType());
- QualType result = Context.getComplexType(rhs);
-
- // _Complex int -> _Complex float
+ assert(order < 0 && "illegal float comparison");
if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), result,
- CK_IntegralComplexToFloatingComplex);
-
- // float -> _Complex float
- rhsExpr = ImpCastExprToType(rhsExpr.take(), result,
- CK_FloatingRealToComplex);
-
- return result;
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast);
+ return rhs;
}
- // Handle GCC complex int extension.
- // FIXME: if the operands are (int, _Complex long), we currently
- // don't promote the complex. Also, signedness?
+ if (LHSFloat)
+ return handleIntToFloatConversion(S, lhsExpr, rhsExpr, lhs, rhs,
+ /*convertFloat=*/!isCompAssign,
+ /*convertInt=*/ true);
+ assert(RHSFloat);
+ return handleIntToFloatConversion(S, rhsExpr, lhsExpr, rhs, lhs,
+ /*convertInt=*/ true,
+ /*convertFloat=*/!isCompAssign);
+}
+
+/// \brief Handle conversions with GCC complex int extension. Helper function
+/// of UsualArithmeticConverions()
+// FIXME: if the operands are (int, _Complex long), we currently
+// don't promote the complex. Also, signedness?
+static QualType handleComplexIntConvsersion(Sema &S, ExprResult &lhsExpr,
+ ExprResult &rhsExpr, QualType lhs,
+ QualType rhs, bool isCompAssign) {
const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+
if (lhsComplexInt && rhsComplexInt) {
- int order = Context.getIntegerTypeOrder(lhsComplexInt->getElementType(),
- rhsComplexInt->getElementType());
+ int order = S.Context.getIntegerTypeOrder(lhsComplexInt->getElementType(),
+ rhsComplexInt->getElementType());
assert(order && "inequal types with equal element ordering");
if (order > 0) {
// _Complex int -> _Complex long
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexCast);
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs,
+ CK_IntegralComplexCast);
return lhs;
}
if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexCast);
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs,
+ CK_IntegralComplexCast);
return rhs;
- } else if (lhsComplexInt) {
- // int -> _Complex int
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralRealToComplex);
- return lhs;
- } else if (rhsComplexInt) {
+ }
+
+ if (lhsComplexInt) {
// int -> _Complex int
- if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs,
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs,
CK_IntegralRealToComplex);
- return rhs;
+ return lhs;
}
- // Finally, we have two differing integer types.
+ assert(rhsComplexInt);
+ // int -> _Complex int
+ if (!isCompAssign)
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs,
+ CK_IntegralRealToComplex);
+ return rhs;
+}
+
+/// \brief Handle integer arithmetic conversions. Helper function of
+/// UsualArithmeticConversions()
+static QualType handleIntegerConversion(Sema &S, ExprResult &lhsExpr,
+ ExprResult &rhsExpr, QualType lhs,
+ QualType rhs, bool isCompAssign) {
// The rules for this case are in C99 6.3.1.8
- int compare = Context.getIntegerTypeOrder(lhs, rhs);
- bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
- rhsSigned = rhs->hasSignedIntegerRepresentation();
+ int order = S.Context.getIntegerTypeOrder(lhs, rhs);
+ bool lhsSigned = lhs->hasSignedIntegerRepresentation();
+ bool rhsSigned = rhs->hasSignedIntegerRepresentation();
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
- if (compare >= 0) {
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
+ if (order >= 0) {
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
- } else if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
+ } else if (!isCompAssign)
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
- } else if (compare != (lhsSigned ? 1 : -1)) {
+ } else if (order != (lhsSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (rhsSigned) {
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
} else if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
- } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
+ } else if (S.Context.getIntWidth(lhs) != S.Context.getIntWidth(rhs)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (lhsSigned) {
- rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
} else if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
} else {
// The signed type is higher-ranked than the unsigned type,
@@ -853,14 +822,85 @@
// on most 32-bit systems). Use the unsigned type corresponding
// to the signed type.
QualType result =
- Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
- rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast);
+ S.Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
+ rhsExpr = S.ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast);
if (!isCompAssign)
- lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast);
+ lhsExpr = S.ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast);
return result;
}
}
+/// 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.
+/// FIXME: verify the conversion rules for "complex int" are consistent with
+/// GCC.
+QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr,
+ ExprResult &rhsExpr,
+ bool isCompAssign) {
+ if (!isCompAssign) {
+ lhsExpr = UsualUnaryConversions(lhsExpr.take());
+ if (lhsExpr.isInvalid())
+ return QualType();
+ }
+
+ rhsExpr = UsualUnaryConversions(rhsExpr.take());
+ if (rhsExpr.isInvalid())
+ return QualType();
+
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType lhs =
+ Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType();
+ QualType rhs =
+ Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType();
+
+ // If both types are identical, no conversion is needed.
+ if (lhs == rhs)
+ return lhs;
+
+ // If either side is a non-arithmetic type (e.g. a pointer), we are done.
+ // The caller can deal with this (e.g. pointer + int).
+ if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
+ return lhs;
+
+ // Apply unary and bitfield promotions to the LHS's type.
+ QualType lhs_unpromoted = lhs;
+ if (lhs->isPromotableIntegerType())
+ lhs = Context.getPromotedIntegerType(lhs);
+ QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get());
+ if (!LHSBitfieldPromoteTy.isNull())
+ lhs = LHSBitfieldPromoteTy;
+ if (lhs != lhs_unpromoted && !isCompAssign)
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast);
+
+ // If both types are identical, no conversion is needed.
+ if (lhs == rhs)
+ return lhs;
+
+ // At this point, we have two different arithmetic types.
+
+ // Handle complex types first (C99 6.3.1.8p1).
+ if (lhs->isComplexType() || rhs->isComplexType())
+ return handleComplexFloatConversion(*this, lhsExpr, rhsExpr, lhs, rhs,
+ isCompAssign);
+
+ // Now handle "real" floating types (i.e. float, double, long double).
+ if (lhs->isRealFloatingType() || rhs->isRealFloatingType())
+ return handleFloatConversion(*this, lhsExpr, rhsExpr, lhs, rhs,
+ isCompAssign);
+
+ // Handle GCC complex int extension.
+ if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType())
+ return handleComplexIntConvsersion(*this, lhsExpr, rhsExpr, lhs, rhs,
+ isCompAssign);
+
+ // Finally, we have two differing integer types.
+ return handleIntegerConversion(*this, lhsExpr, rhsExpr, lhs, rhs,
+ isCompAssign);
+}
+
//===----------------------------------------------------------------------===//
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
More information about the cfe-commits
mailing list