fhahn created this revision.
fhahn added reviewers: rjmccall, erichkeane, aaron.ballman.
fhahn requested review of this revision.
Herald added a project: clang.

This patch implements the conditional select operator for
ext_vector_types in C++. It does so by using the same semantics as for
C.

D71463 <https://reviews.llvm.org/D71463> added support for the conditional 
select operator for VectorType
in C++. Unfortunately the semantics between ext_vector_type in C are
different to VectorType in C++. Select for ext_vector_type is based on
the MSB of the condition vector, whereas for VectorType it is `!= 0`.

This unfortunately means that the behavior is inconsistent between
ExtVectorType and VectorType, but I think using the C semantics for
ExtVectorType in C++ as well should be less surprising for users.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D98055

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CodeGenCXX/ext-vector-type-conditional.cpp
  clang/test/CodeGenCXX/vector-conditional.cpp
  clang/test/CodeGenCXX/vector-size-conditional.cpp
  clang/test/SemaCXX/ext-vector-type-conditional.cpp
  clang/test/SemaCXX/vector-conditional.cpp
  clang/test/SemaCXX/vector-size-conditional.cpp

Index: 
===================================================================
--- /dev/null
+++ /dev/null
@@ -1,172 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux-pc -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++17
-// Note that this test depends on the size of long-long to be different from
-// int, so it specifies a triple.
-
-using FourShorts = short __attribute__((__vector_size__(8)));
-using TwoInts = int __attribute__((__vector_size__(8)));
-using TwoUInts = unsigned __attribute__((__vector_size__(8)));
-using FourInts = int __attribute__((__vector_size__(16)));
-using FourUInts = unsigned __attribute__((__vector_size__(16)));
-using TwoLongLong = long long __attribute__((__vector_size__(16)));
-using FourLongLong = long long __attribute__((__vector_size__(32)));
-using TwoFloats = float __attribute__((__vector_size__(8)));
-using FourFloats = float __attribute__((__vector_size__(16)));
-using TwoDoubles = double __attribute__((__vector_size__(16)));
-using FourDoubles = double __attribute__((__vector_size__(32)));
-
-FourShorts four_shorts;
-TwoInts two_ints;
-TwoUInts two_uints;
-FourInts four_ints;
-FourUInts four_uints;
-TwoLongLong two_ll;
-FourLongLong four_ll;
-TwoFloats two_floats;
-FourFloats four_floats;
-TwoDoubles two_doubles;
-FourDoubles four_doubles;
-
-enum E {};
-enum class SE {};
-E e;
-SE se;
-
-// Check the rules of the condition of the conditional operator.
-void Condition() {
-  // Only int types are allowed here, the rest should fail to convert to bool.
-  (void)(four_floats ? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
-  (void)(two_doubles ? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
-}
-
-// Check the rules of the LHS/RHS of the conditional operator.
-void Operands() {
-  (void)(four_ints ? four_ints : throw 1); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
-  (void)(four_ints ? throw 1 : four_ints); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
-  (void)(four_ints ?: throw 1);            // expected-error {{GNU vector conditional operand cannot be a throw expression}}
-  (void)(four_ints ? (void)1 : four_ints); // expected-error {{GNU vector conditional operand cannot be void}}
-  (void)(four_ints ?: (void)1);            // expected-error {{GNU vector conditional operand cannot be void}}
-
-  // Vector types must be the same element size as the condition.
-  (void)(four_ints ? two_ll : two_ll);             // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'TwoLongLong' (vector of 2 'long long' values) do not have the same number of elements}}
-  (void)(four_ints ? four_ll : four_ll);           // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'FourLongLong' (vector of 4 'long long' values) do not have elements of the same size}}
-  (void)(four_ints ? two_doubles : two_doubles);   // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'TwoDoubles' (vector of 2 'double' values) do not have the same number of elements}}
-  (void)(four_ints ? four_doubles : four_doubles); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'FourDoubles' (vector of 4 'double' values) do not have elements of the same size}}
-  (void)(four_ints ?: two_ints);                   // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'TwoInts' (vector of 2 'int' values)}}
-  (void)(four_ints ?: four_doubles);               // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourDoubles' (vector of 4 'double' values)}}
-
-  // Scalars are promoted, but must be the same element size.
-  (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) do not have elements of the same size}}
-  (void)(four_ints ? 5ll : 5);    // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(long long)))) long long' (vector of 4 'long long' values) do not have elements of the same size}}
-  (void)(four_ints ?: 3.0);       // expected-error {{cannot convert between scalar type 'double' and vector type 'FourInts' (vector of 4 'int' values) as implicit conversion would cause truncation}}
-  (void)(four_ints ?: 5ll);       // We allow this despite GCc not allowing this since we support integral->vector-integral conversions despite integer rank.
-
-  // This one would be allowed in GCC, but we don't allow vectors of enum. Also,
-  // the error message isn't perfect, since it is only going to be a problem
-  // when both sides are an enum, otherwise it'll be promoted to whatever type
-  // the other side causes.
-  (void)(four_ints ? e : e);                          // expected-error {{enumeration type 'E' is not allowed in a vector conditional}}
-  (void)(four_ints ? se : se);                        // expected-error {{enumeration type 'SE' is not allowed in a vector conditional}}
-  (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
-
-  // They must also be convertible.
-  (void)(four_ints ? 3.0f : 5u);
-  (void)(four_ints ? 3.0f : 5);
-  unsigned us = 5u;
-  int sint = 5;
-  short shrt = 5;
-  unsigned short uss = 5u;
-  // The following 2 error in GCC for truncation errors, but it seems
-  // unimportant and inconsistent to enforce that rule.
-  (void)(four_ints ? 3.0f : us);
-  (void)(four_ints ? 3.0f : sint);
-
-  // Test promotion:
-  (void)(four_shorts ? uss : shrt);  // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
-  (void)(four_shorts ? shrt : shrt); // should be fine.
-  (void)(four_ints ? uss : shrt);    // should be fine, since they get promoted to int.
-  (void)(four_ints ? shrt : shrt);   //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(short)))) short' (vector of 4 'short' values) do not have elements of the same size}}
-
-  // Vectors must be the same type as eachother.
-  (void)(four_ints ? four_uints : four_floats); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourFloats' (vector of 4 'float' values))}}
-  (void)(four_ints ? four_uints : four_ints);   // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourInts' (vector of 4 'int' values))}}
-  (void)(four_ints ? four_ints : four_uints);   // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourUInts' (vector of 4 'unsigned int' values))}}
-
-  // GCC rejects these, but our lax vector conversions don't seem to have a problem with them. Allow conversion of the float to an int as an extension.
-  (void)(four_ints ? four_uints : 3.0f);
-  (void)(four_ints ? four_ints : 3.0f);
-
-  // When there is a vector and a scalar, conversions must be legal.
-  (void)(four_ints ? four_floats : 3); // should work, ints can convert to floats.
-  (void)(four_ints ? four_uints : e);  // expected-error {{cannot convert between scalar type 'E' and vector type 'FourUInts'}}
-  (void)(four_ints ? four_uints : se); // expected-error {{cannot convert between vector and non-scalar values ('FourUInts' (vector of 4 'unsigned int' values) and 'SE'}}
-  // GCC permits this, but our conversion rules reject this for truncation.
-  (void)(two_ints ? two_ints : us);        // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'TwoInts'}}
-  (void)(four_shorts ? four_shorts : uss); // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'FourShorts'}}
-  (void)(four_ints ? four_floats : us);    // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'FourFloats'}}
-  (void)(four_ints ? four_floats : sint);  // expected-error {{cannot convert between scalar type 'int' and vector type 'FourFloats'}}
-}
-
-template <typename T1, typename T2>
-struct is_same {
-  static constexpr bool value = false;
-};
-template <typename T>
-struct is_same<T, T> {
-  static constexpr bool value = true;
-};
-template <typename T1, typename T2>
-constexpr bool is_same_v = is_same<T1, T2>::value;
-template <typename T>
-T &&declval();
-
-// Check the result types when given two vector types.
-void ResultTypes() {
-  // Vectors must be the same, but result is the type of the LHS/RHS.
-  static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ? declval<TwoInts>() : declval<TwoInts>())>);
-  static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : declval<TwoFloats>())>);
-
-  // When both are scalars, converts to vectors of common type.
-  static_assert(is_same_v<TwoUInts, decltype(declval<TwoInts>() ? declval<int>() : declval<unsigned int>())>);
-
-  // Constant is allowed since it doesn't truncate, and should promote to float.
-  static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<float>() : 5u)>);
-  static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? 5 : declval<float>())>);
-
-  // when only 1 is a scalar, it should convert to a compatible type.
-  static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : declval<float>())>);
-  static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ? declval<TwoInts>() : declval<int>())>);
-  static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : 5)>);
-
-  // For the Binary conditional operator, the result type is either the vector on the RHS (that fits the rules on size/count), or the scalar extended to the correct count.
-  static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ?: declval<TwoInts>())>);
-  static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ?: declval<int>())>);
-}
-
-template <typename Cond>
-void dependent_cond(Cond C) {
-  (void)(C ? 1 : 2);
-}
-
-template <typename Operand>
-void dependent_operand(Operand C) {
-  (void)(two_ints ? 1 : C);
-  (void)(two_ints ? C : 1);
-  (void)(two_ints ? C : C);
-}
-
-template <typename Cond, typename LHS, typename RHS>
-void all_dependent(Cond C, LHS L, RHS R) {
-  (void)(C ? L : R);
-}
-
-// Check dependent cases.
-void Templates() {
-  dependent_cond(two_ints);
-  dependent_operand(two_floats);
-  // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values))}}}
-  all_dependent(four_ints, four_uints, four_doubles); // expected-note {{in instantiation of}}
-
-  // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values))}}}
-  all_dependent(four_ints, four_uints, two_uints); // expected-note {{in instantiation of}}
-  all_dependent(four_ints, four_uints, four_uints);
-}
Index: clang/test/SemaCXX/ext-vector-type-conditional.cpp
===================================================================
--- clang/test/SemaCXX/ext-vector-type-conditional.cpp
+++ clang/test/SemaCXX/ext-vector-type-conditional.cpp
@@ -2,17 +2,17 @@
 // Note that this test depends on the size of long-long to be different from
 // int, so it specifies a triple.
 
