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
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 28fb918..bbfab88 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -359,6 +359,8 @@
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 @@
// 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 b995717..829ea91 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1615,7 +1615,7 @@
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 @@
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 @@
// (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 @@
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 @@
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 @@
// 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 @@
}
// Process attributes attached to the ivar.
- ProcessDeclAttributes(NewID, D);
+ ProcessDeclAttributes(S, NewID, D);
if (D.isInvalidType())
NewID->setInvalidDecl();
@@ -4151,7 +4152,7 @@
}
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 1afdb60..b309b3b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -156,8 +156,8 @@
// 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 @@
}
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;
+
+ // 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));
}
- 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;
+
+ // 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);
}
- // 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;
- }
- // 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, 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 @@
/// 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 @@
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 @@
/// 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 @@
/// 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 @@
// 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 70057a3..7a47894 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2671,7 +2671,7 @@
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 5d47516..9013726 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -116,7 +116,7 @@
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
ClassName, ClassLoc);
if (AttrList)
- ProcessDeclAttributeList(IDecl, AttrList);
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
PushOnScopeChains(IDecl, TUScope);
}
@@ -282,7 +282,7 @@
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 @@
PushOnScopeChains(PDecl, TUScope);
}
if (attrList)
- ProcessDeclAttributeList(PDecl, attrList);
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
Protocols.push_back(PDecl);
}
@@ -1663,7 +1663,7 @@
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 @@
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 @@
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 c046941..ab12cff 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5126,7 +5126,7 @@
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 @@
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 d7a8a72..0ae9f1d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -548,7 +548,7 @@
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 c9b6e13..dd955fe 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -802,6 +802,14 @@
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 31c048d..fd5a460 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -431,6 +431,32 @@
}
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 70a9270..967f650 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -543,6 +543,48 @@
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.
///