From: Steve Naroff Date: Fri, 27 Jul 2007 22:15:19 +0000 (+0000) Subject: Implement syntax/semantic analysis for OCU Vector Components. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1b31fedbc006e6e4071bbb4f74c6116b56cfa9f;p=clang Implement syntax/semantic analysis for OCU Vector Components. Next step, AST support... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40568 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Sema/Sema.h b/Sema/Sema.h index e1857b7583..589161bfab 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -38,6 +38,7 @@ namespace clang { class ArrayType; class LabelStmt; class SwitchStmt; + class OCUVectorType; /// Sema - This implements semantic analysis and AST building for C. class Sema : public Action { @@ -369,7 +370,11 @@ private: QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc); QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc, bool isSizeof); - + + /// type checking primary expressions. + QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc, + IdentifierInfo &Comp, SourceLocation CmpLoc); + /// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have /// a constant expression of type int with a value greater than zero. If the /// array has an incomplete type or a valid constant size, return false, diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 00838f79c1..91d6d8de9b 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -339,6 +339,57 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc); } +QualType Sema:: +CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc, + IdentifierInfo &CompName, SourceLocation CompLoc) { + const OCUVectorType *vecType = baseType->isOCUVectorType(); + + // The vector accessor can't exceed the number of elements. + const char *compStr = CompName.getName(); + if (strlen(compStr) > vecType->getNumElements()) { + Diag(OpLoc, diag::err_ocuvector_component_exceeds_length, + baseType.getAsString(), SourceRange(CompLoc)); + return QualType(); + } + // The component names must come from the same set. + if (vecType->isPointAccessor(*compStr)) + do { compStr++; } while (*compStr && vecType->isPointAccessor(*compStr)); + else if (vecType->isColorAccessor(*compStr)) + do { compStr++; } while (*compStr && vecType->isColorAccessor(*compStr)); + else if (vecType->isTextureAccessor(*compStr)) + do { compStr++; } while (*compStr && vecType->isTextureAccessor(*compStr)); + + if (*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_ocuvector_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)) + compStr++; + else + break; + } + if (*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_ocuvector_component_exceeds_length, + baseType.getAsString(), SourceRange(CompLoc)); + return QualType(); + } + // 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. + unsigned CompSize = strlen(CompName.getName()); + if (CompSize == 1) + return vecType->getElementType(); + return Context.getOCUVectorType(vecType->getElementType(), CompSize); +} + Action::ExprResult Sema:: ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, @@ -356,22 +407,27 @@ ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, return Diag(OpLoc, diag::err_typecheck_member_reference_arrow, SourceRange(MemberLoc)); } - // Get the member decl from the struct/union definition. - FieldDecl *MemberDecl; + // The base type is either a record or an OCUVectorType. if (const RecordType *RTy = BaseType->isRecordType()) { RecordDecl *RDecl = RTy->getDecl(); if (RTy->isIncompleteType()) return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(), BaseExpr->getSourceRange()); // The record definition is complete, now make sure the member is valid. - if (!(MemberDecl = RDecl->getMember(&Member))) + FieldDecl *MemberDecl = RDecl->getMember(&Member); + if (!MemberDecl) return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(), SourceRange(MemberLoc)); + return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl, MemberLoc); + } else if (BaseType->isOCUVectorType() && OpKind == tok::period) { + QualType ret = CheckOCUVectorComponent(BaseType, OpLoc, Member, MemberLoc); + if (ret.isNull()) + return true; + // FIXME: instantiate a OCUVectorComponentExpr node... + return true; } else return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion, SourceRange(MemberLoc)); - - return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl, MemberLoc); } /// ParseCallExpr - Handle a call to Fn with the specified array of arguments. diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index f9e2c0a21a..39e3b89919 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -23,6 +23,7 @@ using namespace clang; Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) { Expr *E = static_cast(expr); + assert(E && "ParseExprStmt(): missing expression"); // Exprs are statements, so there is no need to do a conversion here. However, // diagnose some potentially bad code. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 17d2d0a3c0..3988b99966 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -504,6 +504,28 @@ class OCUVectorType : public VectorType { VectorType(OCUVector, vecType, nElements, canonType) {} friend class ASTContext; // ASTContext creates these. public: + bool isPointAccessor(const char c) const { + return c == 'x' || c == 'y' || c == 'z' || c == 'w'; + } + bool isColorAccessor(const char c) const { + return c == 'r' || c == 'g' || c == 'b' || c == 'a'; + } + bool isTextureAccessor(const char c) const { + return c == 's' || c == 't' || c == 'p' || c == 'q'; + }; + bool isAccessorWithinNumElements(const char c) const { + switch (NumElements) { + default: assert(0 && "Illegal number of elements"); + case 2: return c == 'x' || c == 'y' || + c == 'r' || c == 'g' || + c == 's' || c == 't'; + case 3: return c == 'x' || c == 'y' || c == 'z' || + c == 'r' || c == 'g' || c == 'b' || + c == 's' || c == 't' || c == 'p'; + case 4: return isPointAccessor(c) || isColorAccessor(c) || + isTextureAccessor(c); + } + } static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == OCUVector; } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 64de3aa16e..68e333a1e4 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -445,6 +445,10 @@ DIAG(err_typecheck_vector_not_convertable, ERROR, "can't convert between vector values of different size ('%0' and '%1')") DIAG(err_typecheck_ocu_vector_not_typedef, ERROR, "ocu_vector_type only applies to types, not variables") +DIAG(err_ocuvector_component_exceeds_length, ERROR, + "vector component access exceeds type '%0'") +DIAG(err_ocuvector_component_name_illegal, ERROR, + "illegal vector component name '%0'") // Function Parameter Semantic Analysis. DIAG(err_param_with_void_type, ERROR, diff --git a/test/Parser/ocu_vector_components.c b/test/Parser/ocu_vector_components.c new file mode 100644 index 0000000000..8c7aa98a41 --- /dev/null +++ b/test/Parser/ocu_vector_components.c @@ -0,0 +1,20 @@ +// RUN: clang -parse-ast-check %s + +typedef __attribute__(( ocu_vector_type(2) )) float float2; +typedef __attribute__(( ocu_vector_type(3) )) float float3; +typedef __attribute__(( ocu_vector_type(4) )) float float4; + +static void test() { + float2 vec2; + float3 vec3; + float4 vec4; + 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'}} + vec3 = vec4.rgb; // legal, shorten + f = vec2.x; // legal, shorten + vec4 = (float4){ 1,2,3,4 }; +}