diff options
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 110 |
1 files changed, 106 insertions, 4 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d4b9095c7509..4d2d05307a6d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -222,6 +222,11 @@ namespace { ArraySize = 2; MostDerivedLength = I + 1; IsArray = true; + } else if (const auto *VT = Type->getAs<VectorType>()) { + Type = VT->getElementType(); + ArraySize = VT->getNumElements(); + MostDerivedLength = I + 1; + IsArray = true; } else if (const FieldDecl *FD = getAsField(Path[I])) { Type = FD->getType(); ArraySize = 0; @@ -268,7 +273,6 @@ namespace { /// If the current array is an unsized array, the value of this is /// undefined. uint64_t MostDerivedArraySize; - /// The type of the most derived object referred to by this address. QualType MostDerivedType; @@ -442,6 +446,16 @@ namespace { MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } + + void addVectorElementUnchecked(QualType EltTy, uint64_t Size, + uint64_t Idx) { + Entries.push_back(PathEntry::ArrayIndex(Idx)); + MostDerivedType = EltTy; + MostDerivedPathLength = Entries.size(); + MostDerivedArraySize = 0; + MostDerivedIsArrayElement = false; + } + void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E); void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, const APSInt &N); @@ -1737,6 +1751,11 @@ namespace { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } + void addVectorElement(EvalInfo &Info, const Expr *E, QualType EltTy, + uint64_t Size, uint64_t Idx) { + if (checkSubobject(Info, E, CSK_VectorElement)) + Designator.addVectorElementUnchecked(EltTy, Size, Idx); + } void clearIsNullPointer() { IsNullPtr = false; } @@ -3310,6 +3329,19 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, return true; } +static bool HandleLValueVectorElement(EvalInfo &Info, const Expr *E, + LValue &LVal, QualType EltTy, + uint64_t Size, uint64_t Idx) { + if (Idx) { + CharUnits SizeOfElement; + if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfElement)) + return false; + LVal.Offset += SizeOfElement * Idx; + } + LVal.addVectorElement(Info, E, EltTy, Size, Idx); + return true; +} + /// Try to evaluate the initializer for a variable declaration. /// /// \param Info Information about the ongoing evaluation. @@ -3855,6 +3887,27 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, return handler.found(Index ? O->getComplexFloatImag() : O->getComplexFloatReal(), ObjType); } + } else if (const auto *VT = ObjType->getAs<VectorType>()) { + uint64_t Index = Sub.Entries[I].getAsArrayIndex(); + unsigned NumElements = VT->getNumElements(); + if (Index == NumElements) { + if (Info.getLangOpts().CPlusPlus11) + Info.FFDiag(E, diag::note_constexpr_access_past_end) + << handler.AccessKind; + else + Info.FFDiag(E); + return handler.failed(); + } + + if (Index > NumElements) { + Info.CCEDiag(E, diag::note_constexpr_array_index) + << Index << /*array*/ 0 << NumElements; + return handler.failed(); + } + + ObjType = VT->getElementType(); + assert(I == N - 1 && "extracting subobject of scalar?"); + return handler.found(O->getVectorElt(Index), ObjType); } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) { @@ -8509,6 +8562,7 @@ public: bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); + bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -8850,15 +8904,63 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } +bool LValueExprEvaluator::VisitExtVectorElementExpr( + const ExtVectorElementExpr *E) { + bool Success = true; + + APValue Val; + if (!Evaluate(Val, Info, E->getBase())) { + if (!Info.noteFailure()) + return false; + Success = false; + } + + SmallVector<uint32_t, 4> Indices; + E->getEncodedElementAccess(Indices); + // FIXME: support accessing more than one element + if (Indices.size() > 1) + return false; + + if (Success) { + Result.setFrom(Info.Ctx, Val); + const auto *VT = E->getBase()->getType()->castAs<VectorType>(); + HandleLValueVectorElement(Info, E, Result, VT->getElementType(), + VT->getNumElements(), Indices[0]); + } + + return Success; +} + bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { - // FIXME: Deal with vectors as array subscript bases. - if (E->getBase()->getType()->isVectorType() || - E->getBase()->getType()->isSveVLSBuiltinType()) + if (E->getBase()->getType()->isSveVLSBuiltinType()) return Error(E); APSInt Index; bool Success = true; + if (const auto *VT = E->getBase()->getType()->getAs<VectorType>()) { + APValue Val; + if (!Evaluate(Val, Info, E->getBase())) { + if (!Info.noteFailure()) + return false; + Success = false; + } + + if (!EvaluateInteger(E->getIdx(), Index, Info)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + + if (Success) { + Result.setFrom(Info.Ctx, Val); + HandleLValueVectorElement(Info, E, Result, VT->getElementType(), + VT->getNumElements(), Index.getExtValue()); + } + + return Success; + } + // C++17's rules require us to evaluate the LHS first, regardless of which // side is the base. for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) { |
