@@ -134,6 +134,85 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
134134 return true ;
135135}
136136
137+ template <typename ResultT>
138+ bool Context::evaluateStringRepr (State &Parent, const Expr *SizeExpr,
139+ const Expr *PtrExpr, ResultT &Result) {
140+ assert (Stk.empty ());
141+ Compiler<EvalEmitter> C (*this , *P, Parent, Stk);
142+
143+ // Evaluate size value.
144+ APValue SizeValue;
145+ if (!evaluateAsRValue (Parent, SizeExpr, SizeValue))
146+ return false ;
147+
148+ if (!SizeValue.isInt ())
149+ return false ;
150+ uint64_t Size = SizeValue.getInt ().getZExtValue ();
151+
152+ auto PtrRes = C.interpretAsPointer (PtrExpr, [&](const Pointer &Ptr) {
153+ if (Size == 0 ) {
154+ if constexpr (std::is_same_v<ResultT, APValue>)
155+ Result = APValue (APValue::UninitArray{}, 0 , 0 );
156+ return true ;
157+ }
158+
159+ if (!Ptr.isLive () || !Ptr.getFieldDesc ()->isPrimitiveArray ())
160+ return false ;
161+
162+ // Must be char.
163+ if (Ptr.getFieldDesc ()->getElemSize () != 1 /* bytes*/ )
164+ return false ;
165+
166+ if (Size > Ptr.getNumElems ()) {
167+ Parent.FFDiag (SizeExpr, diag::note_constexpr_access_past_end) << AK_Read;
168+ Size = Ptr.getNumElems ();
169+ }
170+
171+ if constexpr (std::is_same_v<ResultT, APValue>) {
172+ QualType CharTy = PtrExpr->getType ()->getPointeeType ();
173+ Result = APValue (APValue::UninitArray{}, Size, Size);
174+ for (uint64_t I = 0 ; I != Size; ++I) {
175+ if (std::optional<APValue> ElemVal =
176+ Ptr.atIndex (I).toRValue (*this , CharTy))
177+ Result.getArrayInitializedElt (I) = *ElemVal;
178+ else
179+ return false ;
180+ }
181+ } else {
182+ assert ((std::is_same_v<ResultT, std::string>));
183+ if (Size < Result.max_size ())
184+ Result.resize (Size);
185+ Result.assign (reinterpret_cast <const char *>(Ptr.getRawAddress ()), Size);
186+ }
187+
188+ return true ;
189+ });
190+
191+ if (PtrRes.isInvalid ()) {
192+ C.cleanup ();
193+ Stk.clear ();
194+ return false ;
195+ }
196+
197+ return true ;
198+ }
199+
200+ bool Context::evaluateCharRange (State &Parent, const Expr *SizeExpr,
201+ const Expr *PtrExpr, APValue &Result) {
202+ assert (SizeExpr);
203+ assert (PtrExpr);
204+
205+ return evaluateStringRepr (Parent, SizeExpr, PtrExpr, Result);
206+ }
207+
208+ bool Context::evaluateCharRange (State &Parent, const Expr *SizeExpr,
209+ const Expr *PtrExpr, std::string &Result) {
210+ assert (SizeExpr);
211+ assert (PtrExpr);
212+
213+ return evaluateStringRepr (Parent, SizeExpr, PtrExpr, Result);
214+ }
215+
137216const LangOptions &Context::getLangOpts () const { return Ctx.getLangOpts (); }
138217
139218std::optional<PrimType> Context::classify (QualType T) const {
0 commit comments