@@ -2688,9 +2688,11 @@ static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
2688
2688
}
2689
2689
2690
2690
// Expand a string literal into an array of characters.
2691
- static void expandStringLiteral(EvalInfo &Info, const Expr *Lit,
2691
+ //
2692
+ // FIXME: This is inefficient; we should probably introduce something similar
2693
+ // to the LLVM ConstantDataArray to make this cheaper.
2694
+ static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S,
2692
2695
APValue &Result) {
2693
- const StringLiteral *S = cast<StringLiteral>(Lit);
2694
2696
const ConstantArrayType *CAT =
2695
2697
Info.Ctx.getAsConstantArrayType(S->getType());
2696
2698
assert(CAT && "string literal isn't an array");
@@ -2884,18 +2886,6 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
2884
2886
2885
2887
ObjType = CAT->getElementType();
2886
2888
2887
- // An array object is represented as either an Array APValue or as an
2888
- // LValue which refers to a string literal.
2889
- if (O->isLValue()) {
2890
- assert(I == N - 1 && "extracting subobject of character?");
2891
- assert(!O->hasLValuePath() || O->getLValuePath().empty());
2892
- if (handler.AccessKind != AK_Read)
2893
- expandStringLiteral(Info, O->getLValueBase().get<const Expr *>(),
2894
- *O);
2895
- else
2896
- return handler.foundString(*O, ObjType, Index);
2897
- }
2898
-
2899
2889
if (O->getArrayInitializedElts() > Index)
2900
2890
O = &O->getArrayInitializedElt(Index);
2901
2891
else if (handler.AccessKind != AK_Read) {
@@ -3008,11 +2998,6 @@ struct ExtractSubobjectHandler {
3008
2998
Result = APValue(Value);
3009
2999
return true;
3010
3000
}
3011
- bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) {
3012
- Result = APValue(extractStringLiteralCharacter(
3013
- Info, Subobj.getLValueBase().get<const Expr *>(), Character));
3014
- return true;
3015
- }
3016
3001
};
3017
3002
} // end anonymous namespace
3018
3003
@@ -3070,9 +3055,6 @@ struct ModifySubobjectHandler {
3070
3055
Value = NewVal.getFloat();
3071
3056
return true;
3072
3057
}
3073
- bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) {
3074
- llvm_unreachable("shouldn't encounter string elements with ExpandArrays");
3075
- }
3076
3058
};
3077
3059
} // end anonymous namespace
3078
3060
@@ -3386,12 +3368,20 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
3386
3368
CompleteObject LitObj(&Lit, Base->getType(), false);
3387
3369
return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal);
3388
3370
} else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {
3389
- // We represent a string literal array as an lvalue pointing at the
3390
- // corresponding expression, rather than building an array of chars.
3391
- // FIXME: Support ObjCEncodeExpr, MakeStringConstant
3392
- APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
3393
- CompleteObject StrObj(&Str, Base->getType(), false);
3394
- return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal);
3371
+ // Special-case character extraction so we don't have to construct an
3372
+ // APValue for the whole string.
3373
+ assert(LVal.Designator.Entries.size() == 1 &&
3374
+ "Can only read characters from string literals");
3375
+ if (LVal.Designator.isOnePastTheEnd()) {
3376
+ if (Info.getLangOpts().CPlusPlus11)
3377
+ Info.FFDiag(Conv, diag::note_constexpr_access_past_end) << AK_Read;
3378
+ else
3379
+ Info.FFDiag(Conv);
3380
+ return false;
3381
+ }
3382
+ uint64_t CharIndex = LVal.Designator.Entries[0].ArrayIndex;
3383
+ RVal = APValue(extractStringLiteralCharacter(Info, Base, CharIndex));
3384
+ return true;
3395
3385
}
3396
3386
}
3397
3387
@@ -3517,9 +3507,6 @@ struct CompoundAssignSubobjectHandler {
3517
3507
LVal.moveInto(Subobj);
3518
3508
return true;
3519
3509
}
3520
- bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) {
3521
- llvm_unreachable("shouldn't encounter string elements here");
3522
- }
3523
3510
};
3524
3511
} // end anonymous namespace
3525
3512
@@ -3668,9 +3655,6 @@ struct IncDecSubobjectHandler {
3668
3655
LVal.moveInto(Subobj);
3669
3656
return true;
3670
3657
}
3671
- bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) {
3672
- llvm_unreachable("shouldn't encounter string elements here");
3673
- }
3674
3658
};
3675
3659
} // end anonymous namespace
3676
3660
@@ -7150,8 +7134,7 @@ namespace {
7150
7134
: ExprEvaluatorBaseTy(Info), This(This), Result(Result) {}
7151
7135
7152
7136
bool Success(const APValue &V, const Expr *E) {
7153
- assert((V.isArray() || V.isLValue()) &&
7154
- "expected array or string literal");
7137
+ assert(V.isArray() && "expected array");
7155
7138
Result = V;
7156
7139
return true;
7157
7140
}
@@ -7182,6 +7165,10 @@ namespace {
7182
7165
bool VisitCXXConstructExpr(const CXXConstructExpr *E,
7183
7166
const LValue &Subobject,
7184
7167
APValue *Value, QualType Type);
7168
+ bool VisitStringLiteral(const StringLiteral *E) {
7169
+ expandStringLiteral(Info, E, Result);
7170
+ return true;
7171
+ }
7185
7172
};
7186
7173
} // end anonymous namespace
7187
7174
@@ -7214,14 +7201,8 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
7214
7201
7215
7202
// C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]
7216
7203
// an appropriately-typed string literal enclosed in braces.
7217
- if (E->isStringLiteralInit()) {
7218
- LValue LV;
7219
- if (!EvaluateLValue(E->getInit(0), LV, Info))
7220
- return false;
7221
- APValue Val;
7222
- LV.moveInto(Val);
7223
- return Success(Val, E);
7224
- }
7204
+ if (E->isStringLiteralInit())
7205
+ return Visit(E->getInit(0));
7225
7206
7226
7207
bool Success = true;
7227
7208
0 commit comments