diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-17 21:51:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-17 21:51:59 +0000 |
commit | 9cdda0cf8528e3d595be9bfa002f0450074beb4d (patch) | |
tree | 5ffc959c4c5f38e164c9be332cd27388ee0a86b6 | |
parent | 69e07a75ef2815961929f34675b7c806a9cc37da (diff) |
Support dependent extended vector types and template instantiation
thereof. Patch by Anders Johnsen!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73641 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 9 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 37 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 12 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 73 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 42 | ||||
-rw-r--r-- | test/SemaTemplate/ext-vector-type.cpp | 47 |
16 files changed, 258 insertions, 60 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2ab1adac7e..3147aa746a 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -71,6 +71,7 @@ class ASTContext { llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; std::vector<VariableArrayType*> VariableArrayTypes; std::vector<DependentSizedArrayType*> DependentSizedArrayTypes; + std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes; llvm::FoldingSet<VectorType> VectorTypes; llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; @@ -277,6 +278,14 @@ public: /// type. QualType getExtVectorType(QualType VectorType, unsigned NumElts); + /// getDependentSizedExtVectorType - Returns a non-unique reference to + /// the type for a dependently-sized vector of the specified element + /// type. FIXME: We will need these to be uniqued, or at least + /// comparable, at some point. + QualType getDependentSizedExtVectorType(QualType VectorType, + Expr *SizeExpr, + SourceLocation AttrLoc); + /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// QualType getFunctionNoProtoType(QualType ResultTy); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 5cbe26d523..014907365e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -992,6 +992,41 @@ public: } }; +/// DependentSizedExtVectorType - This type represent an ext vectory type +/// where either the type or size is dependent. For example: +/// @code +/// template<typename T, int Size> +/// class vector { +/// typedef T __attribute__((ext_vector_type(Size))) type; +/// } +/// @endcode +class DependentSizedExtVectorType : public Type { + Expr *SizeExpr; + /// ElementType - The element type of the array. + QualType ElementType; + SourceLocation loc; + + DependentSizedExtVectorType(QualType ElementType, QualType can, + Expr *SizeExpr, SourceLocation loc) + : Type (DependentSizedExtVector, can, true), + SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {} + friend class ASTContext; + virtual void Destroy(ASTContext& C); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return loc; } + + virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentSizedExtVector; + } + static bool classof(const DependentSizedExtVectorType *) { return true; } +}; + + /// VectorType - GCC generic vector type. This type is created using /// __attribute__((vector_size(n)), where "n" specifies the vector size in /// bytes. Since the constructor takes the number of vector elements, the @@ -1783,7 +1818,7 @@ public: static bool classof(const ObjCQualifiedIdType *) { return true; } }; - + // Inline function definitions. /// getUnqualifiedType - Return the type without any qualifiers. diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 76cbed311d..627056eb50 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -60,6 +60,7 @@ TYPE(ConstantArray, ArrayType) TYPE(IncompleteArray, ArrayType) TYPE(VariableArray, ArrayType) DEPENDENT_TYPE(DependentSizedArray, ArrayType) +DEPENDENT_TYPE(DependentSizedExtVector, Type) TYPE(Vector, Type) TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d97d2155c0..660b30a5e2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1269,6 +1269,18 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { return QualType(New, 0); } +QualType ASTContext::getDependentSizedExtVectorType(QualType vecType, + Expr *SizeExpr, + SourceLocation AttrLoc) { + DependentSizedExtVectorType *New = + new (*this,8) DependentSizedExtVectorType(vecType, QualType(), + SizeExpr, AttrLoc); + + DependentSizedExtVectorTypes.push_back(New); + Types.push_back(New); + return QualType(New, 0); +} + /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 40a997cebc..55a0952223 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -50,6 +50,13 @@ void DependentSizedArrayType::Destroy(ASTContext& C) { C.Deallocate(this); } +void DependentSizedExtVectorType::Destroy(ASTContext& C) { + if (SizeExpr) + SizeExpr->Destroy(C); + this->~DependentSizedExtVectorType(); + C.Deallocate(this); +} + /// getArrayElementTypeNoTypeQual - If this is an array type, return the /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. @@ -1356,6 +1363,19 @@ void DependentSizedArrayType::getAsStringInternal(std::string &S, const Printing getElementType().getAsStringInternal(S, Policy); } +void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { + getElementType().getAsStringInternal(S, Policy); + + S += " __attribute__((ext_vector_ type("; + if (getSizeExpr()) { + std::string SStr; + llvm::raw_string_ostream s(SStr); + getSizeExpr()->printPretty(s, 0, Policy); + S += s.str(); + } + S += ")))"; +} + void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { // FIXME: We prefer to print the size directly here, but have no way // to get the size of the type. diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 28fb918fef..bbfab88a3f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -359,6 +359,8 @@ public: QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceLocation Loc, DeclarationName Entity); + QualType BuildExtVectorType(QualType T, ExprArg ArraySize, + SourceLocation AttrLoc); QualType BuildFunctionType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, bool Variadic, unsigned Quals, @@ -1116,8 +1118,8 @@ public: // More parsing and symbol table subroutines. // Decl attributes - this routine is the top level dispatcher. - void ProcessDeclAttributes(Decl *D, const Declarator &PD); - void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList); + void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); + void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList); void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b995717ac8..829ea91028 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1615,7 +1615,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewTD->setInvalidDecl(); // Handle attributes prior to checking for duplicates in MergeVarDecl - ProcessDeclAttributes(NewTD, D); + ProcessDeclAttributes(S, NewTD, D); // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) { @@ -1801,7 +1801,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewVD->setLexicalDeclContext(CurContext); // Handle attributes prior to checking for duplicates in MergeVarDecl - ProcessDeclAttributes(NewVD, D); + ProcessDeclAttributes(S, NewVD, D); // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { @@ -2298,7 +2298,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // (for example to check for conflicts, etc). // FIXME: This needs to happen before we merge declarations. Then, // let attribute merging cope with attribute conflicts. - ProcessDeclAttributes(NewFD, D); + ProcessDeclAttributes(S, NewFD, D); AddKnownFunctionAttributes(NewFD); if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { @@ -2907,7 +2907,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (II) IdResolver.AddDecl(New); - ProcessDeclAttributes(New, D); + ProcessDeclAttributes(S, New, D); if (New->hasAttr<BlocksAttr>()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); @@ -3628,7 +3628,7 @@ CreateNewDecl: New->setInvalidDecl(); if (Attr) - ProcessDeclAttributeList(New, Attr); + ProcessDeclAttributeList(S, New, Attr); // If we're declaring or defining a tag in function prototype scope // in C, note that this type can only be used within the function. @@ -3878,7 +3878,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. if (D) - ProcessDeclAttributes(NewFD, *D); + // FIXME: What to pass instead of TUScope? + ProcessDeclAttributes(TUScope, NewFD, *D); if (T.isObjCGCWeak()) Diag(Loc, diag::warn_attribute_weak_on_field); @@ -3985,7 +3986,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, } // Process attributes attached to the ivar. - ProcessDeclAttributes(NewID, D); + ProcessDeclAttributes(S, NewID, D); if (D.isInvalidType()) NewID->setInvalidDecl(); @@ -4151,7 +4152,7 @@ void Sema::ActOnFields(Scope* S, } if (Attr) - ProcessDeclAttributeList(Record, Attr); + ProcessDeclAttributeList(S, Record, Attr); } EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1afdb6011d..b309b3b552 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -156,8 +156,8 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { // least add some helper functions to check most argument patterns (# // and types of args). -static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, + const AttributeList &Attr, Sema &S) { TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); @@ -165,37 +165,32 @@ static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, } QualType curType = tDecl->getUnderlyingType(); - // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); - llvm::APSInt vecSize(32); - if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "ext_vector_type" << sizeExpr->getSourceRange(); - return; - } - // unlike gcc's vector_size attribute, we do not allow vectors to be defined - // in conjunction with complex types (pointers, arrays, functions, etc.). - if (!curType->isIntegerType() && !curType->isRealFloatingType()) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType; - return; + + Expr *sizeExpr; + + // Special case where the argument is a template id. + if (Attr.getParameterName()) { + sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), + Attr.getParameterName(), + false, 0, false).takeAs<Expr>(); + } else { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + sizeExpr = static_cast<Expr *>(Attr.getArg(0)); } - // unlike gcc's vector_size attribute, the size is specified as the - // number of elements, not the number of bytes. - unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); - - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - return; + + // Instantiate/Install the vector type, and let Sema build the type for us. + // This will run the reguired checks. + QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc()); + if (!T.isNull()) { + tDecl->setUnderlyingType(T); + + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(tDecl); } - // Instantiate/Install the vector type, the number of elements is > 0. - tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize)); - // Remember this typedef decl, we will need it later for diagnostics. - S.ExtVectorDecls.push_back(tDecl); } @@ -1698,7 +1693,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it. -static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { +static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.isDeclspecAttribute()) // FIXME: Try to deal with __declspec attributes! return; @@ -1721,7 +1716,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; case AttributeList::AT_ext_vector_type: - HandleExtVectorTypeAttr(D, Attr, S); + HandleExtVectorTypeAttr(scope, D, Attr, S); break; case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; @@ -1777,9 +1772,9 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. -void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { +void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) { while (AttrList) { - ProcessDeclAttribute(D, *AttrList, *this); + ProcessDeclAttribute(S, D, *AttrList, *this); AttrList = AttrList->getNext(); } } @@ -1787,10 +1782,10 @@ void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. -void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: @@ -1798,9 +1793,9 @@ void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 70057a34df..7a4789411c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2671,7 +2671,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { else CurContext->addDecl(Context, ExDecl); - ProcessDeclAttributes(ExDecl, D); + ProcessDeclAttributes(S, ExDecl, D); return DeclPtrTy::make(ExDecl); } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 5d475163cb..9013726e1a 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -116,7 +116,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, ClassLoc); if (AttrList) - ProcessDeclAttributeList(IDecl, AttrList); + ProcessDeclAttributeList(TUScope, IDecl, AttrList); PushOnScopeChains(IDecl, TUScope); } @@ -282,7 +282,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PDecl->setForwardDecl(false); } if (AttrList) - ProcessDeclAttributeList(PDecl, AttrList); + ProcessDeclAttributeList(TUScope, PDecl, AttrList); if (NumProtoRefs) { /// Check then save referenced protocols. PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context); @@ -532,7 +532,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, PushOnScopeChains(PDecl, TUScope); } if (attrList) - ProcessDeclAttributeList(PDecl, attrList); + ProcessDeclAttributeList(TUScope, PDecl, attrList); Protocols.push_back(PDecl); } @@ -1663,7 +1663,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); // Apply the attributes to the parameter. - ProcessDeclAttributeList(Param, ArgInfo[i].ArgAttrs); + ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); Params.push_back(Param); } @@ -1674,7 +1674,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( const ObjCMethodDecl *PrevMethod = 0; if (AttrList) - ProcessDeclAttributeList(ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); // For implementations (which can be very "coarse grain"), we add the // method now. This allows the AST to implement lookup methods that work @@ -1877,7 +1877,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(PDecl, FD.D); + ProcessDeclAttributes(S, PDecl, FD.D); // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c0469416e4..ab12cff3af 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5126,7 +5126,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { if (ParamInfo.getNumTypeObjects() == 0 || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) { - ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo); + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); QualType T = GetTypeForDeclarator(ParamInfo, CurScope); if (T->isArrayType()) { @@ -5182,7 +5182,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(), CurBlock->Params.size()); CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); - ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo); + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), E = CurBlock->TheDecl->param_end(); AI != E; ++AI) // If this has an identifier, add it to the scope stack. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d7a8a727f8..0ae9f1d077 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -548,7 +548,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, NewClass->startDefinition(); if (Attr) - ProcessDeclAttributeList(NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); PushOnScopeChains(NewTemplate, S); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index c9b6e13d4a..dd955fe0af 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -802,6 +802,14 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, Deduced); break; + case Type::DependentSizedExtVector: { + const DependentSizedExtVectorType *VecType + = cast<DependentSizedExtVectorType>(T.getTypePtr()); + MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced); + MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced); + break; + } + case Type::FunctionProto: { const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr()); MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 31c048d74c..fd5a460bfc 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -431,6 +431,32 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T, } QualType +TemplateTypeInstantiator:: +InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T, + unsigned Quals) const { + + // Instantiate the element type if needed + QualType ElementType = T->getElementType(); + if (ElementType->isDependentType()) { + ElementType = Instantiate(ElementType); + if (ElementType.isNull()) + return QualType(); + } + + // Instantiate the size expression + Expr *SizeExpr = T->getSizeExpr(); + Sema::OwningExprResult InstantiatedArraySize = + SemaRef.InstantiateExpr(SizeExpr, TemplateArgs); + if (InstantiatedArraySize.isInvalid()) + return QualType(); + + return SemaRef.BuildExtVectorType(ElementType, + SemaRef.Owned( + InstantiatedArraySize.takeAs<Expr>()), + T->getAttributeLoc()); +} + +QualType TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T, unsigned Quals) const { // FIXME: Implement this diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 70a9270607..967f650d13 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -543,6 +543,48 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } + +/// \brief Build an ext-vector type. +/// +/// Run the required checks for the extended vector type. +QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize, + SourceLocation AttrLoc) { + + Expr *Arg = (Expr *)ArraySize.get(); + + // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // in conjunction with complex types (pointers, arrays, functions, etc.). + if (!T->isDependentType() && + !T->isIntegerType() && !T->isRealFloatingType()) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T; + return QualType(); + } + + if (!Arg->isTypeDependent() && !Arg->isValueDependent()) { + llvm::APSInt vecSize(32); + if (!Arg->isIntegerConstantExpr(vecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_not_int) + << "ext_vector_type" << Arg->getSourceRange(); + return QualType(); + } + + // unlike gcc's vector_size attribute, the size is specified as the + // number of elements, not the number of bytes. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); + + if (vectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) + << Arg->getSourceRange(); + return QualType(); + } + + if (!T->isDependentType()) + return Context.getExtVectorType(T, vectorSize); + } + + return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(), + AttrLoc); +} /// \brief Build a function type. /// diff --git a/test/SemaTemplate/ext-vector-type.cpp b/test/SemaTemplate/ext-vector-type.cpp new file mode 100644 index 0000000000..d6c02bb629 --- /dev/null +++ b/test/SemaTemplate/ext-vector-type.cpp @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, unsigned Length> +struct make1 { + typedef T __attribute__((ext_vector_type(Length))) type; +}; + +int test_make1() { + make1<int, 5>::type x; + x.x = 4; +} + +template<typename T, unsigned Length> +struct make2 { + typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{zero vector size}} +}; + +int test_make2() { + make2<int, 0> x; // expected-note{{in instantiation of}} +} + +template<typename T, unsigned Length> +struct make3 { + typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type 'struct s'}} +}; + +struct s {}; + +int test_make3() { + make3<s, 3>x; // expected-note{{in instantiation of}} +} + +template<typename T, T Length> +struct make4 { + typedef T __attribute__((ext_vector_type(Length))) type; +}; + +int test_make4() { + make4<int, 4>::type x; + x.w = 7; +} + +typedef int* int_ptr; +template<unsigned Length> +struct make5 { + typedef int_ptr __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type}} +}; + |