-using FourShorts = short __attribute__((__vector_size__(8)));
-using TwoInts = int __attribute__((__vector_size__(8)));
-using TwoUInts = unsigned __attribute__((__vector_size__(8)));
-using FourInts = int __attribute__((__vector_size__(16)));
-using FourUInts = unsigned __attribute__((__vector_size__(16)));
-using TwoLongLong = long long __attribute__((__vector_size__(16)));
-using FourLongLong = long long __attribute__((__vector_size__(32)));
-using TwoFloats = float __attribute__((__vector_size__(8)));
-using FourFloats = float __attribute__((__vector_size__(16)));
-using TwoDoubles = double __attribute__((__vector_size__(16)));
-using FourDoubles = double __attribute__((__vector_size__(32)));
+using FourShorts = short __attribute__((ext_vector_type(4)));
+using TwoInts = int __attribute__((ext_vector_type(2)));
+using TwoUInts = unsigned __attribute__((ext_vector_type(2)));
+using FourInts = int __attribute__((ext_vector_type(4)));
+using FourUInts = unsigned __attribute__((ext_vector_type(4)));
+using TwoLongLong = long long __attribute__((ext_vector_type(2)));
+using FourLongLong = long long __attribute__((ext_vector_type(4)));
+using TwoFloats = float __attribute__((ext_vector_type(2)));
+using FourFloats = float __attribute__((ext_vector_type(4)));
+using TwoDoubles = double __attribute__((ext_vector_type(2)));
+using FourDoubles = double __attribute__((ext_vector_type(4)));
 
 FourShorts four_shorts;
 TwoInts two_ints;
