Eliminate a 'default' case in template argument deduction, where we
were just punting on template argument deduction for a number of type
nodes. Most of them, obviously, didn't matter.
As a consequence of this, make extended vector types (via the
ext_vector_type attribute) actually work properly for several
important cases:
- If the attribute appears in a type-id (i.e, not attached to a
typedef), actually build a proper vector type
- Build ExtVectorType whenever the size is constant; previously, we
were building DependentSizedExtVectorType when the size was constant
but the type was dependent, which makes no sense at all.
- Teach template argument deduction to handle
ExtVectorType/DependentSizedExtVectorType.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133060 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1ec7199..430b4f9 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -217,7 +217,12 @@
CXXScopeSpec SS;
UnqualifiedId id;
id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
- sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
+
+ ExprResult Size = S.ActOnIdExpression(scope, SS, id, false, false);
+ if (Size.isInvalid())
+ return;
+
+ sizeExpr = Size.get();
} else {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 842c5fb..9011cdf 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1053,10 +1053,39 @@
}
switch (Param->getTypeClass()) {
- // No deduction possible for these types
+ // Non-canonical types cannot appear here.
+#define NON_CANONICAL_TYPE(Class, Base) \
+ case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
+#define TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+
+ case Type::TemplateTypeParm:
+ case Type::SubstTemplateTypeParmPack:
+ llvm_unreachable("Type nodes handled above");
+
+ // These types cannot be used in templates or cannot be dependent, so
+ // deduction always fails.
case Type::Builtin:
+ case Type::VariableArray:
+ case Type::Vector:
+ case Type::FunctionNoProto:
+ case Type::Record:
+ case Type::Enum:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
return Sema::TDK_NonDeducedMismatch;
+ // _Complex T [placeholder extension]
+ case Type::Complex:
+ if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
+ return DeduceTemplateArguments(S, TemplateParams,
+ cast<ComplexType>(Param)->getElementType(),
+ ComplexArg->getElementType(),
+ Info, Deduced, TDF);
+
+ return Sema::TDK_NonDeducedMismatch;
+
// T *
case Type::Pointer: {
QualType PointeeType;
@@ -1360,14 +1389,105 @@
Deduced, 0);
}
+ // (clang extension)
+ //
+ // T __attribute__(((ext_vector_type(<integral constant>))))
+ case Type::ExtVector: {
+ const ExtVectorType *VectorParam = cast<ExtVectorType>(Param);
+ if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+ // Make sure that the vectors have the same number of elements.
+ if (VectorParam->getNumElements() != VectorArg->getNumElements())
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Perform deduction on the element types.
+ return DeduceTemplateArguments(S, TemplateParams,
+ VectorParam->getElementType(),
+ VectorArg->getElementType(),
+ Info, Deduced,
+ TDF);
+ }
+
+ if (const DependentSizedExtVectorType *VectorArg
+ = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+ // We can't check the number of elements, since the argument has a
+ // dependent number of elements. This can only occur during partial
+ // ordering.
+
+ // Perform deduction on the element types.
+ return DeduceTemplateArguments(S, TemplateParams,
+ VectorParam->getElementType(),
+ VectorArg->getElementType(),
+ Info, Deduced,
+ TDF);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ // (clang extension)
+ //
+ // T __attribute__(((ext_vector_type(N))))
+ case Type::DependentSizedExtVector: {
+ const DependentSizedExtVectorType *VectorParam
+ = cast<DependentSizedExtVectorType>(Param);
+
+ if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ VectorParam->getElementType(),
+ VectorArg->getElementType(),
+ Info, Deduced,
+ TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP
+ = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+ ArgSize = VectorArg->getNumElements();
+ return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
+ false, Info, Deduced);
+ }
+
+ if (const DependentSizedExtVectorType *VectorArg
+ = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+ // Perform deduction on the element types.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ VectorParam->getElementType(),
+ VectorArg->getElementType(),
+ Info, Deduced,
+ TDF))
+ return Result;
+
+ // Perform deduction on the vector size, if we can.
+ NonTypeTemplateParmDecl *NTTP
+ = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+ Info, Deduced);
+ }
+
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
+ case Type::UnresolvedUsing:
+ case Type::Decltype:
+ case Type::UnaryTransform:
+ case Type::Auto:
+ case Type::DependentTemplateSpecialization:
+ case Type::PackExpansion:
// No template argument deduction for these types
return Sema::TDK_Success;
-
- default:
- break;
}
// FIXME: Many more cases to go (to go).
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ec8fdc9..ef3c262 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1320,8 +1320,7 @@
return QualType();
}
- if (!T->isDependentType())
- return Context.getExtVectorType(T, vectorSize);
+ return Context.getExtVectorType(T, vectorSize);
}
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
@@ -3151,6 +3150,40 @@
VectorType::GenericVector);
}
+/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
+/// a type.
+static void HandleExtVectorTypeAttr(QualType &CurType,
+ const AttributeList &Attr,
+ Sema &S) {
+ Expr *sizeExpr;
+
+ // Special case where the argument is a template id.
+ if (Attr.getParameterName()) {
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+
+ ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, id, false,
+ false);
+ if (Size.isInvalid())
+ return;
+
+ sizeExpr = Size.get();
+ } else {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ sizeExpr = Attr.getArg(0);
+ }
+
+ // Create the vector type.
+ QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
+ if (!T.isNull())
+ CurType = T;
+}
+
/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
/// "neon_polyvector_type" attributes are used to create vector types that
/// are mangled according to ARM's ABI. Otherwise, these types are identical
@@ -3241,6 +3274,11 @@
case AttributeList::AT_vector_size:
HandleVectorSizeAttr(type, attr, state.getSema());
break;
+ case AttributeList::AT_ext_vector_type:
+ if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
+ != DeclSpec::SCS_typedef)
+ HandleExtVectorTypeAttr(type, attr, state.getSema());
+ break;
case AttributeList::AT_neon_vector_type:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector, "neon_vector_type");