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:
parent
853fbea313
commit
4f89ccb1df
|
@ -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
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue