PR15730/PR16986 Allow dependently typed vector_size types.

As listed in the above PRs, vector_size doesn't allow
dependent types/values. This patch introduces a new
DependentVectorType to handle a VectorType that has a dependent
size or type.

In the future, ALL the vector-types should be able to create one
of these to handle dependent types/sizes as well. For example,
DependentSizedExtVectorType could likely be switched to just use
this instead, though that is left as an exercise for the future.


Differential Revision: https://reviews.llvm.org/D49045

llvm-svn: 337036
This commit is contained in:
Erich Keane 2018-07-13 19:46:04 +00:00
parent 393fe62e33
commit f702b029f4
22 changed files with 560 additions and 87 deletions

View File

@ -168,6 +168,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DependentAddressSpaceType>
DependentAddressSpaceTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes;
mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
FunctionProtoTypes;
@ -1321,6 +1322,11 @@ public:
/// \pre \p VectorType must be a built-in type.
QualType getVectorType(QualType VectorType, unsigned NumElts,
VectorType::VectorKind VecKind) const;
/// Return the unique reference to the type for a dependently sized vector of
/// the specified element type.
QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr,
SourceLocation AttrLoc,
VectorType::VectorKind VecKind) const;
/// Return the unique reference to an extended vector type
/// of the specified element type and size.

View File

@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
DEF_TRAVERSE_TYPE(DependentVectorType, {
if (T->getSizeExpr())
TRY_TO(TraverseStmt(T->getSizeExpr()));
TRY_TO(TraverseType(T->getElementType()));
})
DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
if (T->getSizeExpr())
TRY_TO(TraverseStmt(T->getSizeExpr()));
@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, {
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
DEF_TRAVERSE_TYPELOC(DependentVectorType, {
if (TL.getTypePtr()->getSizeExpr())
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
// FIXME: size and attributes
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(ExtVectorType, {

View File

@ -1590,6 +1590,7 @@ protected:
class VectorTypeBitfields {
friend class VectorType;
friend class DependentVectorType;
unsigned : NumTypeBits;
@ -3079,6 +3080,51 @@ public:
}
};
/// Represents a vector type where either the type or size is dependent.
////
/// For example:
/// \code
/// template<typename T, int Size>
/// class vector {
/// typedef T __attribute__((vector_size(Size))) type;
/// }
/// \endcode
class DependentVectorType : public Type, public llvm::FoldingSetNode {
friend class ASTContext;
const ASTContext &Context;
QualType ElementType;
Expr *SizeExpr;
SourceLocation Loc;
DependentVectorType(const ASTContext &Context, QualType ElementType,
QualType CanonType, Expr *SizeExpr,
SourceLocation Loc, VectorType::VectorKind vecKind);
public:
Expr *getSizeExpr() const { return SizeExpr; }
QualType getElementType() const { return ElementType; }
SourceLocation getAttributeLoc() const { return Loc; }
VectorType::VectorKind getVectorKind() const {
return VectorType::VectorKind(VectorTypeBits.VecKind);
}
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
static bool classof(const Type *T) {
return T->getTypeClass() == DependentVector;
}
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind());
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType ElementType, const Expr *SizeExpr,
VectorType::VectorKind VecKind);
};
/// ExtVectorType - Extended vector type. This type is created using
/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This

View File

@ -1798,6 +1798,13 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
VectorType> {
};
// FIXME: size expression and attribute locations (or keyword if we
// ever fully support altivec syntax).
class DependentVectorTypeLoc
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DependentVectorTypeLoc,
DependentVectorType> {};
// FIXME: size expression and attribute locations.
class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
ExtVectorTypeLoc,

View File

@ -75,6 +75,7 @@ DEPENDENT_TYPE(DependentSizedArray, ArrayType)
DEPENDENT_TYPE(DependentSizedExtVector, Type)
DEPENDENT_TYPE(DependentAddressSpace, Type)
TYPE(Vector, Type)
DEPENDENT_TYPE(DependentVector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)

View File

@ -1377,6 +1377,7 @@ public:
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity);
QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc);
QualType BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc);
QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,

View File

