From: John Thompson Date: Fri, 4 Dec 2009 21:51:28 +0000 (+0000) Subject: Fix for PR5650 - Revised vector_size attribute handling to be done earlier before... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6e132aab867c189b1c3ee7463ef9d2b1f03a294d;p=clang Fix for PR5650 - Revised vector_size attribute handling to be done earlier before declaration is finalized. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90600 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 8393253011..3d7a5376d7 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,12 +242,13 @@ void TypePrinter::PrintDependentSizedExtVector( void TypePrinter::PrintVector(const VectorType *T, std::string &S) { // FIXME: We prefer to print the size directly here, but have no way // to get the size of the type. - S += " __attribute__((__vector_size__("; - S += llvm::utostr_32(T->getNumElements()); // convert back to bytes. + Print(T->getElementType(), S); + std::string V = "__attribute__((__vector_size__("; + V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. std::string ET; Print(T->getElementType(), ET); - S += " * sizeof(" + ET + "))))"; - Print(T->getElementType(), S); + V += " * sizeof(" + ET + ")))) "; + S = V + S; } void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b2124fe014..2e641d9041 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -202,91 +202,6 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, } } - -/// HandleVectorSizeAttribute - this attribute is only applicable to integral -/// and float scalars, although arrays, pointers, and function return values are -/// allowed in conjunction with this construct. Aggregates with this attribute -/// are invalid, even if they are of the same size as a corresponding scalar. -/// The raw attribute should contain precisely 1 argument, the vector size for -/// the variable, measured in bytes. If curType and rawAttr are well formed, -/// this routine will return a new vector type. -static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) { - QualType CurType; - if (ValueDecl *VD = dyn_cast(D)) - CurType = VD->getType(); - else if (TypedefDecl *TD = dyn_cast(D)) - CurType = TD->getUnderlyingType(); - else { - S.Diag(D->getLocation(), diag::err_attr_wrong_decl) - << "vector_size" << SourceRange(Attr.getLoc(), Attr.getLoc()); - return; - } - - // Check the attribute arugments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - Expr *sizeExpr = static_cast(Attr.getArg(0)); - llvm::APSInt vecSize(32); - if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "vector_size" << sizeExpr->getSourceRange(); - return; - } - // navigate to the base type - we need to provide for vector pointers, vector - // arrays, and functions returning vectors. - if (CurType->isPointerType() || CurType->isArrayType() || - CurType->isFunctionType()) { - S.Diag(Attr.getLoc(), diag::err_unsupported_vector_size) << CurType; - return; - /* FIXME: rebuild the type from the inside out, vectorizing the inner type. - do { - if (PointerType *PT = dyn_cast(canonType)) - canonType = PT->getPointeeType().getTypePtr(); - else if (ArrayType *AT = dyn_cast(canonType)) - canonType = AT->getElementType().getTypePtr(); - else if (FunctionType *FT = dyn_cast(canonType)) - canonType = FT->getResultType().getTypePtr(); - } while (canonType->isPointerType() || canonType->isArrayType() || - canonType->isFunctionType()); - */ - } - // the base type must be integer or float, and can't already be a vector. - if (CurType->isVectorType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; - return; - } - unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - // vecSize is specified in bytes - convert to bits. - unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); - - // the vector size needs to be an integral multiple of the type size. - if (vectorSize % typeSize) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) - << sizeExpr->getSourceRange(); - return; - } - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - return; - } - - // Success! Instantiate the vector type, the number of elements is > 0, and - // not required to be a power of 2, unlike GCC. - CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); - - if (ValueDecl *VD = dyn_cast(D)) - VD->setType(CurType); - else { - // FIXME: preserve existing source info. - DeclaratorInfo *DInfo = S.Context.getTrivialDeclaratorInfo(CurType); - cast(D)->setTypeDeclaratorInfo(DInfo); - } -} - static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 0) { @@ -1964,6 +1879,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; case AttributeList::AT_address_space: case AttributeList::AT_objc_gc: + case AttributeList::AT_vector_size: // Ignore these, these are type attributes, handled by // ProcessTypeAttributes. break; @@ -2013,7 +1929,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; - case AttributeList::AT_vector_size: HandleVectorSizeAttr (D, Attr, S); break; case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break; case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); break; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 526ab91e9f..d1ee596b75 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1643,6 +1643,53 @@ static void HandleNoReturnTypeAttribute(QualType &Type, Type = S.Context.getNoReturnType(Type); } +/// HandleVectorSizeAttribute - this attribute is only applicable to integral +/// and float scalars, although arrays, pointers, and function return values are +/// allowed in conjunction with this construct. Aggregates with this attribute +/// are invalid, even if they are of the same size as a corresponding scalar. +/// The raw attribute should contain precisely 1 argument, the vector size for +/// the variable, measured in bytes. If curType and rawAttr are well formed, +/// this routine will return a new vector type. +static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) { + // Check the attribute arugments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + Expr *sizeExpr = static_cast(Attr.getArg(0)); + llvm::APSInt vecSize(32); + if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "vector_size" << sizeExpr->getSourceRange(); + return; + } + // the base type must be integer or float, and can't already be a vector. + if (CurType->isVectorType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; + return; + } + unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); + // vecSize is specified in bytes - convert to bits. + unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); + + // the vector size needs to be an integral multiple of the type size. + if (vectorSize % typeSize) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + return; + } + if (vectorSize == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) + << sizeExpr->getSourceRange(); + return; + } + + // Success! Instantiate the vector type, the number of elements is > 0, and + // not required to be a power of 2, unlike GCC. + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); +} + void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the @@ -1662,6 +1709,9 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { case AttributeList::AT_noreturn: HandleNoReturnTypeAttribute(Result, *AL, *this); break; + case AttributeList::AT_vector_size: + HandleVectorSizeAttr(Result, *AL, *this); + break; } } } diff --git a/test/Sema/vector-init.c b/test/Sema/vector-init.c index 9dac6c7114..1eec6c57a6 100644 --- a/test/Sema/vector-init.c +++ b/test/Sema/vector-init.c @@ -16,10 +16,15 @@ float4 array2[2] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, float4 array3[2] = { {1.0, 2.0, 3.0}, 5.0, 6.0, 7.0, 8.0, 9.0 }; // expected-warning {{excess elements in array initializer}} +// PR5650 +__attribute__((vector_size(16))) float f1(void) { + __attribute__((vector_size(16))) float vec = {0.0f, 0.0f, 0.0f}; + return(vec); +} -// rdar://6881069 -__attribute__((vector_size(16))) // expected-error {{unsupported type 'float (void)' for vector_size attribute, please use on typedef}} -float f1(void) { +__attribute__((vector_size(16))) float f2( + __attribute__((vector_size(16))) float a1) { + return(a1); }