@@ -55,9 +55,9 @@
   (void)(four_ints ?: four_doubles);               // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourDoubles' (vector of 4 'double' values)}}
 
   // Scalars are promoted, but must be the same element size.
-  (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) do not have elements of the same size}}
-  (void)(four_ints ? 5ll : 5);    // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(long long)))) long long' (vector of 4 'long long' values) do not have elements of the same size}}
-  (void)(four_ints ?: 3.0);       // expected-error {{cannot convert between scalar type 'double' and vector type 'FourInts' (vector of 4 'int' values) as implicit conversion would cause truncation}}
+  (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values) do not have elements of the same size}}
+  (void)(four_ints ? 5ll : 5);    // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'long long __attribute__((ext_vector_type(4)))' (vector of 4 'long long' values) do not have elements of the same size}}
+  (void)(four_ints ?: 3.0);       // expected-error {{annot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'double')}}
   (void)(four_ints ?: 5ll);       // We allow this despite GCc not allowing this since we support integral->vector-integral conversions despite integer rank.
 
   // This one would be allowed in GCC, but we don't allow vectors of enum. Also,
@@ -66,7 +66,7 @@
   // the other side causes.
   (void)(four_ints ? e : e);                          // expected-error {{enumeration type 'E' is not allowed in a vector conditional}}
   (void)(four_ints ? se : se);                        // expected-error {{enumeration type 'SE' is not allowed in a vector conditional}}
-  (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
+  (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}}
 
   // They must also be convertible.
   (void)(four_ints ? 3.0f : 5u);
@@ -81,29 +81,28 @@
   (void)(four_ints ? 3.0f : sint);
 
   // Test promotion:
-  (void)(four_shorts ? uss : shrt);  // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
+  (void)(four_shorts ? uss : shrt);  // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}}
   (void)(four_shorts ? shrt : shrt); // should be fine.
   (void)(four_ints ? uss : shrt);    // should be fine, since they get promoted to int.
-  (void)(four_ints ? shrt : shrt);   //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(short)))) short' (vector of 4 'short' values) do not have elements of the same size}}
+  (void)(four_ints ? shrt : shrt);   //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'short __attribute__((ext_vector_type(4)))' (vector of 4 'short' values) do not have elements of the same size}}
 
   // Vectors must be the same type as eachother.
   (void)(four_ints ? four_uints : four_floats); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourFloats' (vector of 4 'float' values))}}
   (void)(four_ints ? four_uints : four_ints);   // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourInts' (vector of 4 'int' values))}}
   (void)(four_ints ? four_ints : four_uints);   // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourUInts' (vector of 4 'unsigned int' values))}}
 
