@@ -221,6 +221,11 @@ namespace {
221
221
ArraySize = 2;
222
222
MostDerivedLength = I + 1;
223
223
IsArray = true;
224
+ } else if (const auto *VT = Type->getAs<VectorType>()) {
225
+ Type = VT->getElementType();
226
+ ArraySize = VT->getNumElements();
227
+ MostDerivedLength = I + 1;
228
+ IsArray = true;
224
229
} else if (const FieldDecl *FD = getAsField(Path[I])) {
225
230
Type = FD->getType();
226
231
ArraySize = 0;
@@ -437,6 +442,16 @@ namespace {
437
442
MostDerivedArraySize = 2;
438
443
MostDerivedPathLength = Entries.size();
439
444
}
445
+ void addVectorUnchecked(QualType EltTy, uint64_t Size, uint64_t Idx) {
446
+ Entries.push_back(PathEntry::ArrayIndex(Idx));
447
+
448
+ // This is technically a most-derived object, though in practice this
449
+ // is unlikely to matter.
450
+ MostDerivedType = EltTy;
451
+ MostDerivedIsArrayElement = true;
452
+ MostDerivedArraySize = Size;
453
+ MostDerivedPathLength = Entries.size();
454
+ }
440
455
void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
441
456
void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
442
457
const APSInt &N);
@@ -1732,6 +1747,11 @@ namespace {
1732
1747
if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
1733
1748
Designator.addComplexUnchecked(EltTy, Imag);
1734
1749
}
1750
+ void addVectorElement(EvalInfo &Info, const Expr *E, QualType EltTy,
1751
+ uint64_t Size, uint64_t Idx) {
1752
+ if (checkSubobject(Info, E, CSK_VectorElement))
1753
+ Designator.addVectorUnchecked(EltTy, Size, Idx);
1754
+ }
1735
1755
void clearIsNullPointer() {
1736
1756
IsNullPtr = false;
1737
1757
}
@@ -3278,6 +3298,19 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E,
3278
3298
return true;
3279
3299
}
3280
3300
3301
+ static bool HandleLValueVectorElement(EvalInfo &Info, const Expr *E,
3302
+ LValue &LVal, QualType EltTy,
3303
+ uint64_t Size, uint64_t Idx) {
3304
+ if (Idx) {
3305
+ CharUnits SizeOfElement;
3306
+ if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfElement))
3307
+ return false;
3308
+ LVal.Offset += SizeOfElement * Idx;
3309
+ }
3310
+ LVal.addVectorElement(Info, E, EltTy, Size, Idx);
3311
+ return true;
3312
+ }
3313
+
3281
3314
/// Try to evaluate the initializer for a variable declaration.
3282
3315
///
3283
3316
/// \param Info Information about the ongoing evaluation.
@@ -3823,6 +3856,21 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
3823
3856
return handler.found(Index ? O->getComplexFloatImag()
3824
3857
: O->getComplexFloatReal(), ObjType);
3825
3858
}
3859
+ } else if (const auto *VT = ObjType->getAs<VectorType>()) {
3860
+ uint64_t Index = Sub.Entries[I].getAsArrayIndex();
3861
+ if (Index >= VT->getNumElements()) {
3862
+ if (Info.getLangOpts().CPlusPlus11)
3863
+ Info.FFDiag(E, diag::note_constexpr_access_past_end)
3864
+ << handler.AccessKind;
3865
+ else
3866
+ Info.FFDiag(E);
3867
+ return handler.failed();
3868
+ }
3869
+
3870
+ ObjType = VT->getElementType();
3871
+
3872
+ assert(I == N - 1 && "extracting subobject of scalar?");
3873
+ return handler.found(O->getVectorElt(Index), ObjType);
3826
3874
} else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
3827
3875
if (Field->isMutable() &&
3828
3876
!Obj.mayAccessMutableMembers(Info, handler.AccessKind)) {
@@ -8432,6 +8480,7 @@ class LValueExprEvaluator
8432
8480
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
8433
8481
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
8434
8482
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
8483
+ bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
8435
8484
bool VisitUnaryDeref(const UnaryOperator *E);
8436
8485
bool VisitUnaryReal(const UnaryOperator *E);
8437
8486
bool VisitUnaryImag(const UnaryOperator *E);
@@ -8755,15 +8804,63 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
8755
8804
return LValueExprEvaluatorBaseTy::VisitMemberExpr(E);
8756
8805
}
8757
8806
8807
+ bool LValueExprEvaluator::VisitExtVectorElementExpr(
8808
+ const ExtVectorElementExpr *E) {
8809
+ bool Success = true;
8810
+
8811
+ APValue Val;
8812
+ if (!Evaluate(Val, Info, E->getBase())) {
8813
+ if (!Info.noteFailure())
8814
+ return false;
8815
+ Success = false;
8816
+ }
8817
+
8818
+ SmallVector<uint32_t, 4> Indices;
8819
+ E->getEncodedElementAccess(Indices);
8820
+ // FIXME: support accessing more than one element
8821
+ if (Indices.size() > 1)
8822
+ return false;
8823
+
8824
+ if (Success) {
8825
+ Result.setFrom(Info.Ctx, Val);
8826
+ const auto *VT = E->getBase()->getType()->castAs<VectorType>();
8827
+ HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
8828
+ VT->getNumElements(), Indices[0]);
8829
+ }
8830
+
8831
+ return Success;
8832
+ }
8833
+
8758
8834
bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
8759
- // FIXME: Deal with vectors as array subscript bases.
8760
- if (E->getBase()->getType()->isVectorType() ||
8761
- E->getBase()->getType()->isSveVLSBuiltinType())
8835
+ if (E->getBase()->getType()->isSveVLSBuiltinType())
8762
8836
return Error(E);
8763
8837
8764
8838
APSInt Index;
8765
8839
bool Success = true;
8766
8840
8841
+ if (const auto *VT = E->getBase()->getType()->getAs<VectorType>()) {
8842
+ APValue Val;
8843
+ if (!Evaluate(Val, Info, E->getBase())) {
8844
+ if (!Info.noteFailure())
8845
+ return false;
8846
+ Success = false;
8847
+ }
8848
+
8849
+ if (!EvaluateInteger(E->getIdx(), Index, Info)) {
8850
+ if (!Info.noteFailure())
8851
+ return false;
8852
+ Success = false;
8853
+ }
8854
+
8855
+ if (Success) {
8856
+ Result.setFrom(Info.Ctx, Val);
8857
+ HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
8858
+ VT->getNumElements(), Index.getExtValue());
8859
+ }
8860
+
8861
+ return Success;
8862
+ }
8863
+
8767
8864
// C++17's rules require us to evaluate the LHS first, regardless of which
8768
8865
// side is the base.
8769
8866
for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) {
0 commit comments