Implement syntax/semantic analysis for OCU Vector Components.

Next step, AST support...

llvm-svn: 40568
This commit is contained in:
Steve Naroff 2007-07-27 22:15:19 +00:00
parent 004937bbd9
commit f8fd09e22b
6 changed files with 114 additions and 6 deletions

View File

@ -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,

View File

@ -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.

View File

@ -23,6 +23,7 @@ using namespace clang;
Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) {
Expr *E = static_cast<Expr*>(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.

View File

@ -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;
}

View File

@ -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,

View File

@ -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 };
}