Index: llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td +++ llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -519,6 +519,7 @@ def ZeroLengthArray : DiagGroup<"zero-length-array">; def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">; def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">; +def GNUVecElemSize : DiagGroup<"gnu-vec-elem-size">; def Fallback : DiagGroup<"fallback">; // This covers both the deprecated case (in C++98) @@ -758,7 +759,8 @@ GNUStringLiteralOperatorTemplate, GNUUnionCast, GNUVariableSizedTypeNotAtEnd, ZeroLengthArray, GNUZeroLineDirective, - GNUZeroVariadicMacroArguments]>; + GNUZeroVariadicMacroArguments, + GNUVecElemSize]>; // A warning group for warnings about code that clang accepts but gcc doesn't. def GccCompat : DiagGroup<"gcc-compat">; Index: llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2301,6 +2301,9 @@ "cannot convert between vector and non-scalar values (%0 and %1)">; def err_typecheck_vector_lengths_not_equal : Error< "vector operands do not have the same number of elements (%0 and %1)">; +def warn_typecheck_vector_element_sizes_not_equal : Warning< + "vector operands do not have the same elements sizes (%0 and %1)">, + InGroup, DefaultIgnore; def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< Index: llvm/tools/clang/lib/Sema/SemaExpr.cpp =================================================================== --- llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -8784,6 +8784,65 @@ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } + if (!S.LangOpts.OpenCL && !S.LangOpts.ZVector) { + const BuiltinType *LHSBT = LHSEleType->getAs(); + const BuiltinType *RHSBT = RHSEleType->getAs(); + if (LHSBT != RHSBT) { + BuiltinType::Kind LHSKind = LHSBT->getKind(); + BuiltinType::Kind RHSKind = RHSBT->getKind(); + bool DiffSizes = true; + switch (LHSKind) { + case BuiltinType::Char_S: + DiffSizes = + RHSKind != BuiltinType::Char_U && RHSKind != BuiltinType::UChar; + break; + case BuiltinType::Char_U: + DiffSizes = + RHSKind != BuiltinType::Char_S && RHSKind != BuiltinType::UChar; + break; + case BuiltinType::UChar: + DiffSizes = + RHSKind != BuiltinType::Char_U && RHSKind != BuiltinType::Char_S; + break; + case BuiltinType::Short: + DiffSizes = RHSKind != BuiltinType::UShort; + break; + case BuiltinType::UShort: + DiffSizes = RHSKind != BuiltinType::Short; + break; + case BuiltinType::Int: + DiffSizes = RHSKind != BuiltinType::UInt; + break; + case BuiltinType::UInt: + DiffSizes = RHSKind != BuiltinType::Int; + break; + case BuiltinType::Long: + DiffSizes = RHSKind != BuiltinType::ULong; + break; + case BuiltinType::ULong: + DiffSizes = RHSKind != BuiltinType::Long; + break; + case BuiltinType::LongLong: + DiffSizes = RHSKind != BuiltinType::ULongLong; + break; + case BuiltinType::ULongLong: + DiffSizes = RHSKind != BuiltinType::LongLong; + break; + default: + DiffSizes = true; + break; + } + if (DiffSizes) { + S.Diag(Loc, diag::warn_typecheck_vector_element_sizes_not_equal) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + if (S.Diags.getDiagnosticLevel( + diag::warn_typecheck_vector_element_sizes_not_equal, Loc) == + DiagnosticsEngine::Level::Error) + return QualType(); + } + } + } } else { // ...else expand RHS to match the number of elements in LHS. QualType VecTy = Index: llvm/tools/clang/test/Sema/vecshift.c =================================================================== --- llvm/tools/clang/test/Sema/vecshift.c +++ llvm/tools/clang/test/Sema/vecshift.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -DERR -Werror-gnu-vec-elem-size -verify %s typedef __attribute__((__ext_vector_type__(8))) char vector_char8; typedef __attribute__((__ext_vector_type__(8))) short vector_short8; @@ -48,16 +49,30 @@ vus8 = 1 << vus8; vc8 = vc8 << vc8; +#ifdef ERR + vi8 = vi8 << vuc8; // expected-error {{vector operands do not have the same elements sizes}} + vuc8 = vuc8 << vi8; // expected-error {{vector operands do not have the same elements sizes}} + vus8 = vus8 << vui8; // expected-error {{vector operands do not have the same elements sizes}} + vui8 = vui8 << vs8; // expected-error {{vector operands do not have the same elements sizes}} +#else vi8 = vi8 << vuc8; vuc8 = vuc8 << vi8; vus8 = vus8 << vui8; vui8 = vui8 << vs8; +#endif vc8 <<= vc8; +#ifdef ERR + vi8 <<= vuc8; // expected-error {{vector operands do not have the same elements sizes}} + vuc8 <<= vi8; // expected-error {{vector operands do not have the same elements sizes}} + vus8 <<= vui8; // expected-error {{vector operands do not have the same elements sizes}} + vui8 <<= vs8; // expected-error {{vector operands do not have the same elements sizes}} +#else vi8 <<= vuc8; vuc8 <<= vi8; vus8 <<= vui8; vui8 <<= vs8; +#endif c <<= vc8; // expected-error {{assigning to 'char' from incompatible type}} i <<= vuc8; // expected-error {{assigning to 'int' from incompatible type}}