[cfe-commits] r118993 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/SemaExpr.cpp
John McCall
rjmccall at apple.com
Sat Nov 13 00:17:46 PST 2010
Author: rjmccall
Date: Sat Nov 13 02:17:45 2010
New Revision: 118993
URL: http://llvm.org/viewvc/llvm-project?rev=118993&view=rev
Log:
Bring UsualArithmeticConversionsType back into Sema and cast the
operands appropriately. There are a lot of missing complex-related
cast kinds.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=118993&r1=118992&r2=118993&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sat Nov 13 02:17:45 2010
@@ -1304,11 +1304,6 @@
QualType mergeObjCGCQualifiers(QualType, QualType);
- /// UsualArithmeticConversionsType - handles the various conversions
- /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
- /// and returns the result type of that conversion.
- QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
-
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=118993&r1=118992&r2=118993&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Nov 13 02:17:45 2010
@@ -5537,146 +5537,6 @@
FunctionType::ExtInfo());
}
-QualType
-ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
- // Perform the usual unary conversions. We do this early so that
- // integral promotions to "int" can allow us to exit early, in the
- // lhs == rhs check. Also, for conversion purposes, we ignore any
- // qualifiers. For example, "const float" and "float" are
- // equivalent.
- if (lhs->isPromotableIntegerType())
- lhs = getPromotedIntegerType(lhs);
- else
- lhs = lhs.getUnqualifiedType();
- if (rhs->isPromotableIntegerType())
- rhs = getPromotedIntegerType(rhs);
- else
- rhs = rhs.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;
-
- // 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() || rhs->isComplexIntegerType()) {
- // convert the rhs to the lhs complex type.
- return lhs;
- }
- if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
- // convert the lhs to the rhs complex type.
- 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".
- int result = getFloatingTypeOrder(lhs, rhs);
-
- if (result > 0) { // The left side is bigger, convert rhs.
- rhs = getFloatingTypeOfSizeWithinDomain(lhs, rhs);
- } else if (result < 0) { // The right side is bigger, convert lhs.
- lhs = getFloatingTypeOfSizeWithinDomain(rhs, lhs);
- }
- // At this point, lhs and rhs have the same rank/size. Now, make sure the
- // domains match. This is a requirement for our implementation, C99
- // does not require this promotion.
- if (lhs != rhs) { // Domains don't match, we have complex/float mix.
- if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
- return rhs;
- } else { // handle "_Complex double, double".
- return lhs;
- }
- }
- return lhs; // The domain/size match exactly.
- }
- // 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()) {
- // convert rhs to the lhs floating point type.
- return lhs;
- }
- if (rhs->isComplexIntegerType()) {
- // convert rhs to the complex floating point type.
- return getComplexType(lhs);
- }
- if (lhs->isIntegerType()) {
- // convert lhs to the rhs floating point type.
- return rhs;
- }
- if (lhs->isComplexIntegerType()) {
- // convert lhs to the complex floating point type.
- return getComplexType(rhs);
- }
- // We have two real floating types, float/complex combos were handled above.
- // Convert the smaller operand to the bigger result.
- int result = getFloatingTypeOrder(lhs, rhs);
- if (result > 0) // convert the rhs
- return lhs;
- assert(result < 0 && "illegal float comparison");
- return rhs; // convert the lhs
- }
- if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
- // Handle GCC complex int extension.
- const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
- const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
-
- if (lhsComplexInt && rhsComplexInt) {
- if (getIntegerTypeOrder(lhsComplexInt->getElementType(),
- rhsComplexInt->getElementType()) >= 0)
- return lhs; // convert the rhs
- return rhs;
- } else if (lhsComplexInt && rhs->isIntegerType()) {
- // convert the rhs to the lhs complex type.
- return lhs;
- } else if (rhsComplexInt && lhs->isIntegerType()) {
- // convert the lhs to the rhs complex type.
- return rhs;
- }
- }
- // Finally, we have two differing integer types.
- // The rules for this case are in C99 6.3.1.8
- int compare = getIntegerTypeOrder(lhs, rhs);
- bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
- rhsSigned = rhs->hasSignedIntegerRepresentation();
- QualType destType;
- if (lhsSigned == rhsSigned) {
- // Same signedness; use the higher-ranked type
- destType = compare >= 0 ? lhs : rhs;
- } else if (compare != (lhsSigned ? 1 : -1)) {
- // The unsigned type has greater than or equal rank to the
- // signed type, so use the unsigned type
- destType = lhsSigned ? rhs : lhs;
- } else if (getIntWidth(lhs) != 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.
- destType = lhsSigned ? lhs : rhs;
- } else {
- // The signed type is higher-ranked than the unsigned type,
- // but isn't actually any bigger (like unsigned int and long
- // on most 32-bit systems). Use the unsigned type corresponding
- // to the signed type.
- destType = getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
- }
- return destType;
-}
-
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
GVALinkage External = GVA_StrongExternal;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=118993&r1=118992&r2=118993&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Nov 13 02:17:45 2010
@@ -348,7 +348,6 @@
return false;
}
-
/// 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
@@ -378,19 +377,254 @@
if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
return lhs;
- // Perform bitfield promotions.
+ // 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);
if (!LHSBitfieldPromoteTy.isNull())
lhs = LHSBitfieldPromoteTy;
- QualType RHSBitfieldPromoteTy = Context.isPromotableBitField(rhsExpr);
- if (!RHSBitfieldPromoteTy.isNull())
- rhs = RHSBitfieldPromoteTy;
+ if (lhs != lhs_unpromoted && !isCompAssign)
+ ImpCastExprToType(lhsExpr, lhs, CK_IntegralCast);
- QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);
- if (!isCompAssign)
- ImpCastExprToType(lhsExpr, destType, CK_Unknown);
- ImpCastExprToType(rhsExpr, destType, CK_Unknown);
- return destType;
+ // 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.
+
+ if (LHSComplexFloat &&
+ (rhs->isIntegerType() || rhs->isComplexIntegerType())) {
+ // convert the rhs to the lhs complex type.
+ ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+ return lhs;
+ }
+
+ if (!LHSComplexFloat && RHSComplexFloat &&
+ (lhs->isIntegerType() || lhs->isComplexIntegerType())) {
+ // convert the lhs to the rhs complex type.
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+ 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".
+ 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
+ ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+ return lhs;
+
+ } else if (order < 0) {
+ // _Complex float -> _Complex double
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+ return rhs;
+ }
+ return lhs;
+ }
+
+ // 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
+ ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+ return lhs;
+ }
+
+ // RHS is at least as wide. Find its corresponding complex type.
+ QualType result = (order == 0 ? lhs : Context.getComplexType(rhs));
+
+ // double -> _Complex double
+ ImpCastExprToType(rhsExpr, result, CK_Unknown);
+
+ // _Complex float -> _Complex double
+ if (!isCompAssign && order < 0)
+ ImpCastExprToType(lhsExpr, result, CK_Unknown);
+
+ return result;
+ }
+
+ // 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)
+ ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+ return rhs;
+ }
+
+ // LHS is at least as wide. Find its corresponding complex type.
+ QualType result = (order == 0 ? rhs : Context.getComplexType(lhs));
+
+ // double -> _Complex double
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_Unknown);
+
+ // _Complex float -> _Complex double
+ if (order > 0)
+ ImpCastExprToType(rhsExpr, result, CK_Unknown);
+
+ return result;
+ }
+
+ // Now handle "real" floating types (i.e. float, double, long double).
+ 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) {
+ ImpCastExprToType(rhsExpr, lhs, CK_FloatingCast);
+ return lhs;
+ }
+
+ assert(order < 0 && "illegal float comparison");
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, 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.
+ ImpCastExprToType(rhsExpr, 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
+ ImpCastExprToType(rhsExpr, result, CK_Unknown);
+
+ // float -> _Complex float
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_Unknown);
+
+ return result;
+ }
+
+ assert(RHSFloat);
+ if (lhs->isIntegerType()) {
+ // Convert lhs to the rhs floating point type.
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloating);
+ return rhs;
+ }
+
+ // Convert both sides to the appropriate complex float.
+ assert(lhs->isComplexIntegerType());
+ QualType result = Context.getComplexType(rhs);
+
+ // _Complex int -> _Complex float
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_Unknown);
+
+ // float -> _Complex float
+ ImpCastExprToType(rhsExpr, result, CK_Unknown);
+
+ return result;
+ }
+
+ // Handle GCC complex int extension.
+ // FIXME: if the operands are (int, _Complex long), we currently
+ // don't promote the complex. Also, signedness?
+ const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
+ const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+ if (lhsComplexInt && rhsComplexInt) {
+ int order = Context.getIntegerTypeOrder(lhsComplexInt->getElementType(),
+ rhsComplexInt->getElementType());
+ assert(order && "inequal types with equal element ordering");
+ if (order > 0) {
+ // _Complex int -> _Complex long
+ ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+ return lhs;
+ }
+
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+ return rhs;
+ } else if (lhsComplexInt) {
+ // int -> _Complex int
+ ImpCastExprToType(rhsExpr, lhs, CK_Unknown);
+ return lhs;
+ } else if (rhsComplexInt) {
+ // int -> _Complex int
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_Unknown);
+ return rhs;
+ }
+
+ // Finally, we have two differing integer types.
+ // 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();
+ if (lhsSigned == rhsSigned) {
+ // Same signedness; use the higher-ranked type
+ if (compare >= 0) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return rhs;
+ } else if (compare != (lhsSigned ? 1 : -1)) {
+ // The unsigned type has greater than or equal rank to the
+ // signed type, so use the unsigned type
+ if (rhsSigned) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return rhs;
+ } else if (Context.getIntWidth(lhs) != 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) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return rhs;
+ } else {
+ // The signed type is higher-ranked than the unsigned type,
+ // but isn't actually any bigger (like unsigned int and long
+ // on most 32-bit systems). Use the unsigned type corresponding
+ // to the signed type.
+ QualType result =
+ Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
+ ImpCastExprToType(rhsExpr, result, CK_IntegralCast);
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_IntegralCast);
+ return result;
+ }
}
//===----------------------------------------------------------------------===//
More information about the cfe-commits
mailing list