Implement pretty diagnostics when doing on-the-fly vector sizing (for vector component access).

For example, before this commit, the following diagnostics would be emitted...

ocu.c:49:12: error: incompatible types assigning 'float  __attribute__((ocu_vector_type(3)))' to 'float4'
    vec4_2 = vec4.rgb; // shorten
    ~~~~~~ ^ ~~~~~~~~
ocu.c:51:7: error: incompatible types assigning 'float  __attribute__((ocu_vector_type(2)))' to 'float'
    f = vec2.xx; // shorten
    ~ ^ ~~~~~~~

Now, the diagnostics look as you would expect...

ocu.c:49:12: error: incompatible types assigning 'float3' to 'float4'
    vec4_2 = vec4.rgb; // shorten
    ~~~~~~ ^ ~~~~~~~~
ocu.c:51:7: error: incompatible types assigning 'float2' to 'float'
    f = vec2.xx; // shorten
    ~ ^ ~~~~~~~

llvm-svn: 40579
This commit is contained in:
Steve Naroff 2007-07-29 16:33:31 +00:00
parent 5fecb80efa
commit ddf5a1d7a6
4 changed files with 31 additions and 19 deletions

View File

@ -39,7 +39,8 @@ namespace clang {
class LabelStmt;
class SwitchStmt;
class OCUVectorType;
class TypedefDecl;
/// Sema - This implements semantic analysis and AST building for C.
class Sema : public Action {
Preprocessor &PP;
@ -62,6 +63,11 @@ class Sema : public Action {
llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
/// OCUVectorDecls - This is a list all the OCU vector types. This allows
/// us to associate a raw vector type with one of the OCU type names.
/// This is only necessary for issuing pretty diagnostics.
llvm::SmallVector<TypedefDecl*, 24> OCUVectorDecls;
public:
Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
@ -158,7 +164,7 @@ private:
// for the variable, measured in bytes. If curType and rawAttr are well
// formed, this routine will return a new vector type.
QualType HandleVectorTypeAttribute(QualType curType, AttributeList *rawAttr);
QualType HandleOCUVectorTypeAttribute(QualType curType, AttributeList *rawAttr);
void HandleOCUVectorTypeAttribute(TypedefDecl *d, AttributeList *rawAttr);
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.

View File

@ -965,15 +965,11 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
}
}
if (strcmp(rawAttr->getAttributeName()->getName(), "ocu_vector_type") == 0) {
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
QualType newType = HandleOCUVectorTypeAttribute(tDecl->getUnderlyingType(),
rawAttr);
if (!newType.isNull()) // install the new vector type into the decl
tDecl->setUnderlyingType(newType);
} else {
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New))
HandleOCUVectorTypeAttribute(tDecl, rawAttr);
else
Diag(rawAttr->getAttributeLoc(),
diag::err_typecheck_ocu_vector_not_typedef);
}
}
// FIXME: add other attributes...
}
@ -990,20 +986,21 @@ void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
}
}
QualType Sema::HandleOCUVectorTypeAttribute(QualType curType,
AttributeList *rawAttr) {
void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl,
AttributeList *rawAttr) {
QualType curType = tDecl->getUnderlyingType();
// check the attribute arugments.
if (rawAttr->getNumArgs() != 1) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments,
std::string("1"));
return QualType();
return;
}
Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0));
llvm::APSInt vecSize(32);
if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_vector_size_not_int,
sizeExpr->getSourceRange());
return QualType();
return;
}
// unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
@ -1011,7 +1008,7 @@ QualType Sema::HandleOCUVectorTypeAttribute(QualType curType,
if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_vector_type,
curType.getCanonicalType().getAsString());
return QualType();
return;
}
// unlike gcc's vector_size attribute, the size is specified as the
// number of elements, not the number of bytes.
@ -1020,10 +1017,12 @@ QualType Sema::HandleOCUVectorTypeAttribute(QualType curType,
if (vectorSize == 0) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_zero_size,
sizeExpr->getSourceRange());
return QualType();
return;
}
// Instantiate the vector type, the number of elements is > 0.
return Context.getOCUVectorType(curType, vectorSize);
// Instantiate/Install the vector type, the number of elements is > 0.
tDecl->setUnderlyingType(Context.getOCUVectorType(curType, vectorSize));
// Remember this typedef decl, we will need it later for diagnostics.
OCUVectorDecls.push_back(tDecl);
}
QualType Sema::HandleVectorTypeAttribute(QualType curType,

View File

@ -387,7 +387,15 @@ CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
unsigned CompSize = strlen(CompName.getName());
if (CompSize == 1)
return vecType->getElementType();
return Context.getOCUVectorType(vecType->getElementType(), CompSize);
QualType VT = Context.getOCUVectorType(vecType->getElementType(), CompSize);
// Now look up the TypeDefDecl from the vector type. Without this,
// diagostics look bad. We want OCU vector types to appear built-in.
for (unsigned i = 0, e = OCUVectorDecls.size(); i != e; ++i) {
if (OCUVectorDecls[i]->getUnderlyingType() == VT)
return Context.getTypedefType(OCUVectorDecls[i]);
}
return VT; // should never get here (a typedef type should always be found).
}
Action::ExprResult Sema::

View File

@ -313,7 +313,6 @@ protected:
TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
: Decl(DK, L, Id, PrevDecl), TypeForDecl(0) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= Typedef && D->getKind() <= Enum;