Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -475,7 +475,7 @@ +,--,*,/,% yes yes yes -- bitwise operators &,|,^,~ yes yes yes -- >>,<< yes yes yes -- -!, &&, || yes -- yes [#]_ -- +!, &&, || yes -- yes -- ==, !=, >, <, >=, <= yes yes yes -- = yes yes yes yes :? [#]_ yes -- yes -- @@ -488,7 +488,6 @@ See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. -.. [#] unary operator ! is not implemented, however && and || are. .. [#] While OpenCL and GCC vectors both implement the comparison operator(?:) as a 'select', they operate somewhat differently. OpenCL selects based on signedness of the condition operands, but GCC vectors use normal bool conversions (that is, != 0). Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -2742,7 +2742,9 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { // Perform vector logical not on comparison with zero vector. - if (E->getType()->isExtVectorType()) { + if (E->getType()->isVectorType() && + E->getType()->castAs()->getVectorKind() == + VectorType::GenericVector) { Value *Oper = Visit(E->getSubExpr()); Value *Zero = llvm::Constant::getNullValue(Oper->getType()); Value *Result; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -14436,12 +14436,19 @@ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) { + const VectorType *VTy = resultType->castAs(); + if (VTy->getVectorKind() != VectorType::GenericVector) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + // Vector logical not returns the signed variant of the operand type. resultType = GetSignedVectorType(resultType); break; } else { - // FIXME: GCC's vector extension permits the usage of '!' with a vector - // type in C++. We should allow that here too. return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } Index: clang/test/CodeGen/vector.c =================================================================== --- clang/test/CodeGen/vector.c +++ clang/test/CodeGen/vector.c @@ -80,3 +80,19 @@ // CHECK: define void @lax_vector_compare2(<2 x i32>* {{.*sret.*}}, i64 {{.*}}, i64 {{.*}}) // CHECK: icmp eq <2 x i32> + +vec_int1 lax_vector_logic_not1(int x, vec_int1 y) { + y = x != y; + return y; +} + +// CHECK: define i32 @lax_vector_logic_not1(i32 {{.*}}, i32 {{.*}}) +// CHECK: icmp ne i32 + +vec_int2 lax_vector_logic_not2(long long x, vec_int2 y) { + y = x != y; + return y; +} + +// CHECK: define void @lax_vector_logic_not2(<2 x i32>* {{.*sret.*}}, i64 {{.*}}, i64 {{.*}}) +// CHECK: icmp ne <2 x i32> Index: clang/test/Sema/vector-gcc-compat.cpp =================================================================== --- clang/test/Sema/vector-gcc-compat.cpp +++ clang/test/Sema/vector-gcc-compat.cpp @@ -83,7 +83,7 @@ v2i64 v2i64_c = (v2i64){3, 1}; // expected-warning {{compound literals are a C99-specific feature}} v2i64 v2i64_r; - v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}} + v2i64_r = !v2i64_a; v2i64_r = ~v2i64_a; v2i64_r = v2i64_a ? v2i64_b : v2i64_c;