LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
/// an objective pointer type for the purpose of GC'ability
bool hasObjCPointerRepresentation() const;
+ /// \brief Determine whether this type has an integer representation
+ /// of some sort, e.g., it is an integer type or a vector.
+ bool hasIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an signed integer representation
+ /// of some sort, e.g., it is an signed integer type or a vector.
+ bool hasSignedIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an unsigned integer representation
+ /// of some sort, e.g., it is an unsigned integer type or a vector.
+ bool hasUnsignedIntegerRepresentation() const;
+
/// \brief Determine whether this type has a floating-point representation
/// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const;
-
+
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can.
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
- assert(T->isSignedIntegerType() && "Unexpected type");
+ assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
// Turn <4 x signed int> -> <4 x unsigned int>
if (const VectorType *VTy = T->getAs<VectorType>())
// 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->isSignedIntegerType(),
- rhsSigned = rhs->isSignedIntegerType();
+ bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
+ rhsSigned = rhs->hasSignedIntegerRepresentation();
QualType destType;
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
// FIXME: In C++, enum types are never integer types.
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true;
+ return false;
+}
+
+bool Type::hasIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
- return false;
+ else
+ return isIntegerType();
}
/// \brief Determine whether this type is an integral type.
/// isSignedIntegerType - Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
-/// an enum decl which has a signed representation, or a vector of signed
-/// integer element type.
+/// an enum decl which has a signed representation
bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ return false;
+}
+
+bool Type::hasSignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
- return false;
+ else
+ return isSignedIntegerType();
}
/// isUnsignedIntegerType - Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
-/// decl which has an unsigned representation, or a vector of unsigned integer
-/// element type.
+/// decl which has an unsigned representation
bool Type::isUnsignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ return false;
+}
+
+bool Type::hasUnsignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
- return false;
+ else
+ return isUnsignedIntegerType();
}
bool Type::isFloatingType() const {
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
- if (RetTy->isSignedIntegerType()) {
+ if (RetTy->hasSignedIntegerRepresentation()) {
RetAttrs |= llvm::Attribute::SExt;
- } else if (RetTy->isUnsignedIntegerType()) {
+ } else if (RetTy->hasUnsignedIntegerRepresentation()) {
RetAttrs |= llvm::Attribute::ZExt;
}
// FALLTHROUGH
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
if (Ops.LHS->getType()->isFPOrFPVectorTy())
return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
- else if (Ops.Ty->isUnsignedIntegerType())
+ else if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div");
else
return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div");
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isAnyPointerType()) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (!isa<llvm::PointerType>(Ops.LHS->getType())) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
CGF.EmitBlock(Cont);
}
- if (Ops.Ty->isUnsignedIntegerType())
+ if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateLShr(Ops.LHS, RHS, "shr");
return Builder.CreateAShr(Ops.LHS, RHS, "shr");
}
if (LHS->getType()->isFPOrFPVectorTy()) {
Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc,
LHS, RHS, "cmp");
- } else if (LHSTy->isSignedIntegerType()) {
+ } else if (LHSTy->hasSignedIntegerRepresentation()) {
Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc,
LHS, RHS, "cmp");
} else {
// with mask. If so, verify that RHS is an integer vector type with the
// same number of elts as lhs.
if (TheCall->getNumArgs() == 2) {
- if (!RHSType->isIntegerType() ||
+ if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements)
Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
<< SourceRange(TheCall->getArg(1)->getLocStart(),
// We don't do anything special if this isn't an unsigned integral
// comparison: we're only interested in integral comparisons, and
// signed comparisons only happen in cases we don't care to warn about.
- if (!T->isUnsignedIntegerType())
+ if (!T->hasUnsignedIntegerRepresentation())
return AnalyzeImpConvsInComparison(S, E);
Expr *lex = E->getLHS()->IgnoreParenImpCasts();
// Check to see if one of the (unmodified) operands is of different
// signedness.
Expr *signedOperand, *unsignedOperand;
- if (lex->getType()->isSignedIntegerType()) {
- assert(!rex->getType()->isSignedIntegerType() &&
+ if (lex->getType()->hasSignedIntegerRepresentation()) {
+ assert(!rex->getType()->hasSignedIntegerRepresentation() &&
"unsigned comparison between two signed integer expressions?");
signedOperand = lex;
unsignedOperand = rex;
- } else if (rex->getType()->isSignedIntegerType()) {
+ } else if (rex->getType()->hasSignedIntegerRepresentation()) {
signedOperand = rex;
unsignedOperand = lex;
} else {
<< LHSExp->getSourceRange() << RHSExp->getSourceRange());
}
// C99 6.5.2.1p1
- if (!(IndexExpr->getType()->isIntegerType() &&
- IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent())
+ if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
<< IndexExpr->getSourceRange());
// "unsigned char" on systems where "char" is unsigned.
if (lhptee->isCharType())
lhptee = Context.UnsignedCharTy;
- else if (lhptee->isSignedIntegerType())
+ else if (lhptee->hasSignedIntegerRepresentation())
lhptee = Context.getCorrespondingUnsignedType(lhptee);
if (rhptee->isCharType())
rhptee = Context.UnsignedCharTy;
- else if (rhptee->isSignedIntegerType())
+ else if (rhptee->hasSignedIntegerRepresentation())
rhptee = Context.getCorrespondingUnsignedType(rhptee);
if (lhptee == rhptee) {
QualType Sema::CheckRemainderOperands(
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
- if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
return CheckVectorOperands(Loc, lex, rex);
return InvalidOperands(Loc, lex, rex);
}
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
- if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+ if (!lex->getType()->hasIntegerRepresentation() ||
+ !rex->getType()->hasIntegerRepresentation())
return InvalidOperands(Loc, lex, rex);
// Vector shifts promote their scalar inputs to vector type.
// Return the type for the comparison, which is the same as vector type for
// integer vectors, or an integer type of identical size and number of
// elements for floating point vectors.
- if (lType->isIntegerType())
+ if (lType->hasIntegerRepresentation())
return lType;
const VectorType *VTy = lType->getAs<VectorType>();
inline QualType Sema::CheckBitwiseOperands(
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
- return CheckVectorOperands(Loc, lex, rex);
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
+ return CheckVectorOperands(Loc, lex, rex);
+
+ return InvalidOperands(Loc, lex, rex);
+ }
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
// C99 does not support '~' for complex conjugation.
Diag(OpLoc, diag::ext_integer_complement_complex)
<< resultType << Input->getSourceRange();
- else if (!resultType->isIntegerType())
+ else if (!resultType->hasIntegerRepresentation())
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input->getSourceRange());
break;
if (Method && DiagnoseUseOfDecl(Method, Loc))
return ExprError();
} else if (!Context.getObjCIdType().isNull() &&
- (ReceiverType->isPointerType() ||
- (ReceiverType->isIntegerType() &&
- ReceiverType->isScalarType()))) {
+ (ReceiverType->isPointerType() ||
+ ReceiverType->isIntegerType())) {
// Implicitly convert integers and pointers to 'id' but emit a warning.
Diag(Loc, diag::warn_bad_receiver_type)
<< ReceiverType
return;
}
// the base type must be integer or float, and can't already be a vector.
- if (CurType->isVectorType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
+ if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
--- /dev/null
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wvector-conversions
+typedef unsigned int v2u __attribute__ ((vector_size (8)));
+typedef int v2s __attribute__ ((vector_size (8)));
+typedef float v2f __attribute__ ((vector_size(8)));
+
+void test1(v2u v2ua, v2s v2sa, v2f v2fa) {
+ // Bitwise binary operators
+ (void)(v2ua & v2ua);
+ (void)(v2fa & v2fa); // expected-error{{invalid operands to binary expression}}
+
+ // Unary operators
+ (void)(~v2ua);
+ (void)(~v2fa); // expected-error{{invalid argument type 'v2f' to unary}}
+
+ // Arrays
+ int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u'}}
+ int array2[17];
+ // FIXME: error message below needs type!
+ (void)(array2[v2ua]); // expected-error{{array subscript is not an integer}}
+
+ v2u *v2u_ptr = 0;
+ v2s *v2s_ptr;
+ v2s_ptr = v2u_ptr; // expected-warning{{converts between pointers to integer types with different sign}}
+}
+