Index: llvm/tools/clang/lib/Sema/SemaExpr.cpp =================================================================== --- llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -8721,7 +8721,8 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { // OpenCL v1.1 s6.3.j says RHS can be a vector only if LHS is a vector. - if (!LHS.get()->getType()->isVectorType()) { + if ((S.LangOpts.OpenCL || S.LangOpts.ZVector) && + !LHS.get()->getType()->isVectorType()) { S.Diag(Loc, diag::err_shift_rhs_only_vector) << RHS.get()->getType() << LHS.get()->getType() << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); @@ -8737,8 +8738,10 @@ if (RHS.isInvalid()) return QualType(); QualType LHSType = LHS.get()->getType(); - const VectorType *LHSVecTy = LHSType->castAs(); - QualType LHSEleType = LHSVecTy->getElementType(); + // Note that LHS might be a scalar because the routine calls not only in + // OpenCL case. + const VectorType *LHSVecTy = LHSType->getAs(); + QualType LHSEleType = LHSVecTy ? LHSVecTy->getElementType() : LHSType; // Note that RHS might not be a vector. QualType RHSType = RHS.get()->getType(); @@ -8758,7 +8761,19 @@ return QualType(); } - if (RHSVecTy) { + if (!LHSVecTy) { + assert(RHSVecTy); + if (IsCompAssign) + return RHSType; + if (LHSEleType != RHSEleType) { + LHS = S.ImpCastExprToType(LHS.get(),RHSEleType, CK_IntegralCast); + LHSEleType = RHSEleType; + } + QualType VecTy = + S.Context.getExtVectorType(LHSEleType, RHSVecTy->getNumElements()); + LHS = S.ImpCastExprToType(LHS.get(), VecTy, CK_VectorSplat); + LHSType = VecTy; + } else if (RHSVecTy) { // OpenCL v1.1 s6.3.j says that for vector types, the operators // are applied component-wise. So if RHS is a vector, then ensure // that the number of elements is the same as LHS... Index: llvm/tools/clang/test/Sema/vecshift.c =================================================================== --- llvm/tools/clang/test/Sema/vecshift.c +++ llvm/tools/clang/test/Sema/vecshift.c @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef __attribute__((__ext_vector_type__(8))) char vector_char8; +typedef __attribute__((__ext_vector_type__(8))) short vector_short8; +typedef __attribute__((__ext_vector_type__(8))) int vector_int8; +typedef __attribute__((__ext_vector_type__(8))) unsigned char vector_uchar8; +typedef __attribute__((__ext_vector_type__(8))) unsigned short vector_ushort8; +typedef __attribute__((__ext_vector_type__(8))) unsigned int vector_uint8; +typedef __attribute__((__ext_vector_type__(4))) char vector_char4; +typedef __attribute__((__ext_vector_type__(4))) short vector_short4; +typedef __attribute__((__ext_vector_type__(4))) int vector_int4; +typedef __attribute__((__ext_vector_type__(4))) unsigned char vector_uchar4; +typedef __attribute__((__ext_vector_type__(4))) unsigned short vector_ushort4; +typedef __attribute__((__ext_vector_type__(4))) unsigned int vector_uint4; + +char c; +short s; +int i; +unsigned char uc; +unsigned short us; +unsigned int ui; +vector_char8 vc8; +vector_short8 vs8; +vector_int8 vi8; +vector_uchar8 vuc8; +vector_ushort8 vus8; +vector_uint8 vui8; +vector_char4 vc4; +vector_short4 vs4; +vector_int4 vi4; +vector_uchar4 vuc4; +vector_ushort4 vus4; +vector_uint4 vui4; + +void foo() { + vc8 = 1 << vc8; + vuc8 = 1 << vuc8; + vi8 = 1 << vi8; + vui8 = 1 << vui8; + vs8 = 1 << vs8; + vus8 = 1 << vus8; + + vc8 = c << vc8; + vuc8 = i << vuc8; + vi8 = uc << vi8; + vui8 = us << vui8; + vs8 = ui << vs8; + vus8 = 1 << vus8; + + vc8 = vc8 << vc8; + vi8 = vi8 << vuc8; + vuc8 = vuc8 << vi8; + vus8 = vus8 << vui8; + vui8 = vui8 << vs8; + + vc4 = vc4 << vc8; // expected-error {{vector operands do not have the same number of elements}} + vi4 = vi4 << vuc8; // expected-error {{vector operands do not have the same number of elements}} + vuc4 = vuc4 << vi8; // expected-error {{vector operands do not have the same number of elements}} + vus4 = vus4 << vui8; // expected-error {{vector operands do not have the same number of elements}} + vui4 = vui4 << vs8; // expected-error {{vector operands do not have the same number of elements}} + + + vc8 = vc8 << vc4; // expected-error {{vector operands do not have the same number of elements}} + vi8 = vi8 << vuc4; // expected-error {{vector operands do not have the same number of elements}} + vuc8 = vuc8 << vi4; // expected-error {{vector operands do not have the same number of elements}} + vus8 = vus8 << vui4; // expected-error {{vector operands do not have the same number of elements}} + vui8 = vui8 << vs4; // expected-error {{vector operands do not have the same number of elements}} + + vc8 <<= vc8; + vi8 <<= vuc8; + vuc8 <<= vi8; + vus8 <<= vui8; + vui8 <<= vs8; + + c <<= vc8; // expected-error {{assigning to 'char' from incompatible type}} + i <<= vuc8; // expected-error {{assigning to 'int' from incompatible type}} + uc <<= vi8; // expected-error {{assigning to 'unsigned char' from incompatible type}} + us <<= vui8; // expected-error {{assigning to 'unsigned short' from incompatible type}} + ui <<= vs8; // expected-error {{assigning to 'unsigned int' from incompatible type}} +}