Fix for PR2501; this patch makes usual arithmetic conversions for

integers which have the same width and different signedness work 
correctly. (The testcase in PR2501 uses a comparison between long and 
unsigned int).

llvm-svn: 52853
This commit is contained in:
Eli Friedman 2008-06-28 06:23:08 +00:00
parent 853fbea313
commit 4f89ccb1df
6 changed files with 97 additions and 5 deletions

View File

@ -370,6 +370,19 @@ public:
return T->getAsStructureType() == SelStructType;
}
//===--------------------------------------------------------------------===//
// Integer Predicates
//===--------------------------------------------------------------------===//
// The width of an integer, as defined in C99 6.2.6.2. This is the number
// of bits in an integer type excluding any padding bits.
unsigned getIntWidth(QualType T);
// Per C99 6.2.5p6, for every signed integer type, there is a corresponding
// unsigned integer type. This method takes a signed type, and returns the
// corresponding unsigned integer type.
QualType getCorrespondingUnsignedType(QualType T);
//===--------------------------------------------------------------------===//
// Serialization
//===--------------------------------------------------------------------===//

View File

@ -48,6 +48,7 @@ namespace clang {
class VariableArrayType;
class IncompleteArrayType;
class RecordType;
class EnumType;
class ComplexType;
class TagType;
class TypedefType;
@ -352,6 +353,7 @@ public:
const RecordType *getAsStructureType() const;
const TypedefType *getAsTypedefType() const;
const RecordType *getAsUnionType() const;
const EnumType *getAsEnumType() const;
const VectorType *getAsVectorType() const; // GCC vector type.
const ComplexType *getAsComplexType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.

View File

@ -1756,6 +1756,41 @@ bool ASTContext::typesAreCompatible(QualType LHS_NC, QualType RHS_NC) {
return true; // should never get here...
}
//===----------------------------------------------------------------------===//
// Integer Predicates
//===----------------------------------------------------------------------===//
unsigned ASTContext::getIntWidth(QualType T) {
if (T == BoolTy)
return 1;
// At the moment, only bool has padding bits
return (unsigned)getTypeSize(T);
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
assert(T->isSignedIntegerType() && "Unexpected type");
if (const EnumType* ETy = T->getAsEnumType())
T = ETy->getDecl()->getIntegerType();
const BuiltinType* BTy = T->getAsBuiltinType();
assert (BTy && "Unexpected signed integer type");
switch (BTy->getKind()) {
case BuiltinType::Char_S:
case BuiltinType::SChar:
return UnsignedCharTy;
case BuiltinType::Short:
return UnsignedShortTy;
case BuiltinType::Int:
return UnsignedIntTy;
case BuiltinType::Long:
return UnsignedLongTy;
case BuiltinType::LongLong:
return UnsignedLongLongTy;
default:
assert(0 && "Unexpected signed integer type");
return QualType();
}
}
//===----------------------------------------------------------------------===//
// Serialization Support
//===----------------------------------------------------------------------===//

View File

@ -390,6 +390,13 @@ const RecordType *Type::getAsUnionType() const {
return 0;
}
const EnumType *Type::getAsEnumType() const {
// Check the canonicalized unqualified type directly; the more complex
// version is unnecessary because there isn't any typedef information
// to preserve.
return dyn_cast<EnumType>(CanonicalType.getUnqualifiedType());
}
const ComplexType *Type::getAsComplexType() const {
// Are we directly a complex type?
if (const ComplexType *CTy = dyn_cast<ComplexType>(this))

View File

@ -1221,12 +1221,35 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
}
}
// Finally, we have two differing integer types.
if (Context.getIntegerTypeOrder(lhs, rhs) >= 0) { // convert the rhs
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
// The rules for this case are in C99 6.3.1.8
int compare = Context.getIntegerTypeOrder(lhs, rhs);
bool lhsSigned = lhs->isSignedIntegerType(),
rhsSigned = rhs->isSignedIntegerType();
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 (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.
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 = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
}
if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
return rhs;
if (!isCompAssign) {
ImpCastExprToType(lhsExpr, destType);
ImpCastExprToType(rhsExpr, destType);
}
return destType;
}
// CheckPointerTypesForAssignment - This is a very tricky routine (despite

View File

@ -0,0 +1,12 @@
// RUN: clang -fsyntax-only -verify %s
// Check types are the same through redeclaration
unsigned long x;
__typeof(1u+1l) x;
unsigned y;
__typeof(1+1u) y;
__typeof(1u+1) y;
long long z;
__typeof(1ll+1u) z;