-  // GCC rejects these, but our lax vector conversions don't seem to have a problem with them. Allow conversion of the float to an int as an extension.
-  (void)(four_ints ? four_uints : 3.0f);
-  (void)(four_ints ? four_ints : 3.0f);
+  (void)(four_ints ? four_uints : 3.0f); // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'float')}}
+  (void)(four_ints ? four_ints : 3.0f);  // expected-error {{cannot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'float')}}
 
   // When there is a vector and a scalar, conversions must be legal.
   (void)(four_ints ? four_floats : 3); // should work, ints can convert to floats.
-  (void)(four_ints ? four_uints : e);  // expected-error {{cannot convert between scalar type 'E' and vector type 'FourUInts'}}
+  (void)(four_ints ? four_uints : e);  // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'E')}}
   (void)(four_ints ? four_uints : se); // expected-error {{cannot convert between vector and non-scalar values ('FourUInts' (vector of 4 'unsigned int' values) and 'SE'}}
-  // GCC permits this, but our conversion rules reject this for truncation.
-  (void)(two_ints ? two_ints : us);        // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'TwoInts'}}
-  (void)(four_shorts ? four_shorts : uss); // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'FourShorts'}}
-  (void)(four_ints ? four_floats : us);    // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'FourFloats'}}
-  (void)(four_ints ? four_floats : sint);  // expected-error {{cannot convert between scalar type 'int' and vector type 'FourFloats'}}
+
+  (void)(two_ints ? two_ints : us);
+  (void)(four_shorts ? four_shorts : uss);
+  (void)(four_ints ? four_floats : us);
+  (void)(four_ints ? four_floats : sint);
 }
 
 template <typename T1, typename T2>
@@ -163,10 +162,10 @@
 void Templates() {
   dependent_cond(two_ints);
   dependent_operand(two_floats);
-  // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values))}}}
+  // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values))}}}
   all_dependent(four_ints, four_uints, four_doubles); // expected-note {{in instantiation of}}
 
-  // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values))}}}
+  // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'unsigned int __attribute__((ext_vector_type(2)))' (vector of 2 'unsigned int' values))}}}
   all_dependent(four_ints, four_uints, two_uints); // expected-note {{in instantiation of}}
   all_dependent(four_ints, four_uints, four_uints);
 }