@ -1032,133 +1032,133 @@ namespace serialization {
/// AST. Note that DeclCode values share this code space.
enum TypeCode {
/// An ExtQualType record.
TYPE_EXT_QUAL = 1,
TYPE_EXT_QUAL = 1,
/// A ComplexType record.
TYPE_COMPLEX = 3,
TYPE_COMPLEX = 3,
/// A PointerType record.
TYPE_POINTER = 4,
TYPE_POINTER = 4,
/// A BlockPointerType record.
TYPE_BLOCK_POINTER = 5,
TYPE_BLOCK_POINTER = 5,
/// An LValueReferenceType record.
TYPE_LVALUE_REFERENCE = 6,
TYPE_LVALUE_REFERENCE = 6,
/// An RValueReferenceType record.
TYPE_RVALUE_REFERENCE = 7,
TYPE_RVALUE_REFERENCE = 7,
/// A MemberPointerType record.
TYPE_MEMBER_POINTER = 8,
TYPE_MEMBER_POINTER = 8,
/// A ConstantArrayType record.
TYPE_CONSTANT_ARRAY = 9,
TYPE_CONSTANT_ARRAY = 9,
/// An IncompleteArrayType record.
TYPE_INCOMPLETE_ARRAY = 10,
TYPE_INCOMPLETE_ARRAY = 10,
/// A VariableArrayType record.
TYPE_VARIABLE_ARRAY = 11,
TYPE_VARIABLE_ARRAY = 11,
/// A VectorType record.
TYPE_VECTOR = 12,
TYPE_VECTOR = 12,
/// An ExtVectorType record.
TYPE_EXT_VECTOR = 13,
TYPE_EXT_VECTOR = 13,
/// A FunctionNoProtoType record.
TYPE_FUNCTION_NO_PROTO = 14,
TYPE_FUNCTION_NO_PROTO = 14,
/// A FunctionProtoType record.
TYPE_FUNCTION_PROTO = 15,
TYPE_FUNCTION_PROTO = 15,
/// A TypedefType record.
TYPE_TYPEDEF = 16,
TYPE_TYPEDEF = 16,
/// A TypeOfExprType record.
TYPE_TYPEOF_EXPR = 17,
TYPE_TYPEOF_EXPR = 17,
/// A TypeOfType record.
TYPE_TYPEOF = 18,
TYPE_TYPEOF = 18,
/// A RecordType record.
TYPE_RECORD = 19,
TYPE_RECORD = 19,
/// An EnumType record.
TYPE_ENUM = 20,
TYPE_ENUM = 20,
/// An ObjCInterfaceType record.
TYPE_OBJC_INTERFACE = 21,
TYPE_OBJC_INTERFACE = 21,
/// An ObjCObjectPointerType record.
TYPE_OBJC_OBJECT_POINTER = 22,
TYPE_OBJC_OBJECT_POINTER = 22,
/// a DecltypeType record.
TYPE_DECLTYPE = 23,
TYPE_DECLTYPE = 23,
/// An ElaboratedType record.
TYPE_ELABORATED = 24,
TYPE_ELABORATED = 24,
/// A SubstTemplateTypeParmType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
/// An UnresolvedUsingType record.
TYPE_UNRESOLVED_USING = 26,
TYPE_UNRESOLVED_USING = 26,
/// An InjectedClassNameType record.
TYPE_INJECTED_CLASS_NAME = 27,
TYPE_INJECTED_CLASS_NAME = 27,
/// An ObjCObjectType record.
TYPE_OBJC_OBJECT = 28,
TYPE_OBJC_OBJECT = 28,
/// An TemplateTypeParmType record.
TYPE_TEMPLATE_TYPE_PARM = 29,
TYPE_TEMPLATE_TYPE_PARM = 29,
/// An TemplateSpecializationType record.
TYPE_TEMPLATE_SPECIALIZATION = 30,
TYPE_TEMPLATE_SPECIALIZATION = 30,
/// A DependentNameType record.
TYPE_DEPENDENT_NAME = 31,
TYPE_DEPENDENT_NAME = 31,
/// A DependentTemplateSpecializationType record.
TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
/// A DependentSizedArrayType record.
TYPE_DEPENDENT_SIZED_ARRAY = 33,
TYPE_DEPENDENT_SIZED_ARRAY = 33,
/// A ParenType record.
TYPE_PAREN = 34,
TYPE_PAREN = 34,
/// A PackExpansionType record.
TYPE_PACK_EXPANSION = 35,
TYPE_PACK_EXPANSION = 35,
/// An AttributedType record.
TYPE_ATTRIBUTED = 36,
TYPE_ATTRIBUTED = 36,
/// A SubstTemplateTypeParmPackType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
/// A AutoType record.
TYPE_AUTO = 38,
TYPE_AUTO = 38,
/// A UnaryTransformType record.
TYPE_UNARY_TRANSFORM = 39,
TYPE_UNARY_TRANSFORM = 39,
/// An AtomicType record.
TYPE_ATOMIC = 40,
TYPE_ATOMIC = 40,
/// A DecayedType record.
TYPE_DECAYED = 41,
TYPE_DECAYED = 41,
/// An AdjustedType record.
TYPE_ADJUSTED = 42,
TYPE_ADJUSTED = 42,
/// A PipeType record.
TYPE_PIPE = 43,
TYPE_PIPE = 43,
/// An ObjCTypeParamType record.
TYPE_OBJC_TYPE_PARAM = 44,
TYPE_OBJC_TYPE_PARAM = 44,
/// A DeducedTemplateSpecializationType record.
TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45,
@ -1167,7 +1167,10 @@ namespace serialization {
TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46,
/// A DependentAddressSpaceType record.
TYPE_DEPENDENT_ADDRESS_SPACE = 47
TYPE_DEPENDENT_ADDRESS_SPACE = 47,
/// A dependentSizedVectorType record.
TYPE_DEPENDENT_SIZED_VECTOR = 48
};
/// The type IDs for special types constructed by semantic

View File

@ -3035,6 +3035,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::Builtin:
case Type::Complex:
case Type::Vector:
case Type::DependentVector:
case Type::ExtVector:
case Type::DependentSizedExtVector:
case Type::DependentAddressSpace:
@ -3313,6 +3314,45 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
return QualType(New, 0);
}
QualType
ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr,
SourceLocation AttrLoc,
VectorType::VectorKind VecKind) const {
llvm::FoldingSetNodeID ID;
DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr,
VecKind);
void *InsertPos = nullptr;
DependentVectorType *Canon =
DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentVectorType *New;
if (Canon) {
New = new (*this, TypeAlignment) DependentVectorType(
*this, VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind);
} else {
QualType CanonVecTy = getCanonicalType(VecType);
if (CanonVecTy == VecType) {
New = new (*this, TypeAlignment) DependentVectorType(
*this, VecType, QualType(), SizeExpr, AttrLoc, VecKind);
DependentVectorType *CanonCheck =
DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!CanonCheck &&
"Dependent-sized vector_size canonical type broken");
(void)CanonCheck;
DependentVectorTypes.InsertNode(New, InsertPos);
} else {
QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
SourceLocation());
New = new (*this, TypeAlignment) DependentVectorType(
*this, VecType, Canon, SizeExpr, AttrLoc, VecKind);
}
}
Types.push_back(New);
return QualType(New, 0);
}
/// getExtVectorType - Return the unique reference to an extended vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType

View File

@ -51,7 +51,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// Determine structural equivalence of two expressions.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Expr *E1, Expr *E2) {
const Expr *E1, const Expr *E2) {
if (!E1 || !E2)
return E1 == E2;
@ -408,6 +408,20 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
case Type::DependentVector: {
const auto *Vec1 = cast<DependentVectorType>(T1);
const auto *Vec2 = cast<DependentVectorType>(T2);
if (Vec1->getVectorKind() != Vec2->getVectorKind())
return false;
if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
Vec2->getSizeExpr()))
return false;
if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
Vec2->getElementType()))
return false;
break;
}
case Type::Vector:
case Type::ExtVector: {
const auto *Vec1 = cast<VectorType>(T1);

View File

@ -539,7 +539,9 @@ private:
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
const FunctionDecl *FD = nullptr);
void mangleNeonVectorType(const VectorType *T);
void mangleNeonVectorType(const DependentVectorType *T);
void mangleAArch64NeonVectorType(const VectorType *T);
void mangleAArch64NeonVectorType(const DependentVectorType *T);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
void mangleMemberExprBase(const Expr *base, bool isArrow);
@ -1930,6 +1932,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentAddressSpace:
case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@ -3000,6 +3003,14 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
Out << BaseName << EltName;
}
void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot mangle this dependent neon vector type yet");
Diags.Report(T->getAttributeLoc(), DiagID);
}
static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
switch (EltType->getKind()) {
case BuiltinType::SChar:
@ -3067,6 +3078,13 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str();
Out << TypeName.length() << TypeName;
}
void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot mangle this dependent neon vector type yet");
Diags.Report(T->getAttributeLoc(), DiagID);
}
// GNU extension: vector types
// <type> ::= <vector-type>
@ -3097,6 +3115,32 @@ void CXXNameMangler::mangleType(const VectorType *T) {
else
mangleType(T->getElementType());
}
void CXXNameMangler::mangleType(const DependentVectorType *T) {
if ((T->getVectorKind() == VectorType::NeonVector ||
T->getVectorKind() == VectorType::NeonPolyVector)) {
llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
llvm::Triple::ArchType Arch =
getASTContext().getTargetInfo().getTriple().getArch();
if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) &&
!Target.isOSDarwin())
mangleAArch64NeonVectorType(T);
else
mangleNeonVectorType(T);
return;
}
Out << "Dv";
mangleExpression(T->getSizeExpr());
Out << '_';
if (T->getVectorKind() == VectorType::AltiVecPixel)
Out << 'p';
else if (T->getVectorKind() == VectorType::AltiVecBool)
Out << 'b';
else
mangleType(T->getElementType());
}
void CXXNameMangler::mangleType(const ExtVectorType *T) {
mangleType(static_cast<const VectorType*>(T));
}

