diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -478,7 +478,7 @@ !, &&, || yes -- yes [#]_ -- ==, !=, >, <, >=, <= yes yes yes -- = yes yes yes yes -:? [#]_ yes -- yes -- +?: [#]_ yes -- yes -- sizeof yes yes yes yes C-style cast yes yes yes no reinterpret_cast yes no yes no @@ -489,9 +489,11 @@ 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). +.. [#] ternary operator(?:) has different behaviors depending on condition + operand's vector type. If the condition is a GNU vector (i.e. __vector_size__), + it's only available in C++ and uses normal bool conversions (that is, != 0). + If it's an extension (OpenCL) vector, it's only available in C and OpenCL C. + And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9). Matrix Types ============ diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4432,8 +4432,8 @@ // OpenCL: If the condition is a vector, we can treat this condition like // the select function. - if (CGF.getLangOpts().OpenCL - && condExpr->getType()->isVectorType()) { + if ((CGF.getLangOpts().OpenCL && condExpr->getType()->isVectorType()) || + condExpr->getType()->isExtVectorType()) { CGF.incrementProfileCounter(E); llvm::Value *CondV = CGF.EmitScalarExpr(condExpr); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8078,7 +8078,8 @@ // The OpenCL operator with a vector condition is sufficiently // different to merit its own checker. - if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) + if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) || + Cond.get()->getType()->isExtVectorType()) return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc); // First, check the condition. diff --git a/clang/test/Sema/ext_vector_comparisons.c b/clang/test/Sema/ext_vector_comparisons.c --- a/clang/test/Sema/ext_vector_comparisons.c +++ b/clang/test/Sema/ext_vector_comparisons.c @@ -28,3 +28,19 @@ return vec > vec; // no-warning return vec >= vec; // no-warning } + +static int4 test3() { + int4 i0, i1; + + return i0 > i1 ? i0 : i1; // no-error + return i0 ? i0 : i1; // no-error +} + +static float4 test4() { + float4 f0, f1; + + // This would actually generate implicit casting warning + // under Weverything flag but we don't really care here + return f0 > f1 ? f0 : f1; // no-error + return f0 ? f0 : f1; // expected-error {{used type 'float4' (vector of 4 'float' values) where floating point type is not allowed}} +}