Index: clang/test/CodeGenCXX/vector-conditional.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/vector-conditional.cpp
@@ -1,231 +0,0 @@
-// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -Wno-unused -std=c++11 -emit-llvm -o - | FileCheck %s
-
-using FourShorts = short __attribute__((__vector_size__(8)));
-using TwoInts = int __attribute__((__vector_size__(8)));
-using TwoUInts = unsigned __attribute__((__vector_size__(8)));
-using FourInts = int __attribute__((__vector_size__(16)));
-using FourUInts = unsigned __attribute__((__vector_size__(16)));
-using TwoLongLong = long long __attribute__((__vector_size__(16)));
-using FourLongLong = long long __attribute__((__vector_size__(32)));
-using TwoFloats = float __attribute__((__vector_size__(8)));
-using FourFloats = float __attribute__((__vector_size__(16)));
-using TwoDoubles = double __attribute__((__vector_size__(16)));
-using FourDoubles = double __attribute__((__vector_size__(32)));
-
-FourShorts four_shorts;
-TwoInts two_ints;
-TwoUInts two_uints;
-FourInts four_ints;
-FourUInts four_uints;
-TwoLongLong two_ll;
-FourLongLong four_ll;
-TwoFloats two_floats;
-FourFloats four_floats;
-TwoDoubles two_doubles;
-FourDoubles four_doubles;
-
-short some_short;
-unsigned short some_ushort;
-int some_int;
-float some_float;
-unsigned int some_uint;
-long long some_ll;
-unsigned long long some_ull;
-double some_double;
-
-// CHECK: TwoVectorOps
-void TwoVectorOps() {
-  two_ints ? two_ints : two_ints;
-  // CHECK: %[[COND:.+]] = load <2 x i32>
-  // CHECK: %[[LHS:.+]] = load <2 x i32>
-  // CHECK: %[[RHS:.+]] = load <2 x i32>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <2 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <2 x i1> %[[NEZERO]], <2 x i32> %[[LHS]], <2 x i32> %[[RHS]]
-
-  two_ints ? two_floats : two_floats;
-  // CHECK: %[[COND:.+]] = load <2 x i32>
-  // CHECK: %[[LHS:.+]] = load <2 x float>
-  // CHECK: %[[RHS:.+]] = load <2 x float>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <2 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <2 x i1> %[[NEZERO]], <2 x float> %[[LHS]], <2 x float> %[[RHS]]
-
-  two_ll ? two_doubles : two_doubles;
-  // CHECK: %[[COND:.+]] = load <2 x i64>
-  // CHECK: %[[LHS:.+]] = load <2 x double>
-  // CHECK: %[[RHS:.+]] = load <2 x double>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <2 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <2 x i1> %[[NEZERO]], <2 x double> %[[LHS]], <2 x double> %[[RHS]]
-}
-
-// CHECK: TwoScalarOps
-void TwoScalarOps() {
-  four_shorts ? some_short : some_short;
-  // CHECK: %[[COND:.+]] = load <4 x i16>
-  // CHECK: %[[LHS:.+]] = load i16
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x i16> poison, i16 %[[LHS]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x i16> %[[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load i16
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i16> poison, i16 %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i16> %[[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i16> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i16> %[[LHS_SPLAT]], <4 x i16> %[[RHS_SPLAT]]
-
-  four_shorts ? some_ushort : some_ushort;
-  // CHECK: %[[COND:.+]] = load <4 x i16>
-  // CHECK: %[[LHS:.+]] = load i16
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x i16> poison, i16 %[[LHS]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x i16> %[[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load i16
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i16> poison, i16 %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i16> %[[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i16> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i16> %[[LHS_SPLAT]], <4 x i16> %[[RHS_SPLAT]]
-
-  four_ints ? some_ushort : some_short;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load i16
-  // CHECK: %[[LHS_ZEXT:.+]] = zext i16 %[[LHS]] to i32
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[LHS_ZEXT]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x i32> %[[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load i16
-  // CHECK: %[[RHS_SEXT:.+]] = sext i16 %[[RHS]] to i32
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[RHS_SEXT]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i32> %[[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS_SPLAT]], <4 x i32> %[[RHS_SPLAT]]
-
-  four_ints ? some_int : some_float;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load i32
-  // CHECK: %[[LHS_CONV:.+]] = sitofp i32 %[[LHS]] to float
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x float> poison, float %[[LHS_CONV]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x float> %[[LHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load float
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x float> poison, float %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x float> %[[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x float> %[[LHS_SPLAT]], <4 x float> %[[RHS_SPLAT]]
-
-  four_ll ? some_double : some_ll;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load double
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x double> poison, double %[[LHS]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x double> %[[LHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load i64
-  // CHECK: %[[RHS_CONV:.+]] = sitofp i64 %[[RHS]] to double
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x double> poison, double %[[RHS_CONV]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x double> %[[RHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x double> %[[LHS_SPLAT]], <4 x double> %[[RHS_SPLAT]]
-
-  four_ints ? some_int : some_short;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load i32
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[LHS]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x i32> %[[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load i16
-  // CHECK: %[[RHS_SEXT:.+]] = sext i16 %[[RHS]] to i32
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[RHS_SEXT]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i32> %[[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS_SPLAT]], <4 x i32> %[[RHS_SPLAT]]
-}
-
-// CHECK: OneScalarOp
-void OneScalarOp() {
-  four_ints ? four_ints : some_int;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load <4 x i32>
-  // CHECK: %[[RHS:.+]] = load i32
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i32> %[[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS]], <4 x i32> %[[RHS_SPLAT]]
-
-  four_ints ? four_ints : 5;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load <4 x i32>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS]], <4 x i32> <i32 5, i32 5, i32 5, i32 5>
-
-  four_ints ?: some_float;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[RHS:.+]] = load float
-  // CHECK: %[[RHS_CONV:.+]] = fptosi float %[[RHS]] to i32
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[RHS_CONV]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i32> %[[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[COND]], <4 x i32> %[[RHS_SPLAT]]
-
-  four_ints ? four_ints : 5.0f;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load <4 x i32>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS]], <4 x i32> <i32 5, i32 5, i32 5, i32 5>
-
-  four_ints ? some_float : four_ints;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load float
-  // CHECK: %[[LHS_CONV:.+]] = fptosi float %[[LHS]] to i32
-  // CHECK: %[[LHS_SPLAT_INSERT:.+]] = insertelement <4 x i32> poison, i32 %[[LHS_CONV]], i32 0
-  // CHECK: %[[LHS_SPLAT:.+]] = shufflevector <4 x i32> %[[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[RHS:.+]] = load <4 x i32>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i32> %[[LHS_SPLAT]], <4 x i32> %[[RHS]]
-
-  four_ints ? four_floats : some_float;
-  // CHECK: %[[COND:.+]] = load <4 x i32>
-  // CHECK: %[[LHS:.+]] = load <4 x float>
-  // CHECK: %[[RHS:.+]] = load float
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x float> poison, float %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x float> %[[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i32> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x float> %[[LHS]], <4 x float> %[[RHS_SPLAT]]
-
-  four_ll ? four_doubles : 6.0;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x double>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x double> %[[LHS]], <4 x double> <double 6.{{.+}}, double 6.{{.+}}, double 6.{{.+}}>
-
-  four_ll ? four_ll : 6.0;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x i64>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i64> %[[LHS]], <4 x i64> <i64 6, i64 6, i64 6, i64 6>
-
-  four_ll ? four_ll : 6;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x i64>
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i64> %[[LHS]], <4 x i64> <i64 6, i64 6, i64 6, i64 6>
-
-  four_ll ? four_ll : some_int;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x i64>
-  // CHECK: %[[RHS:.+]] = load i32
-  // CHECK: %[[RHS_CONV:.+]] = sext i32 %[[RHS]] to i64
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i64> poison, i64 %[[RHS_CONV]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i64> %[[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i64> %[[LHS]], <4 x i64> %[[RHS_SPLAT]]
-
-  four_ll ? four_ll : some_ll;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x i64>
-  // CHECK: %[[RHS:.+]] = load i64
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i64> poison, i64 %[[RHS]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i64> %[[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i64> %[[LHS]], <4 x i64> %[[RHS_SPLAT]]
-
-  four_ll ? four_ll : some_double;
-  // CHECK: %[[COND:.+]] = load <4 x i64>
-  // CHECK: %[[LHS:.+]] = load <4 x i64>
-  // CHECK: %[[RHS:.+]] = load double
-  // CHECK: %[[RHS_CONV:.+]] = fptosi double %[[RHS]] to i64
-  // CHECK: %[[RHS_SPLAT_INSERT:.+]] = insertelement <4 x i64> poison, i64 %[[RHS_CONV]], i32 0
-  // CHECK: %[[RHS_SPLAT:.+]] = shufflevector <4 x i64> %[[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
-  // CHECK: %[[NEZERO:.+]] = icmp ne <4 x i64> %[[COND]], zeroinitializer
-  // CHECK: %[[SELECT:.+]] = select <4 x i1> %[[NEZERO]], <4 x i64> %[[LHS]], <4 x i64> %[[RHS_SPLAT]]
-}
Index: clang/test/CodeGenCXX/ext-vector-type-conditional.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/ext-vector-type-conditional.cpp
@@ -0,0 +1,267 @@
+// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -Wno-unused -std=c++11 -emit-llvm -o - | FileCheck %s
+
+using FourShorts = short __attribute__((ext_vector_type(4)));
+using TwoInts = int __attribute__((ext_vector_type(2)));
+using TwoUInts = unsigned __attribute__((ext_vector_type(2)));
+using FourInts = int __attribute__((ext_vector_type(4)));
+using FourUInts = unsigned __attribute__((ext_vector_type(4)));
+using TwoLongLong = long long __attribute__((ext_vector_type(2)));
+using FourLongLong = long long __attribute__((ext_vector_type(4)));
+using TwoFloats = float __attribute__((ext_vector_type(2)));
+using FourFloats = float __attribute__((ext_vector_type(4)));
+using TwoDoubles = double __attribute__((ext_vector_type(2)));
+using FourDoubles = double __attribute__((ext_vector_type(4)));
+
+FourShorts four_shorts;
+TwoInts two_ints;
+TwoUInts two_uints;
+FourInts four_ints;
+FourUInts four_uints;
+TwoLongLong two_ll;
+FourLongLong four_ll;
+TwoFloats two_floats;
+FourFloats four_floats;
+TwoDoubles two_doubles;
+FourDoubles four_doubles;
+
+short some_short;
+unsigned short some_ushort;
+int some_int;
+float some_float;
+unsigned int some_uint;
+long long some_ll;
+unsigned long long some_ull;
+double some_double;
+
+// CHECK: TwoVectorOps
+void TwoVectorOps() {
+  two_ints ? two_ints : two_ints;
+  // CHECK: [[COND:%.+]] = load <2 x i32>
+  // CHECK: [[LHS:%.+]] = load <2 x i32>
+  // CHECK: [[RHS:%.+]] = load <2 x i32>
+  // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32>
+  // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], <i32 -1, i32 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS]], [[SEXT]]
+  // CHECK: = or <2 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  two_ints ? two_floats : two_floats;
+  // CHECK: [[COND:%.+]] = load <2 x i32>
+  // CHECK: [[LHS:%.+]] = load <2 x float>
+  // CHECK: [[RHS:%.+]] = load <2 x float>
+  // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32>
+  // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], <i32 -1, i32 -1>
+  // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x float> [[RHS]] to <2 x i32>
+  // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x float> [[LHS]] to <2 x i32>
+  // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS_EXT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS_EXT]], [[SEXT]]
+  // CHECK: [[OR:%.+]] = or <2 x i32> [[RHS_AND]], [[LHS_AND]]
+  // CHECK: = bitcast <2 x i32> [[OR]] to <2 x float>
+
+  two_ll ? two_doubles : two_doubles;
+  // CHECK: [[COND:%.+]] = load <2 x i64>
+  // CHECK: [[LHS:%.+]] = load <2 x double>
+  // CHECK: [[RHS:%.+]] = load <2 x double>
+  // CHECK: [[NEG:%.+]] = icmp slt <2 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i64>
+  // CHECK: [[XOR:%.+]] = xor <2 x i64> [[SEXT]], <i64 -1, i64 -1>
+  // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x double> [[RHS]] to <2 x i64>
+  // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x double> [[LHS]] to <2 x i64>
+  // CHECK: [[RHS_AND:%.+]] = and <2 x i64> [[RHS_EXT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <2 x i64> [[LHS_EXT]], [[SEXT]]
+  // CHECK: [[OR:%.+]] = or <2 x i64> [[RHS_AND]], [[LHS_AND]]
+  // CHECK: = bitcast <2 x i64> [[OR]] to <2 x double>
+}
+
+// CHECK: TwoScalarOps
+void TwoScalarOps() {
+  four_shorts ? some_short : some_short;
+  // CHECK: [[COND:%.+]] = load <4 x i16>
+  // CHECK: [[LHS:%.+]] = load i16
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load i16
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16>
+  // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], <i16 -1, i16 -1, i16 -1, i16 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]]
+  // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]]
+
+  four_shorts ? some_ushort : some_ushort;
+  // CHECK: [[COND:%.+]] = load <4 x i16>
+  // CHECK: [[LHS:%.+]] = load i16
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load i16
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16>
+  // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], <i16 -1, i16 -1, i16 -1, i16 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]]
+  // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]]
+
+  four_ints ? some_ushort : some_short;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load i16
+  // CHECK: [[LHS_ZEXT:%.+]] = zext i16 [[LHS]] to i32
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS_ZEXT]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load i16
+  // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  four_ints ? some_int : some_float;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load i32
+  // CHECK: [[LHS_CONV:%.+]] = sitofp i32 [[LHS]] to float
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[LHS_CONV]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x float> [[LHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load float
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32>
+  // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS_SPLAT]] to <4 x i32>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  four_ll ? some_double : some_ll;
+  // CHECK: [[COND:%.+]] = load <4 x i64>
+  // CHECK: [[LHS:%.+]] = load double
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[LHS]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x double> [[LHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load i64
+  // CHECK: [[RHS_CONV:%.+]] = sitofp i64 [[RHS]] to double
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[RHS_CONV]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x double> [[RHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
+  // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
+  // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x double> [[RHS_SPLAT]] to <4 x i64>
+  // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS_SPLAT]] to <4 x i64>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_CAST]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]]
+  // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
+
+  four_ints ? some_int : some_short;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load i32
+  // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS]], i32 0
+  // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
+  // CHECK: [[RHS:%.+]] = load i16
+  // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+}
+
+// CHECK: OneScalarOp
+void OneScalarOp() {
+  four_ints ? four_ints : some_int;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load <4 x i32>
+  // CHECK: [[RHS:%.+]] = load i32
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  four_ints ? four_ints : 5;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load <4 x i32>
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> <i32 5, i32 5, i32 5, i32 5>, [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  four_ints ? four_floats : some_float;
+  // CHECK: [[COND:%.+]] = load <4 x i32>
+  // CHECK: [[LHS:%.+]] = load <4 x float>
+  // CHECK: [[RHS:%.+]] = load float
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
+  // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
+  // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32>
+  // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS]] to <4 x i32>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]]
+  // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
+
+  four_ll ? four_doubles : 6.0;
+  // CHECK: [[COND:%.+]] = load <4 x i64>
+  // CHECK: [[LHS:%.+]] = load <4 x double>
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
+  // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
+  // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS]] to <4 x i64>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i64> <i64 4618441417868443648, i64 4618441417868443648, i64 4618441417868443648, i64 4618441417868443648>, [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]]
+  // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
+
+  four_ll ? four_ll : 6;
+  // CHECK: [[COND:%.+]] = load <4 x i64>
+  // CHECK: [[LHS:%.+]] = load <4 x i64>
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
+  // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i64> <i64 6, i64 6, i64 6, i64 6>, [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
+  // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
+
+  four_ll ? four_ll : some_int;
+  // CHECK: [[COND:%.+]] = load <4 x i64>
+  // CHECK: [[LHS:%.+]] = load <4 x i64>
+  // CHECK: [[RHS:%.+]] = load i32
+  // CHECK: [[RHS_CONV:%.+]] = sext i32 [[RHS]] to i64
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS_CONV]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
+  // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
+  // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
+
+  four_ll ? four_ll : some_ll;
+  // CHECK: [[COND:%.+]] = load <4 x i64>
+  // CHECK: [[LHS:%.+]] = load <4 x i64>
+  // CHECK: [[RHS:%.+]] = load i64
+  // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS]], i32 0
+  // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
+  // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
+  // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
+  // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
+  // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]]
+  // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
+  // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5945,28 +5945,31 @@
 // extension.
 static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
                                                  QualType CondTy) {
-  if (!CondTy->isVectorType() || CondTy->isExtVectorType())
+  if (!CondTy->isVectorType() && !CondTy->isExtVectorType())
     return false;
   const QualType EltTy =
-      cast<VectorType>(CondTy.getCanonicalType())->getElementType();
+      CondTy->isVectorType()
+          ? cast<VectorType>(CondTy.getCanonicalType())->getElementType()
+          : cast<ExtVectorType>(CondTy.getCanonicalType())->getElementType();
 
   assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() &&
          "Vectors cant be boolean or enum types");
   return EltTy->isIntegralType(Ctx);
 }
 
-QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
-                                              ExprResult &RHS,
-                                              SourceLocation QuestionLoc) {
+template <class VectorTy>
+QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
+                                           ExprResult &RHS,
+                                           SourceLocation QuestionLoc) {
   LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
   RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
 
   QualType CondType = Cond.get()->getType();
-  const auto *CondVT = CondType->castAs<VectorType>();
+  const auto *CondVT = CondType->castAs<VectorTy>();
   QualType CondElementTy = CondVT->getElementType();
   unsigned CondElementCount = CondVT->getNumElements();
   QualType LHSType = LHS.get()->getType();
-  const auto *LHSVT = LHSType->getAs<VectorType>();
+  const auto *LHSVT = LHSType->getAs<VectorTy>();
   QualType RHSType = RHS.get()->getType();
   const auto *RHSVT = RHSType->getAs<VectorType>();
 
@@ -5974,17 +5977,6 @@
 
   // FIXME: In the future we should define what the Extvector conditional
   // operator looks like.
-  if (LHSVT && isa<ExtVectorType>(LHSVT)) {
-    Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
-        << /*isExtVector*/ true << LHSType;
-    return {};
-  }
-
-  if (RHSVT && isa<ExtVectorType>(RHSVT)) {
-    Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
-        << /*isExtVector*/ true << RHSType;
-    return {};
-  }
 
   if (LHSVT && RHSVT) {
     // If both are vector types, they must be the same type.
@@ -6017,17 +6009,21 @@
           << /*isExtVector*/ false << ResultElementTy;
       return {};
     }
-    ResultType = Context.getVectorType(
-        ResultElementTy, CondType->castAs<VectorType>()->getNumElements(),
-        VectorType::GenericVector);
+    if (std::is_same<VectorTy, ExtVectorType>::value)
+      ResultType = Context.getExtVectorType(
+          ResultElementTy, CondType->castAs<VectorTy>()->getNumElements());
+    else
+      ResultType = Context.getVectorType(
+          ResultElementTy, CondType->castAs<VectorTy>()->getNumElements(),
+          VectorType::GenericVector);
 
     LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
     RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
   }
 
-  assert(!ResultType.isNull() && ResultType->isVectorType() &&
+  assert(!ResultType.isNull() && ResultType->getAs<VectorTy>() &&
          "Result should have been a vector type");
-  auto *ResultVectorTy = ResultType->castAs<VectorType>();
+  auto *ResultVectorTy = ResultType->castAs<VectorTy>();
   QualType ResultElementTy = ResultVectorTy->getElementType();
   unsigned ResultElementCount = ResultVectorTy->getNumElements();
 
@@ -6143,8 +6139,14 @@
   }
 
   // Neither is void.
-  if (IsVectorConditional)
-    return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
+  if (IsVectorConditional) {
+    auto CondTy = Cond.get()->getType();
+    if (CondTy->isExtVectorType())
+      return CheckVectorConditionalTypes<ExtVectorType>(Cond, LHS, RHS,
+                                                        QuestionLoc);
+    assert(CondTy->isVectorType());
+    return CheckVectorConditionalTypes<VectorType>(Cond, LHS, RHS, QuestionLoc);
+  }
 
   // C++11 [expr.cond]p3
   //   Otherwise, if the second and third operand have different types, and
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11557,9 +11557,10 @@
   QualType CXXCheckConditionalOperands( // C++ 5.16
     ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
     ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
-  QualType CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
-                                          ExprResult &RHS,
-                                          SourceLocation QuestionLoc);
+  template <class VectorTy>
+  QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
+                                       ExprResult &RHS,
+                                       SourceLocation QuestionLoc);
   QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
                                     bool ConvertArgs = true);
   QualType FindCompositePointerType(SourceLocation Loc,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to