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
This commit is contained in:
Douglas Gregor 2011-06-15 16:02:29 +00:00
parent bf60a8c1de
commit 4ac01401b1
6 changed files with 215 additions and 10 deletions

View File

@ -5820,10 +5820,18 @@ private:
protected:
friend class Parser;
friend class InitializationSequence;
friend class InitializationSequence;
public:
/// \brief Retrieve the parser's current scope.
Scope *getCurScope() const { return CurScope; }
///
/// This routine must only be used when it is certain that semantic analysis
/// and the parser are in precisely the same context, which is not the case
/// when, e.g., we are performing any kind of template instantiation.
/// Therefore, the only safe places to use this scope are in the parser
/// itself and in routines directly invoked from the parser and *never* from
/// template substitution or instantiation.
Scope *getCurScope() const { return CurScope; }
};
/// \brief RAII object that enters a new expression evaluation context.

View File

@ -1881,7 +1881,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
/// the specified element type and size. VectorType must be a built-in type.
QualType
ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const {
assert(vecType->isBuiltinType());
assert(vecType->isBuiltinType() || vecType->isDependentType());
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;

View File

@ -217,7 +217,12 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
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) {

View File

@ -1053,10 +1053,39 @@ DeduceTemplateArguments(Sema &S,
}
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 @@ DeduceTemplateArguments(Sema &S,
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).

View File

@ -1320,8 +1320,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
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 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
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 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
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");

View File

@ -58,3 +58,37 @@ int test_make6() {
y.x = -1;
y.w = -1; // expected-error{{vector component access exceeds type}}
}
namespace Deduction {
template<typename T> struct X0;
template<typename T, unsigned N>
struct X0<T __attribute__((ext_vector_type(N)))> {
static const unsigned value = 0;
};
template<typename T>
struct X0<T __attribute__((ext_vector_type(4)))> {
static const unsigned value = 1;
};
template<unsigned N>
struct X0<float __attribute__((ext_vector_type(N)))> {
static const unsigned value = 2;
};
template<>
struct X0<float __attribute__((ext_vector_type(4)))> {
static const unsigned value = 3;
};
typedef int __attribute__((ext_vector_type(2))) int2;
typedef int __attribute__((ext_vector_type(4))) int4;
typedef float __attribute__((ext_vector_type(2))) float2;
typedef float __attribute__((ext_vector_type(4))) float4;
int array0[X0<int2>::value == 0? 1 : -1];
int array1[X0<int4>::value == 1? 1 : -1];
int array2[X0<float2>::value == 2? 1 : -1];
int array3[X0<float4>::value == 3? 1 : -1];
}