View File

@ -2514,6 +2514,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
Qualifiers Quals, SourceRange Range) {
mangleType(static_cast<const VectorType *>(T), Quals, Range);
}
void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot mangle this dependent-sized vector type yet");
Diags.Report(Range.getBegin(), DiagID) << Range;
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
Qualifiers, SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();

View File

@ -177,6 +177,27 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
E->Profile(ID, Context, true);
}
DependentVectorType::DependentVectorType(
const ASTContext &Context, QualType ElementType, QualType CanonType,
Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind)
: Type(DependentVector, CanonType, /*Dependent=*/true,
/*InstantiationDependent=*/true,
ElementType->isVariablyModifiedType(),
ElementType->containsUnexpandedParameterPack() ||
(SizeExpr && SizeExpr->containsUnexpandedParameterPack())),
Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) {
VectorTypeBits.VecKind = VecKind;
}
void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context,
QualType ElementType, const Expr *SizeExpr,
VectorType::VectorKind VecKind) {
ID.AddPointer(ElementType.getAsOpaquePtr());
ID.AddInteger(VecKind);
SizeExpr->Profile(ID, Context, true);
}
DependentSizedExtVectorType::DependentSizedExtVectorType(const
ASTContext &Context,
QualType ElementType,
@ -3783,6 +3804,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:

View File

@ -242,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::RValueReference:
case Type::MemberPointer:
case Type::DependentAddressSpace:
case Type::DependentVector:
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@ -640,7 +641,55 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
}
}
void TypePrinter::printDependentVectorBefore(
const DependentVectorType *T, raw_ostream &OS) {
switch (T->getVectorKind()) {
case VectorType::AltiVecPixel:
OS << "__vector __pixel ";
break;
case VectorType::AltiVecBool:
OS << "__vector __bool ";
printBefore(T->getElementType(), OS);
break;
case VectorType::AltiVecVector:
OS << "__vector ";
printBefore(T->getElementType(), OS);
break;
case VectorType::NeonVector:
OS << "__attribute__((neon_vector_type(";
if (T->getSizeExpr())
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << "))) ";
printBefore(T->getElementType(), OS);
break;
case VectorType::NeonPolyVector:
OS << "__attribute__((neon_polyvector_type(";
if (T->getSizeExpr())
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << "))) ";
printBefore(T->getElementType(), OS);
break;
case VectorType::GenericVector: {
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
OS << "__attribute__((__vector_size__(";
if (T->getSizeExpr())
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
OS << " * sizeof(";
print(T->getElementType(), OS, StringRef());
OS << ")))) ";
printBefore(T->getElementType(), OS);
break;
}
}
}
void TypePrinter::printDependentVectorAfter(
const DependentVectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
}
void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
raw_ostream &OS) {

View File

@ -734,7 +734,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (!hadError && saw_fixed_point_suffix) {
assert(isFract || isAccum);
assert(radix == 16 || radix == 10);
//assert(radix == 16 || radix == 10);
}
}

View File

@ -5341,6 +5341,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
const DependentVectorType *T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
return Visit(T->getElementType());
}

View File

@ -1870,6 +1870,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
case Type::DependentVector: {
const auto *VectorParam = cast<DependentVectorType>(Param);
if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
// Perform deduction on the element types.
if (Sema::TemplateDeductionResult Result =
DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, VectorParam->getElementType(),
VectorArg->getElementType(), Info, Deduced, TDF))
return Result;
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
ArgSize = VectorArg->getNumElements();
// Note that we use the "array bound" rules here; just like in that
// case, we don't have any particular type for the vector size, but
// we can provide one if necessary.
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
S.Context.UnsignedIntTy, true,
Info, Deduced);
}
if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
// Perform deduction on the element types.
if (Sema::TemplateDeductionResult Result =
DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, VectorParam->getElementType(),
VectorArg->getElementType(), Info, Deduced, TDF))
return Result;
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
return DeduceNonTypeTemplateArgument(
S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced);
}
return Sema::TDK_NonDeducedMismatch;
}
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@ -5264,6 +5312,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
OnlyDeduced, Depth, Used);
break;
case Type::DependentVector: {
const auto *VecType = cast<DependentVectorType>(T);
MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
Depth, Used);
MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth,
Used);
break;
}
case Type::DependentSizedExtVector: {
const DependentSizedExtVectorType *VecType
= cast<DependentSizedExtVectorType>(T);

View File

@ -2243,6 +2243,58 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return T;
}
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) {
// The base type must be integer (not Boolean or enumeration) or float, and
// can't already be a vector.
if (!CurType->isDependentType() &&
(!CurType->isBuiltinType() || CurType->isBooleanType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType();
}
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
llvm::APSInt VecSize(32);
if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "vector_size" << AANT_ArgumentIntegerConstant
<< SizeExpr->getSourceRange();
return QualType();
}
if (CurType->isDependentType())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
unsigned VectorSize = static_cast<unsigned>(VecSize.getZExtValue() * 8);
unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
if (VectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange();
return QualType();
}
// vecSize is specified in bytes - convert to bits.
if (VectorSize % TypeSize) {
Diag(AttrLoc, diag::err_attribute_invalid_size)
<< SizeExpr->getSourceRange();
return QualType();
}
if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange();
return QualType();
}
return Context.getVectorType(CurType, VectorSize / TypeSize,
VectorType::GenericVector);
}
/// Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
@ -6857,52 +6909,30 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Attr.setInvalid();
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt vecSize(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
<< Attr.getName() << AANT_ArgumentIntegerConstant
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
// The base type must be integer (not Boolean or enumeration) or float, and
// can't already be a vector.
if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
}
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
// vecSize is specified in bytes - convert to bits.
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
// the vector size needs to be an integral multiple of the type size.
if (vectorSize % typeSize) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
Expr *SizeExpr;
// Special case where the argument is a template id.
if (Attr.isArgIdent(0)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Id;
Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
Id, false, false);
if (Size.isInvalid())
return;
SizeExpr = Size.get();
} else {
SizeExpr = Attr.getArgAsExpr(0);
}
// Success! Instantiate the vector type, the number of elements is > 0, and
// not required to be a power of 2, unlike GCC.
CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
VectorType::GenericVector);
QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
else
Attr.setInvalid();
}
/// Process the OpenCL-like ext_vector_type attribute when it occurs on

View File

