diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 11aca820fdc4..36ab0332cd9a 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -226,6 +226,10 @@ Expr::isLvalueResult Expr::isLvalue() const { break; case ParenExprClass: // C99 6.5.1p5 return cast(this)->getSubExpr()->isLvalue(); + case OCUVectorComponentClass: + if (cast(this)->containsDuplicateComponents()) + return LV_DuplicateVectorComponents; + return LV_Valid; default: break; } @@ -244,6 +248,7 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue() const { case LV_Valid: break; case LV_NotObjectType: return MLV_NotObjectType; case LV_IncompleteVoidType: return MLV_IncompleteVoidType; + case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; case LV_InvalidExpression: return MLV_InvalidExpression; } if (TR.isConstQualified()) @@ -581,3 +586,16 @@ OCUVectorComponent::ComponentType OCUVectorComponent::getComponentType() const { if (VT->isTextureAccessor(*compStr)) return Texture; assert(0 && "getComponentType(): Illegal accessor"); } + +bool OCUVectorComponent::containsDuplicateComponents() const { + const char *compStr = Accessor.getName(); + unsigned length = strlen(compStr); + + for (unsigned i = 0; i < length-1; i++) { + const char *s = compStr+i; + for (const char c = *s++; *s; s++) + if (c == *s) + return true; + } + return false; +} diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 8646c1a79272..557eb7220b8a 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -1136,6 +1136,10 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1 Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue, lhsType.getAsString(), lex->getSourceRange()); return QualType(); + case Expr::MLV_DuplicateVectorComponents: + Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue, + lex->getSourceRange()); + return QualType(); } AssignmentCheckResult result; diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index fc63a7823f73..01917dc7a34c 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -67,6 +67,7 @@ public: LV_Valid, LV_NotObjectType, LV_IncompleteVoidType, + LV_DuplicateVectorComponents, LV_InvalidExpression }; isLvalueResult isLvalue() const; @@ -80,6 +81,7 @@ public: MLV_Valid, MLV_NotObjectType, MLV_IncompleteVoidType, + MLV_DuplicateVectorComponents, MLV_InvalidExpression, MLV_IncompleteType, MLV_ConstQualified, @@ -464,17 +466,15 @@ public: /// OCUVectorComponent /// class OCUVectorComponent : public Expr { + Expr *Base; + IdentifierInfo &Accessor; + SourceLocation AccessorLoc; public: enum ComponentType { Point, Color, Texture }; -private: - Expr *Base; - IdentifierInfo &Accessor; - SourceLocation AccessorLoc; -public: OCUVectorComponent(QualType ty, Expr *base, IdentifierInfo &accessor, SourceLocation loc) : Expr(OCUVectorComponentClass, ty), Base(base), Accessor(accessor), AccessorLoc(loc) {} @@ -483,6 +483,8 @@ public: IdentifierInfo & getAccessor() const { return Accessor; } ComponentType getComponentType() const; + bool containsDuplicateComponents() const; + virtual SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), AccessorLoc); } diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 68e333a1e48b..f700fa24bf44 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -628,6 +628,8 @@ DIAG(err_typecheck_expression_not_modifiable_lvalue, ERROR, "expression is not assignable") DIAG(err_typecheck_incomplete_type_not_modifiable_lvalue, ERROR, "incomplete type '%0' is not assignable") +DIAG(err_typecheck_duplicate_vector_components_not_mlvalue, ERROR, + "vector is not assignable (contains duplicate components)") DIAG(err_typecheck_call_not_function, ERROR, "called object is not a function or function pointer") DIAG(err_typecheck_call_too_few_args, ERROR, diff --git a/clang/test/Parser/ocu_vector_components.c b/clang/test/Parser/ocu_vector_components.c index 8c7aa98a41ba..fc989329bafb 100644 --- a/clang/test/Parser/ocu_vector_components.c +++ b/clang/test/Parser/ocu_vector_components.c @@ -5,16 +5,23 @@ typedef __attribute__(( ocu_vector_type(3) )) float float3; typedef __attribute__(( ocu_vector_type(4) )) float float4; static void test() { - float2 vec2; + float2 vec2, vec2_2; float3 vec3; - float4 vec4; + float4 vec4, vec4_2; float f; - vec2.z; // // expected-error {{vector component access exceeds type 'float2'}} - vec2.rgba; // // expected-error {{vector component access exceeds type 'float2'}} - vec4.rgba; - vec4.rgbc; // // expected-error {{illegal vector component name 'c'}} + vec2.z; // 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.rgbc; // expected-error {{illegal vector component name 'c'}} vec3 = vec4.rgb; // legal, shorten f = vec2.x; // legal, shorten + + 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.xx = vec2_2.xy; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.yx = vec2_2.xy; vec4 = (float4){ 1,2,3,4 }; }