diff options
| author | Erich Keane <erich.keane@intel.com> | 2018-07-13 19:46:04 +0000 |
|---|---|---|
| committer | Erich Keane <erich.keane@intel.com> | 2018-07-13 19:46:04 +0000 |
| commit | f702b029f46e1644f9d4b859e88c09e121009562 (patch) | |
| tree | 71cf5b2097457ef9919c9933f5fd2554162d134b /clang/lib/Sema | |
| parent | 393fe62e3373c04ac9a2ab391335dfe6e08949e7 (diff) | |
| download | bcm5719-llvm-f702b029f46e1644f9d4b859e88c09e121009562.tar.gz bcm5719-llvm-f702b029f46e1644f9d4b859e88c09e121009562.zip | |
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
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 56 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 116 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 54 |
4 files changed, 188 insertions, 43 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e78fd438dcc..c1d8c24796d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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()); } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 3a480628a7e..51d2bae08ca 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -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); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 641a2f5f06e..0736fabac3d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -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 diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6ee5eca75c9..5ed92aea32c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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, |