@ -818,6 +818,15 @@ public:
QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
VectorType::VectorKind VecKind);
/// Build a new potentially dependently-sized extended vector type
/// given the element type and number of elements.
///
/// By default, performs semantic analysis when building the vector type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr,
SourceLocation AttributeLoc,
VectorType::VectorKind);
/// Build a new extended vector type given the element type and
/// number of elements.
///
@ -4750,6 +4759,44 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
return Result;
}
template <typename Derived>
QualType TreeTransform<Derived>::TransformDependentVectorType(
TypeLocBuilder &TLB, DependentVectorTypeLoc TL) {
const DependentVectorType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
return QualType();
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
Size = SemaRef.ActOnConstantExpression(Size);
if (Size.isInvalid())
return QualType();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
Size.get() != T->getSizeExpr()) {
Result = getDerived().RebuildDependentVectorType(
ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind());
if (Result.isNull())
return QualType();
}
// Result might be dependent or not.
if (isa<DependentVectorType>(Result)) {
DependentVectorTypeLoc NewTL =
TLB.push<DependentVectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
} else {
VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
}
return Result;
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
TypeLocBuilder &TLB,
@ -12381,6 +12428,13 @@ TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
}
template <typename Derived>
QualType TreeTransform<Derived>::RebuildDependentVectorType(
QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc,
VectorType::VectorKind VecKind) {
return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc);
}
template<typename Derived>
QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
unsigned NumElements,

View File

@ -6369,6 +6369,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getPipeType(ElementType, ReadOnly);
}
case TYPE_DEPENDENT_SIZED_VECTOR: {
unsigned Idx = 0;
QualType ElementType = readType(*Loc.F, Record, Idx);
Expr *SizeExpr = ReadExpr(*Loc.F);
SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx);
unsigned VecKind = Record[Idx];
return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc,
(VectorType::VectorKind)VecKind);
}
case TYPE_DEPENDENT_SIZED_EXT_VECTOR: {
unsigned Idx = 0;
@ -6549,6 +6560,11 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitDependentVectorTypeLoc(
DependentVectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation());
}

View File

@ -455,6 +455,14 @@ ASTTypeWriter::VisitDependentSizedExtVectorType(
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
}
void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) {
Record.AddTypeRef(T->getElementType());
Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
Record.AddSourceLocation(T->getAttributeLoc());
Record.push_back(T->getVectorKind());
Code = TYPE_DEPENDENT_SIZED_VECTOR;
}
void
ASTTypeWriter::VisitDependentAddressSpaceType(
const DependentAddressSpaceType *T) {
@ -676,6 +684,11 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitDependentVectorTypeLoc(
DependentVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}

View File

@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x;
// PR12649
typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}}
namespace Templates {
template <typename Elt, unsigned Size>
struct TemplateVectorType {
typedef Elt __attribute__((__vector_size__(Size))) type;
};
template <int N, typename T>
struct PR15730 {
typedef T __attribute__((vector_size(N * sizeof(T)))) type;
typedef T __attribute__((vector_size(8192))) type2;
typedef T __attribute__((vector_size(3))) type3;
};
void Init() {
const TemplateVectorType<float, 32>::type Works = {};
const TemplateVectorType<int, 32>::type Works2 = {};
// expected-error@298 {{invalid vector element type 'bool'}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<bool, 32>' requested here}}
const TemplateVectorType<bool, 32>::type NoBool;
// expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int __attribute__((ext_vector_type(4))), 32>' requested here}}
const TemplateVectorType<vi4, 32>::type NoComplex;
// expected-error@298 {{vector size not an integral multiple of component size}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 33>' requested here}}
const TemplateVectorType<int, 33>::type BadSize;
// expected-error@298 {{vector size too large}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 8192>' requested here}}
const TemplateVectorType<int, 8192>::type TooLarge;
// expected-error@298 {{zero vector size}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 0>' requested here}}
const TemplateVectorType<int, 0>::type Zero;
// expected-error@304 {{vector size too large}}
// expected-error@305 {{vector size not an integral multiple of component size}}
// expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}}
const PR15730<8, int>::type PR15730_1 = {};
// expected-error@304 {{vector size too large}}
// expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}}
const PR15730<8, char>::type2 PR15730_2 = {};
}
} // namespace Templates

View File

@ -1772,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type)
DEFAULT_TYPELOC_IMPL(DependentVector, Type)
DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
DEFAULT_TYPELOC_IMPL(Vector, Type)
DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)