diff --git a/clang/AST/Type.cpp b/clang/AST/Type.cpp index 3ce5d9c9dead..cd06c7e7832b 100644 --- a/clang/AST/Type.cpp +++ b/clang/AST/Type.cpp @@ -279,13 +279,17 @@ bool Type::isComplexType() const { return isa(CanonicalType); } +bool Type::isVectorType() const { + return isa(CanonicalType); +} + bool Type::isArithmeticType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() != BuiltinType::Void; if (const TagType *TT = dyn_cast(CanonicalType)) if (TT->getDecl()->getKind() == Decl::Enum) return true; - return isa(CanonicalType); + return isa(CanonicalType) || isa(CanonicalType); } bool Type::isScalarType() const { diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index d692c1b7ae06..ac85868b8ecc 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -303,6 +303,7 @@ private: /// type checking binary operators (subroutines of ParseBinOp). inline void InvalidOperands(SourceLocation l, Expr *lex, Expr *rex); + inline QualType CheckVectorOperands(SourceLocation l, Expr *lex, Expr *rex); inline QualType CheckMultiplyDivideOperands( // C99 6.5.5 Expr *lex, Expr *rex, SourceLocation OpLoc); inline QualType CheckRemainderOperands( // C99 6.5.5 diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 54f6115a7742..fad3196c7916 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -703,9 +703,11 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { // expressions that surpress this implicit conversion (&, sizeof). rhsType = DefaultFunctionArrayConversion(rhsType); - if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) + if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) { + if (lhsType->isVectorType() || rhsType->isVectorType()) + return lhsType == rhsType ? Compatible : Incompatible; return Compatible; - else if (lhsType->isPointerType()) { + } else if (lhsType->isPointerType()) { if (rhsType->isIntegerType()) return PointerFromInt; @@ -734,10 +736,27 @@ inline void Sema::InvalidOperands(SourceLocation loc, Expr *lex, Expr *rex) { lex->getSourceRange(), rex->getSourceRange()); } +inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *lex, + Expr *rex) { + QualType lhsType = lex->getType(), rhsType = rex->getType(); + + // make sure the vector types are identical. + if (lhsType == rhsType) + return lhsType; + // You cannot convert between vector values of different size. + Diag(loc, diag::err_typecheck_vector_not_convertable, + lex->getType().getAsString(), rex->getType().getAsString(), + lex->getSourceRange(), rex->getSourceRange()); + return QualType(); +} + inline QualType Sema::CheckMultiplyDivideOperands( Expr *lex, Expr *rex, SourceLocation loc) { QualType lhsType = lex->getType(), rhsType = rex->getType(); + + if (lhsType->isVectorType() || rhsType->isVectorType()) + return CheckVectorOperands(loc, lex, rex); QualType resType = UsualArithmeticConversions(lhsType, rhsType); if (resType->isArithmeticType()) @@ -762,6 +781,9 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 Expr *lex, Expr *rex, SourceLocation loc) { QualType lhsType = lex->getType(), rhsType = rex->getType(); + + if (lhsType->isVectorType() || rhsType->isVectorType()) + return CheckVectorOperands(loc, lex, rex); QualType resType = UsualArithmeticConversions(lhsType, rhsType); // handle the common case first (both operands are arithmetic). @@ -779,6 +801,9 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6 Expr *lex, Expr *rex, SourceLocation loc) { QualType lhsType = lex->getType(), rhsType = rex->getType(); + + if (lhsType->isVectorType() || rhsType->isVectorType()) + return CheckVectorOperands(loc, lex, rex); QualType resType = UsualArithmeticConversions(lhsType, rhsType); // handle the common case first (both operands are arithmetic). @@ -869,6 +894,9 @@ inline QualType Sema::CheckBitwiseOperands( Expr *lex, Expr *rex, SourceLocation loc) { QualType lhsType = lex->getType(), rhsType = rex->getType(); + + if (lhsType->isVectorType() || rhsType->isVectorType()) + return CheckVectorOperands(loc, lex, rex); QualType resType = UsualArithmeticConversions(lhsType, rhsType); if (resType->isIntegerType()) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 09e0cab7b33f..640c9883f8fb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -227,6 +227,9 @@ public: bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) + /// Vector types + bool isVectorType() const; // GCC vector type. + /// Derived types (C99 6.2.5p20). isFunctionType() is also a derived type. bool isDerivedType() const; bool isPointerType() const; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 46dbadb93614..8addaa493c6a 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -439,6 +439,8 @@ DIAG(err_attribute_invalid_size, ERROR, "vector size not an integral multiple of component size") DIAG(err_attribute_zero_size, ERROR, "zero vector size") +DIAG(err_typecheck_vector_not_convertable, ERROR, + "can't convert between vector values of different size ('%0' and '%1')") // Function Parameter Semantic Analysis. DIAG(err_void_param_with_identifier, ERROR,