Update support for vector component access on ExtVectors.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62440 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7a6c364..7d08132 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1325,64 +1325,61 @@
IdentifierInfo &CompName, SourceLocation CompLoc) {
const ExtVectorType *vecType = baseType->getAsExtVectorType();
- // This flag determines whether or not the component is to be treated as a
- // special name, or a regular GLSL-style component access.
- bool SpecialComponent = false;
-
// The vector accessor can't exceed the number of elements.
const char *compStr = CompName.getName();
- if (strlen(compStr) > vecType->getNumElements()) {
- Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
- << baseType << SourceRange(CompLoc);
- return QualType();
- }
+
+ // This flag determines whether or not the component is one of the four
+ // special names that indicate a subset of exactly half the elements are
+ // to be selected.
+ bool HalvingSwizzle = false;
+
+ // This flag determines whether or not CompName has an 's' char prefix,
+ // indicating that it is a string of hex values to be used as vector indices.
+ bool HexSwizzle = *compStr == 's';
// Check that we've found one of the special components, or that the component
// names must come from the same set.
if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
- !strcmp(compStr, "e") || !strcmp(compStr, "o")) {
- SpecialComponent = true;
+ !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
+ HalvingSwizzle = true;
} else if (vecType->getPointAccessorIdx(*compStr) != -1) {
do
compStr++;
while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
- } else if (vecType->getColorAccessorIdx(*compStr) != -1) {
+ } else if (HexSwizzle || vecType->getNumericAccessorIdx(*compStr) != -1) {
do
compStr++;
- while (*compStr && vecType->getColorAccessorIdx(*compStr) != -1);
- } else if (vecType->getTextureAccessorIdx(*compStr) != -1) {
- do
- compStr++;
- while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1);
+ while (*compStr && vecType->getNumericAccessorIdx(*compStr) != -1);
}
-
- if (!SpecialComponent && *compStr) {
+
+ if (!HalvingSwizzle && *compStr) {
// We didn't get to the end of the string. This means the component names
// didn't come from the same set *or* we encountered an illegal name.
Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
<< std::string(compStr,compStr+1) << SourceRange(CompLoc);
return QualType();
}
- // Each component accessor can't exceed the vector type.
- compStr = CompName.getName();
- while (*compStr) {
- if (vecType->isAccessorWithinNumElements(*compStr))
+
+ // Ensure no component accessor exceeds the width of the vector type it
+ // operates on.
+ if (!HalvingSwizzle) {
+ compStr = CompName.getName();
+
+ if (HexSwizzle)
compStr++;
- else
- break;
- }
- if (!SpecialComponent && *compStr) {
- // We didn't get to the end of the string. This means a component accessor
- // exceeds the number of elements in the vector.
- Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
- << baseType << SourceRange(CompLoc);
- return QualType();
+
+ while (*compStr) {
+ if (!vecType->isAccessorWithinNumElements(*compStr++)) {
+ Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
+ << baseType << SourceRange(CompLoc);
+ return QualType();
+ }
+ }
}
- // If we have a special component name, verify that the current vector length
- // is an even number, since all special component names return exactly half
- // the elements.
- if (SpecialComponent && (vecType->getNumElements() & 1U)) {
+ // If this is a halving swizzle, verify that the base type has an even
+ // number of elements.
+ if (HalvingSwizzle && (vecType->getNumElements() & 1U)) {
Diag(OpLoc, diag::err_ext_vector_component_requires_even)
<< baseType << SourceRange(CompLoc);
return QualType();
@@ -1391,9 +1388,13 @@
// The component accessor looks fine - now we need to compute the actual type.
// The vector type is implied by the component accessor. For example,
// vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
+ // vec4.s0 is a float, vec4.s23 is a vec3, etc.
// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
- unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2
- : CompName.getLength();
+ unsigned CompSize = HalvingSwizzle ? vecType->getNumElements() / 2
+ : CompName.getLength();
+ if (HexSwizzle)
+ CompSize--;
+
if (CompSize == 1)
return vecType->getElementType();