Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2794,7 +2794,8 @@ /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This /// class enables syntactic extensions, like Vector Components for accessing -/// points, colors, and textures (modeled after OpenGL Shading Language). +/// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL +/// Shading Language). class ExtVectorType : public VectorType { ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} @@ -2803,10 +2804,10 @@ static int getPointAccessorIdx(char c) { switch (c) { default: return -1; - case 'x': return 0; - case 'y': return 1; - case 'z': return 2; - case 'w': return 3; + case 'x': case 'r': return 0; + case 'y': case 'g': return 1; + case 'z': case 'b': return 2; + case 'w': case 'a': return 3; } } static int getNumericAccessorIdx(char c) { @@ -2837,13 +2838,15 @@ } } - static int getAccessorIdx(char c) { - if (int idx = getPointAccessorIdx(c)+1) return idx-1; - return getNumericAccessorIdx(c); + static int getAccessorIdx(char c, bool isNumericAccessor) { + if (isNumericAccessor) + return getNumericAccessorIdx(c); + else + return getPointAccessorIdx(c); } - bool isAccessorWithinNumElements(char c) const { - if (int idx = getAccessorIdx(c)+1) + bool isAccessorWithinNumElements(char c, bool isNumericAccessor) const { + if (int idx = getAccessorIdx(c, isNumericAccessor)+1) return unsigned(idx-1) < getNumElements(); return false; } Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -7894,6 +7894,10 @@ "invalid number of arguments to function: %0">; def err_opencl_builtin_to_addr_invalid_arg : Error< "invalid argument %0 to function: %1, expecting a generic pointer argument">; + +// OpenCL v2.2 s2.1.2.3 - Vector Component Access +def warn_opencl_ext_vector_type_rgba_selector: ExtWarn< + "vector component name '%0' is an OpenCL 2.2 extension">; } // end of sema category let CategoryName = "OpenMP Issue" in { Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3383,8 +3383,11 @@ void ExtVectorElementExpr::getEncodedElementAccess( SmallVectorImpl &Elts) const { StringRef Comp = Accessor->getName(); - if (Comp[0] == 's' || Comp[0] == 'S') + bool isNumericAccessor = false; + if (Comp[0] == 's' || Comp[0] == 'S') { Comp = Comp.substr(1); + isNumericAccessor = true; + } bool isHi = Comp == "hi"; bool isLo = Comp == "lo"; @@ -3403,7 +3406,7 @@ else if (isOdd) Index = 2 * i + 1; else - Index = ExtVectorType::getAccessorIdx(Comp[i]); + Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor); Elts.push_back(Index); } Index: lib/Sema/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -268,6 +268,20 @@ llvm_unreachable("unexpected instance member access kind"); } +/// Determine whether input char is from rgba component set. +static bool +IsRGBA(char c) { + switch (c) { + case 'r': + case 'g': + case 'b': + case 'a': + return true; + default: + return false; + } +} + /// Check an ext-vector component access expression. /// /// VK should be set in advance to the value kind of the base @@ -307,11 +321,25 @@ HalvingSwizzle = true; } else if (!HexSwizzle && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) { + bool HasRGBA = IsRGBA(*compStr); do { + // Ensure that xyzw and rgba components don't intermingle. + if (HasRGBA != IsRGBA(*compStr)) + break; if (HasIndex[Idx]) HasRepeated = true; HasIndex[Idx] = true; compStr++; } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1); + + // Emit a warning if an rgba selector is used in OpenCL 2.0 and below. + if (HasRGBA || (*compStr && IsRGBA(*compStr))) { + if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) { + const char *diagBegin = HasRGBA ? CompName->getNameStart() : compStr; + S.Diag(OpLoc, diag::warn_opencl_ext_vector_type_rgba_selector) + << StringRef(diagBegin, 1) + << S.getLangOpts().OpenCLVersion << SourceRange(CompLoc); + } + } } else { if (HexSwizzle) compStr++; while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) { @@ -338,7 +366,7 @@ compStr++; while (*compStr) { - if (!vecType->isAccessorWithinNumElements(*compStr++)) { + if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) { S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) << baseType << SourceRange(CompLoc); return QualType(); Index: test/CodeGen/ext-vector.c =================================================================== --- test/CodeGen/ext-vector.c +++ test/CodeGen/ext-vector.c @@ -301,3 +301,40 @@ char valC; char16 destVal = valC ? valA : valB; } + +typedef __attribute__(( ext_vector_type(16) )) float float16; + +float16 vec16, vec16_2; + +// CHECK: @test_rgba +void test_rgba() { + // CHECK: fadd <4 x float> + vec4_2 = vec4.abgr + vec4; + + // CHECK: shufflevector {{.*}} + vec2 = vec4.rg; + // CHECK: shufflevector {{.*}} + vec2_2 = vec4.ba; + // CHECK: extractelement {{.*}} 2 + f = vec4.b; + // CHECK: shufflevector {{.*}} + vec4_2 = vec4_2.bbbb; + + // CHECK: insertelement {{.*}} 0 + vec2.r = f; + // CHECK: shufflevector {{.*}} + vec2.gr = vec2; + + // CHECK: extractelement {{.*}} 0 + f = vec4_2.rg.r; + // CHECK: shufflevector {{.*}} + // CHECK: shufflevector {{.*}} + // CHECK: shufflevector {{.*}} + vec4.rgb = vec4.bgr; + + // CHECK: extractelement {{.*}} 11 + // CHECK: insertelement {{.*}} 2 + vec4.b = vec16.sb; + // CHECK: shufflevector {{.*}} + vec4_2 = vec16.sabcd; +} Index: test/Misc/warning-flags.c =================================================================== --- test/Misc/warning-flags.c +++ test/Misc/warning-flags.c @@ -18,7 +18,7 @@ The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (84): +CHECK: Warnings without flags (85): CHECK-NEXT: ext_excess_initializers CHECK-NEXT: ext_excess_initializers_in_char_array_initializer CHECK-NEXT: ext_expected_semi_decl_list @@ -83,6 +83,7 @@ CHECK-NEXT: warn_objc_property_copy_missing_on_block CHECK-NEXT: warn_objc_protocol_qualifier_missing_id CHECK-NEXT: warn_on_superclass_use +CHECK-NEXT: warn_opencl_ext_vector_type_rgba_selector CHECK-NEXT: warn_partial_specs_not_deducible CHECK-NEXT: warn_pp_convert_to_positive CHECK-NEXT: warn_pp_expr_overflow Index: test/Sema/ext_vector_components.c =================================================================== --- test/Sema/ext_vector_components.c +++ test/Sema/ext_vector_components.c @@ -39,6 +39,33 @@ vec4.x = vec16.sF; vec4p->yz = vec4p->xy; + + vec2.a; // expected-error {{vector component access exceeds type 'float2'}} + vec2.rgba; // expected-error {{vector component access exceeds type 'float2'}} + vec4.rgba; // expected-warning {{expression result unused}} + vec4.rgbz; // expected-error {{illegal vector component name 'z'}} + vec4.rgbc; // expected-error {{illegal vector component name 'c'}} + vec4.xyzr; // expected-error {{illegal vector component name 'r'}} + vec4.s01b; // expected-error {{vector component access exceeds type 'float4'}} + + vec3 = vec4.rgb; // legal, shorten + f = vec2.r; // legal, shorten + f = vec4.rg.r; // legal, shorten + vec4_2.rgba = vec4.xyzw; // legal, no intermingling + + vec4_2.rgbr = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.rgbb = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.rgga = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.x = f; + vec2.rr = vec2_2.rg; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.gr = vec2_2.rg; + vec2.gr.g = vec2_2.r; + vec4 = (float4){ 1,2,3,4 }; + vec4.rg.b; // expected-error {{vector component access exceeds type 'float2'}} + vec4.r = vec16.sf; + vec4.g = vec16.sF; + + vec4p->gb = vec4p->rg; } float2 lo(float3 x) { return x.lo; } Index: test/SemaOpenCL/ext_vectors.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/ext_vectors.cl @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.1 +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 + +typedef float float4 __attribute__((ext_vector_type(4))); + +void test_ext_vector_accessors(float4 V) { + V = V.wzyx; + V = V.abgr; // expected-warning {{vector component name 'a' is an OpenCL 2.2 extension}} + V = V.xyzr; // expected-warning {{vector component name 'r' is an OpenCL 2.2 extension}} \ + // expected-error {{illegal vector component name 'r'}} +}