mirror of https://github.com/microsoft/clang.git
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:
parent
bf60a8c1de
commit
4ac01401b1
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue