Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -5718,9 +5718,15 @@ // ASTContext::getTypeSize will return the size rounded up to a // power of 2, so instead of using that, we need to use the raw // element size multiplied by the element count. - uint64_t srcEltSize = Context.getTypeSize(srcEltTy); - uint64_t destEltSize = Context.getTypeSize(destEltTy); - + // + // We need to be careful about booleans though; they're lowered to i1s, but + // getTypeSize views them as i8s. (They're allowed in extended vectors + // when compiling code as e.g. C++) + uint64_t srcEltSize = + srcEltTy->isBooleanType() ? 1 : Context.getTypeSize(srcEltTy); + uint64_t destEltSize = + destEltTy->isBooleanType() ? 1 : Context.getTypeSize(destEltTy); + return (srcLen * srcEltSize == destLen * destEltSize); } Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -2184,10 +2184,15 @@ /// Run the required checks for the extended vector type. QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc) { - // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // Unlike gcc's vector_size attribute, we do not allow vectors to be defined // in conjunction with complex types (pointers, arrays, functions, etc.). - if (!T->isDependentType() && - !T->isIntegerType() && !T->isRealFloatingType()) { + // + // Additionally, OpenCL prohibits vectors of booleans (they're considered a + // reserved data type under OpenCL v2.0 s6.1.4), but we do allow their use + // outside of OpenCL. + if ((!T->isDependentType() && !T->isIntegerType() && + !T->isRealFloatingType()) || + (getLangOpts().OpenCL && T->isBooleanType())) { Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T; return QualType(); } @@ -2201,7 +2206,7 @@ return QualType(); } - // unlike gcc's vector_size attribute, the size is specified as the + // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. unsigned vectorSize = static_cast(vecSize.getZExtValue()); Index: test/CodeGen/bool-vector-conversion.c =================================================================== --- /dev/null +++ test/CodeGen/bool-vector-conversion.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -x c -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -x c++ -emit-llvm -o - | FileCheck %s +// +// In many parts of clang, we treat a bool as an i8, but we lower it to an i1. +// This is usually fine, but it broke things with vectors (e.g. we deemed a cast +// from a [4 x i1] to a [1 x i32] to be legal, and proceeded to crash shortly +// afterward). + +#ifdef __cplusplus +typedef bool BOOL; +#else +typedef _Bool BOOL; +#endif + +// Only extended vectors allow bool elements. +// __asm__ label keeps C++ mangling from happening +void test() __asm__("test"); + +// CHECK-LABEL: @test +void test() { + typedef __attribute__((__ext_vector_type__(8))) BOOL CLVectorBool8; + typedef __attribute__((__ext_vector_type__(1))) unsigned char CLVectorInt1; + + // CHECK: store <8 x i1> zeroinitializer + CLVectorBool8 bools = (CLVectorBool8)0; + // CHECK: store <1 x i8> + CLVectorInt1 ints = (CLVectorInt1)bools; + // CHECK: store <8 x i1> + bools = (CLVectorBool8)ints; + + // Run through the code in CGExprConstant. + // CHECK: store <8 x i1> zeroinitializer + bools = (CLVectorBool8)(CLVectorInt1)(CLVectorBool8)0; +} + Index: test/SemaOpenCL/bool-vectors.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/bool-vectors.cl @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only + +typedef __attribute__((ext_vector_type(16))) _Bool bool8; // expected-error{{invalid vector element type 'bool'}}