diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 3579e75d9451..9ac311ae58e8 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3181,53 +3181,42 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { QualType EltTy = VT->getElementType(); SmallVector Elements; - // If a vector is initialized with a single element, that value - // becomes every element of the vector, not just the first. - // This is the behavior described in the IBM AltiVec documentation. - if (NumInits == 1) { - - // Handle the case where the vector is initialized by another - // vector (OpenCL 6.1.6). - if (E->getInit(0)->getType()->isVectorType()) - return Visit(E->getInit(0)); - - APValue InitValue; - if (EltTy->isIntegerType()) { + // The number of initializers can be less than the number of + // vector elements. For OpenCL, this can be due to nested vector + // initialization. For GCC compatibility, missing trailing elements + // should be initialized with zeroes. + unsigned CountInits = 0, CountElts = 0; + while (CountElts < NumElements) { + // Handle nested vector initialization. + if (CountInits < NumInits + && E->getInit(CountInits)->getType()->isExtVectorType()) { + APValue v; + if (!EvaluateVector(E->getInit(CountInits), v, Info)) + return Error(E); + unsigned vlen = v.getVectorLength(); + for (unsigned j = 0; j < vlen; j++) + Elements.push_back(v.getVectorElt(j)); + CountElts += vlen; + } else if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); - if (!EvaluateInteger(E->getInit(0), sInt, Info)) - return false; - InitValue = APValue(sInt); + if (CountInits < NumInits) { + if (!EvaluateInteger(E->getInit(CountInits), sInt, Info)) + return Error(E); + } else // trailing integer zero. + sInt = Info.Ctx.MakeIntValue(0, EltTy); + Elements.push_back(APValue(sInt)); + CountElts++; } else { llvm::APFloat f(0.0); - if (!EvaluateFloat(E->getInit(0), f, Info)) - return false; - InitValue = APValue(f); - } - for (unsigned i = 0; i < NumElements; i++) { - Elements.push_back(InitValue); - } - } else { - for (unsigned i = 0; i < NumElements; i++) { - if (EltTy->isIntegerType()) { - llvm::APSInt sInt(32); - if (i < NumInits) { - if (!EvaluateInteger(E->getInit(i), sInt, Info)) - return false; - } else { - sInt = Info.Ctx.MakeIntValue(0, EltTy); - } - Elements.push_back(APValue(sInt)); - } else { - llvm::APFloat f(0.0); - if (i < NumInits) { - if (!EvaluateFloat(E->getInit(i), f, Info)) - return false; - } else { - f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); - } - Elements.push_back(APValue(f)); - } + if (CountInits < NumInits) { + if (!EvaluateFloat(E->getInit(CountInits), f, Info)) + return Error(E); + } else // trailing float zero. + f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); + Elements.push_back(APValue(f)); + CountElts++; } + CountInits++; } return Success(Elements, E); } diff --git a/clang/test/CodeGenOpenCL/vector_literals_nested.cl b/clang/test/CodeGenOpenCL/vector_literals_nested.cl new file mode 100644 index 000000000000..cb8ea78c7f49 --- /dev/null +++ b/clang/test/CodeGenOpenCL/vector_literals_nested.cl @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 %s -emit-llvm -O3 -o - | FileCheck %s + +typedef int int2 __attribute((ext_vector_type(2))); +typedef int int4 __attribute((ext_vector_type(4))); + +__constant const int4 itest1 = (int4)(1, 2, ((int2)(3, 4))); +// CHECK: constant <4 x i32> +__constant const int4 itest2 = (int4)(1, 2, ((int2)(3))); +// CHECK: constant <4 x i32> + +typedef float float2 __attribute((ext_vector_type(2))); +typedef float float4 __attribute((ext_vector_type(4))); + +float4 ftest1() { + return (float4)(1.1f, 1.2f, ((float2)(1.3f, 1.4f))); +// CHECK: ret <4 x float> +} + +float4 ftest2() { + return (float4)(1.1f, 1.2f, ((float2)(1.3f))); +// CHECK: ret <4 x float> +} + diff --git a/clang/test/SemaOpenCL/vector_literals_const.cl b/clang/test/SemaOpenCL/vector_literals_const.cl new file mode 100644 index 000000000000..e761816db4b7 --- /dev/null +++ b/clang/test/SemaOpenCL/vector_literals_const.cl @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only + +typedef int int2 __attribute((ext_vector_type(2))); +typedef int int3 __attribute((ext_vector_type(3))); +typedef int int4 __attribute((ext_vector_type(4))); + +__constant int4 i_1_1_1_1 = (int4)(1,2,3,4); +__constant int4 i_2_1_1 = (int4)((int2)(1,2),3,4); +__constant int4 i_1_2_1 = (int4)(1,(int2)(2,3),4); +__constant int4 i_1_1_2 = (int4)(1,2,(int2)(3,4)); +__constant int4 i_2_2 = (int4)((int2)(1,2),(int2)(3,4)); +__constant int4 i_3_1 = (int4)((int3)(1,2,3),4); +__constant int4 i_1_3 = (int4)(1,(int3)(2,3,4)); + +typedef float float2 __attribute((ext_vector_type(2))); +typedef float float3 __attribute((ext_vector_type(3))); +typedef float float4 __attribute((ext_vector_type(4))); + +__constant float4 f_1_1_1_1 = (float4)(1,2,3,4); +__constant float4 f_2_1_1 = (float4)((float2)(1,2),3,4); +__constant float4 f_1_2_1 = (float4)(1,(float2)(2,3),4); +__constant float4 f_1_1_2 = (float4)(1,2,(float2)(3,4)); +__constant float4 f_2_2 = (float4)((float2)(1,2),(float2)(3,4)); +__constant float4 f_3_1 = (float4)((float3)(1,2,3),4); +__constant float4 f_1_3 = (float4)(1,(float3)(2,3,4)); +