Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/AST/APValue.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file implements the APValue class. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #include "clang/AST/APValue.h" | |
14 #include "clang/AST/ASTContext.h" | |
15 #include "clang/AST/CharUnits.h" | |
16 #include "clang/AST/DeclCXX.h" | |
17 #include "clang/AST/Expr.h" | |
18 #include "clang/AST/Type.h" | |
19 #include "llvm/Support/ErrorHandling.h" | |
20 #include "llvm/Support/raw_ostream.h" | |
21 using namespace clang; | |
22 | |
23 /// The identity of a type_info object depends on the canonical unqualified | |
24 /// type only. | |
25 TypeInfoLValue::TypeInfoLValue(const Type *T) | |
26 : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} | |
27 | |
28 void TypeInfoLValue::print(llvm::raw_ostream &Out, | |
29 const PrintingPolicy &Policy) const { | |
30 Out << "typeid("; | |
31 QualType(getType(), 0).print(Out, Policy); | |
32 Out << ")"; | |
33 } | |
34 | |
35 static_assert( | |
36 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <= | |
37 alignof(Type), | |
38 "Type is insufficiently aligned"); | |
39 | |
40 APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) | |
41 : Ptr(P), Local{I, V} {} | |
42 APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) | |
43 : Ptr(P), Local{I, V} {} | |
44 | |
45 APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV, | |
46 QualType Type) { | |
47 LValueBase Base; | |
48 Base.Ptr = LV; | |
49 Base.DynamicAllocType = Type.getAsOpaquePtr(); | |
50 return Base; | |
51 } | |
52 | |
53 APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, | |
54 QualType TypeInfo) { | |
55 LValueBase Base; | |
56 Base.Ptr = LV; | |
57 Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); | |
58 return Base; | |
59 } | |
60 | |
61 unsigned APValue::LValueBase::getCallIndex() const { | |
62 return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 | |
63 : Local.CallIndex; | |
64 } | |
65 | |
66 unsigned APValue::LValueBase::getVersion() const { | |
67 return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 : Local.Version; | |
68 } | |
69 | |
70 QualType APValue::LValueBase::getTypeInfoType() const { | |
71 assert(is<TypeInfoLValue>() && "not a type_info lvalue"); | |
72 return QualType::getFromOpaquePtr(TypeInfoType); | |
73 } | |
74 | |
75 QualType APValue::LValueBase::getDynamicAllocType() const { | |
76 assert(is<DynamicAllocLValue>() && "not a dynamic allocation lvalue"); | |
77 return QualType::getFromOpaquePtr(DynamicAllocType); | |
78 } | |
79 | |
80 namespace clang { | |
81 bool operator==(const APValue::LValueBase &LHS, | |
82 const APValue::LValueBase &RHS) { | |
83 if (LHS.Ptr != RHS.Ptr) | |
84 return false; | |
85 if (LHS.is<TypeInfoLValue>()) | |
86 return true; | |
87 return LHS.Local.CallIndex == RHS.Local.CallIndex && | |
88 LHS.Local.Version == RHS.Local.Version; | |
89 } | |
90 } | |
91 | |
92 namespace { | |
93 struct LVBase { | |
94 APValue::LValueBase Base; | |
95 CharUnits Offset; | |
96 unsigned PathLength; | |
97 bool IsNullPtr : 1; | |
98 bool IsOnePastTheEnd : 1; | |
99 }; | |
100 } | |
101 | |
102 void *APValue::LValueBase::getOpaqueValue() const { | |
103 return Ptr.getOpaqueValue(); | |
104 } | |
105 | |
106 bool APValue::LValueBase::isNull() const { | |
107 return Ptr.isNull(); | |
108 } | |
109 | |
110 APValue::LValueBase::operator bool () const { | |
111 return static_cast<bool>(Ptr); | |
112 } | |
113 | |
114 clang::APValue::LValueBase | |
115 llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { | |
116 return clang::APValue::LValueBase( | |
117 DenseMapInfo<const ValueDecl*>::getEmptyKey()); | |
118 } | |
119 | |
120 clang::APValue::LValueBase | |
121 llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { | |
122 return clang::APValue::LValueBase( | |
123 DenseMapInfo<const ValueDecl*>::getTombstoneKey()); | |
124 } | |
125 | |
126 namespace clang { | |
127 llvm::hash_code hash_value(const APValue::LValueBase &Base) { | |
128 if (Base.is<TypeInfoLValue>() || Base.is<DynamicAllocLValue>()) | |
129 return llvm::hash_value(Base.getOpaqueValue()); | |
130 return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), | |
131 Base.getVersion()); | |
132 } | |
133 } | |
134 | |
135 unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( | |
136 const clang::APValue::LValueBase &Base) { | |
137 return hash_value(Base); | |
138 } | |
139 | |
140 bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( | |
141 const clang::APValue::LValueBase &LHS, | |
142 const clang::APValue::LValueBase &RHS) { | |
143 return LHS == RHS; | |
144 } | |
145 | |
146 struct APValue::LV : LVBase { | |
147 static const unsigned InlinePathSpace = | |
148 (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); | |
149 | |
150 /// Path - The sequence of base classes, fields and array indices to follow to | |
151 /// walk from Base to the subobject. When performing GCC-style folding, there | |
152 /// may not be such a path. | |
153 union { | |
154 LValuePathEntry Path[InlinePathSpace]; | |
155 LValuePathEntry *PathPtr; | |
156 }; | |
157 | |
158 LV() { PathLength = (unsigned)-1; } | |
159 ~LV() { resizePath(0); } | |
160 | |
161 void resizePath(unsigned Length) { | |
162 if (Length == PathLength) | |
163 return; | |
164 if (hasPathPtr()) | |
165 delete [] PathPtr; | |
166 PathLength = Length; | |
167 if (hasPathPtr()) | |
168 PathPtr = new LValuePathEntry[Length]; | |
169 } | |
170 | |
171 bool hasPath() const { return PathLength != (unsigned)-1; } | |
172 bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } | |
173 | |
174 LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } | |
175 const LValuePathEntry *getPath() const { | |
176 return hasPathPtr() ? PathPtr : Path; | |
177 } | |
178 }; | |
179 | |
180 namespace { | |
181 struct MemberPointerBase { | |
182 llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; | |
183 unsigned PathLength; | |
184 }; | |
185 } | |
186 | |
187 struct APValue::MemberPointerData : MemberPointerBase { | |
188 static const unsigned InlinePathSpace = | |
189 (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); | |
190 typedef const CXXRecordDecl *PathElem; | |
191 union { | |
192 PathElem Path[InlinePathSpace]; | |
193 PathElem *PathPtr; | |
194 }; | |
195 | |
196 MemberPointerData() { PathLength = 0; } | |
197 ~MemberPointerData() { resizePath(0); } | |
198 | |
199 void resizePath(unsigned Length) { | |
200 if (Length == PathLength) | |
201 return; | |
202 if (hasPathPtr()) | |
203 delete [] PathPtr; | |
204 PathLength = Length; | |
205 if (hasPathPtr()) | |
206 PathPtr = new PathElem[Length]; | |
207 } | |
208 | |
209 bool hasPathPtr() const { return PathLength > InlinePathSpace; } | |
210 | |
211 PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } | |
212 const PathElem *getPath() const { | |
213 return hasPathPtr() ? PathPtr : Path; | |
214 } | |
215 }; | |
216 | |
217 // FIXME: Reduce the malloc traffic here. | |
218 | |
219 APValue::Arr::Arr(unsigned NumElts, unsigned Size) : | |
220 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), | |
221 NumElts(NumElts), ArrSize(Size) {} | |
222 APValue::Arr::~Arr() { delete [] Elts; } | |
223 | |
224 APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : | |
225 Elts(new APValue[NumBases+NumFields]), | |
226 NumBases(NumBases), NumFields(NumFields) {} | |
227 APValue::StructData::~StructData() { | |
228 delete [] Elts; | |
229 } | |
230 | |
231 APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} | |
232 APValue::UnionData::~UnionData () { | |
233 delete Value; | |
234 } | |
235 | |
236 APValue::APValue(const APValue &RHS) : Kind(None) { | |
237 switch (RHS.getKind()) { | |
238 case None: | |
239 case Indeterminate: | |
240 Kind = RHS.getKind(); | |
241 break; | |
242 case Int: | |
243 MakeInt(); | |
244 setInt(RHS.getInt()); | |
245 break; | |
246 case Float: | |
247 MakeFloat(); | |
248 setFloat(RHS.getFloat()); | |
249 break; | |
250 case FixedPoint: { | |
251 APFixedPoint FXCopy = RHS.getFixedPoint(); | |
252 MakeFixedPoint(std::move(FXCopy)); | |
253 break; | |
254 } | |
255 case Vector: | |
256 MakeVector(); | |
257 setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, | |
258 RHS.getVectorLength()); | |
259 break; | |
260 case ComplexInt: | |
261 MakeComplexInt(); | |
262 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); | |
263 break; | |
264 case ComplexFloat: | |
265 MakeComplexFloat(); | |
266 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); | |
267 break; | |
268 case LValue: | |
269 MakeLValue(); | |
270 if (RHS.hasLValuePath()) | |
271 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), | |
272 RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); | |
273 else | |
274 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), | |
275 RHS.isNullPointer()); | |
276 break; | |
277 case Array: | |
278 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); | |
279 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) | |
280 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); | |
281 if (RHS.hasArrayFiller()) | |
282 getArrayFiller() = RHS.getArrayFiller(); | |
283 break; | |
284 case Struct: | |
285 MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); | |
286 for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) | |
287 getStructBase(I) = RHS.getStructBase(I); | |
288 for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) | |
289 getStructField(I) = RHS.getStructField(I); | |
290 break; | |
291 case Union: | |
292 MakeUnion(); | |
293 setUnion(RHS.getUnionField(), RHS.getUnionValue()); | |
294 break; | |
295 case MemberPointer: | |
296 MakeMemberPointer(RHS.getMemberPointerDecl(), | |
297 RHS.isMemberPointerToDerivedMember(), | |
298 RHS.getMemberPointerPath()); | |
299 break; | |
300 case AddrLabelDiff: | |
301 MakeAddrLabelDiff(); | |
302 setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); | |
303 break; | |
304 } | |
305 } | |
306 | |
307 void APValue::DestroyDataAndMakeUninit() { | |
308 if (Kind == Int) | |
309 ((APSInt*)(char*)Data.buffer)->~APSInt(); | |
310 else if (Kind == Float) | |
311 ((APFloat*)(char*)Data.buffer)->~APFloat(); | |
312 else if (Kind == FixedPoint) | |
313 ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); | |
314 else if (Kind == Vector) | |
315 ((Vec*)(char*)Data.buffer)->~Vec(); | |
316 else if (Kind == ComplexInt) | |
317 ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); | |
318 else if (Kind == ComplexFloat) | |
319 ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); | |
320 else if (Kind == LValue) | |
321 ((LV*)(char*)Data.buffer)->~LV(); | |
322 else if (Kind == Array) | |
323 ((Arr*)(char*)Data.buffer)->~Arr(); | |
324 else if (Kind == Struct) | |
325 ((StructData*)(char*)Data.buffer)->~StructData(); | |
326 else if (Kind == Union) | |
327 ((UnionData*)(char*)Data.buffer)->~UnionData(); | |
328 else if (Kind == MemberPointer) | |
329 ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); | |
330 else if (Kind == AddrLabelDiff) | |
331 ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); | |
332 Kind = None; | |
333 } | |
334 | |
335 bool APValue::needsCleanup() const { | |
336 switch (getKind()) { | |
337 case None: | |
338 case Indeterminate: | |
339 case AddrLabelDiff: | |
340 return false; | |
341 case Struct: | |
342 case Union: | |
343 case Array: | |
344 case Vector: | |
345 return true; | |
346 case Int: | |
347 return getInt().needsCleanup(); | |
348 case Float: | |
349 return getFloat().needsCleanup(); | |
350 case FixedPoint: | |
351 return getFixedPoint().getValue().needsCleanup(); | |
352 case ComplexFloat: | |
353 assert(getComplexFloatImag().needsCleanup() == | |
354 getComplexFloatReal().needsCleanup() && | |
355 "In _Complex float types, real and imaginary values always have the " | |
356 "same size."); | |
357 return getComplexFloatReal().needsCleanup(); | |
358 case ComplexInt: | |
359 assert(getComplexIntImag().needsCleanup() == | |
360 getComplexIntReal().needsCleanup() && | |
361 "In _Complex int types, real and imaginary values must have the " | |
362 "same size."); | |
363 return getComplexIntReal().needsCleanup(); | |
364 case LValue: | |
365 return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); | |
366 case MemberPointer: | |
367 return reinterpret_cast<const MemberPointerData *>(Data.buffer) | |
368 ->hasPathPtr(); | |
369 } | |
370 llvm_unreachable("Unknown APValue kind!"); | |
371 } | |
372 | |
373 void APValue::swap(APValue &RHS) { | |
374 std::swap(Kind, RHS.Kind); | |
375 char TmpData[DataSize]; | |
376 memcpy(TmpData, Data.buffer, DataSize); | |
377 memcpy(Data.buffer, RHS.Data.buffer, DataSize); | |
378 memcpy(RHS.Data.buffer, TmpData, DataSize); | |
379 } | |
380 | |
381 LLVM_DUMP_METHOD void APValue::dump() const { | |
382 dump(llvm::errs()); | |
383 llvm::errs() << '\n'; | |
384 } | |
385 | |
386 static double GetApproxValue(const llvm::APFloat &F) { | |
387 llvm::APFloat V = F; | |
388 bool ignored; | |
389 V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, | |
390 &ignored); | |
391 return V.convertToDouble(); | |
392 } | |
393 | |
394 void APValue::dump(raw_ostream &OS) const { | |
395 switch (getKind()) { | |
396 case None: | |
397 OS << "None"; | |
398 return; | |
399 case Indeterminate: | |
400 OS << "Indeterminate"; | |
401 return; | |
402 case Int: | |
403 OS << "Int: " << getInt(); | |
404 return; | |
405 case Float: | |
406 OS << "Float: " << GetApproxValue(getFloat()); | |
407 return; | |
408 case FixedPoint: | |
409 OS << "FixedPoint : " << getFixedPoint(); | |
410 return; | |
411 case Vector: | |
412 OS << "Vector: "; | |
413 getVectorElt(0).dump(OS); | |
414 for (unsigned i = 1; i != getVectorLength(); ++i) { | |
415 OS << ", "; | |
416 getVectorElt(i).dump(OS); | |
417 } | |
418 return; | |
419 case ComplexInt: | |
420 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); | |
421 return; | |
422 case ComplexFloat: | |
423 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) | |
424 << ", " << GetApproxValue(getComplexFloatImag()); | |
425 return; | |
426 case LValue: | |
427 OS << "LValue: <todo>"; | |
428 return; | |
429 case Array: | |
430 OS << "Array: "; | |
431 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { | |
432 getArrayInitializedElt(I).dump(OS); | |
433 if (I != getArraySize() - 1) OS << ", "; | |
434 } | |
435 if (hasArrayFiller()) { | |
436 OS << getArraySize() - getArrayInitializedElts() << " x "; | |
437 getArrayFiller().dump(OS); | |
438 } | |
439 return; | |
440 case Struct: | |
441 OS << "Struct "; | |
442 if (unsigned N = getStructNumBases()) { | |
443 OS << " bases: "; | |
444 getStructBase(0).dump(OS); | |
445 for (unsigned I = 1; I != N; ++I) { | |
446 OS << ", "; | |
447 getStructBase(I).dump(OS); | |
448 } | |
449 } | |
450 if (unsigned N = getStructNumFields()) { | |
451 OS << " fields: "; | |
452 getStructField(0).dump(OS); | |
453 for (unsigned I = 1; I != N; ++I) { | |
454 OS << ", "; | |
455 getStructField(I).dump(OS); | |
456 } | |
457 } | |
458 return; | |
459 case Union: | |
460 OS << "Union: "; | |
461 getUnionValue().dump(OS); | |
462 return; | |
463 case MemberPointer: | |
464 OS << "MemberPointer: <todo>"; | |
465 return; | |
466 case AddrLabelDiff: | |
467 OS << "AddrLabelDiff: <todo>"; | |
468 return; | |
469 } | |
470 llvm_unreachable("Unknown APValue kind!"); | |
471 } | |
472 | |
473 void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, | |
474 QualType Ty) const { | |
475 switch (getKind()) { | |
476 case APValue::None: | |
477 Out << "<out of lifetime>"; | |
478 return; | |
479 case APValue::Indeterminate: | |
480 Out << "<uninitialized>"; | |
481 return; | |
482 case APValue::Int: | |
483 if (Ty->isBooleanType()) | |
484 Out << (getInt().getBoolValue() ? "true" : "false"); | |
485 else | |
486 Out << getInt(); | |
487 return; | |
488 case APValue::Float: | |
489 Out << GetApproxValue(getFloat()); | |
490 return; | |
491 case APValue::FixedPoint: | |
492 Out << getFixedPoint(); | |
493 return; | |
494 case APValue::Vector: { | |
495 Out << '{'; | |
496 QualType ElemTy = Ty->castAs<VectorType>()->getElementType(); | |
497 getVectorElt(0).printPretty(Out, Ctx, ElemTy); | |
498 for (unsigned i = 1; i != getVectorLength(); ++i) { | |
499 Out << ", "; | |
500 getVectorElt(i).printPretty(Out, Ctx, ElemTy); | |
501 } | |
502 Out << '}'; | |
503 return; | |
504 } | |
505 case APValue::ComplexInt: | |
506 Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; | |
507 return; | |
508 case APValue::ComplexFloat: | |
509 Out << GetApproxValue(getComplexFloatReal()) << "+" | |
510 << GetApproxValue(getComplexFloatImag()) << "i"; | |
511 return; | |
512 case APValue::LValue: { | |
513 bool IsReference = Ty->isReferenceType(); | |
514 QualType InnerTy | |
515 = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); | |
516 if (InnerTy.isNull()) | |
517 InnerTy = Ty; | |
518 | |
519 LValueBase Base = getLValueBase(); | |
520 if (!Base) { | |
521 if (isNullPointer()) { | |
522 Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); | |
523 } else if (IsReference) { | |
524 Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" | |
525 << getLValueOffset().getQuantity(); | |
526 } else { | |
527 Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" | |
528 << getLValueOffset().getQuantity(); | |
529 } | |
530 return; | |
531 } | |
532 | |
533 if (!hasLValuePath()) { | |
534 // No lvalue path: just print the offset. | |
535 CharUnits O = getLValueOffset(); | |
536 CharUnits S = Ctx.getTypeSizeInChars(InnerTy); | |
537 if (!O.isZero()) { | |
538 if (IsReference) | |
539 Out << "*("; | |
540 if (O % S) { | |
541 Out << "(char*)"; | |
542 S = CharUnits::One(); | |
543 } | |
544 Out << '&'; | |
545 } else if (!IsReference) { | |
546 Out << '&'; | |
547 } | |
548 | |
549 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) | |
550 Out << *VD; | |
551 else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { | |
552 TI.print(Out, Ctx.getPrintingPolicy()); | |
553 } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) { | |
554 Out << "{*new " | |
555 << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" | |
556 << DA.getIndex() << "}"; | |
557 } else { | |
558 assert(Base.get<const Expr *>() != nullptr && | |
559 "Expecting non-null Expr"); | |
560 Base.get<const Expr*>()->printPretty(Out, nullptr, | |
561 Ctx.getPrintingPolicy()); | |
562 } | |
563 | |
564 if (!O.isZero()) { | |
565 Out << " + " << (O / S); | |
566 if (IsReference) | |
567 Out << ')'; | |
568 } | |
569 return; | |
570 } | |
571 | |
572 // We have an lvalue path. Print it out nicely. | |
573 if (!IsReference) | |
574 Out << '&'; | |
575 else if (isLValueOnePastTheEnd()) | |
576 Out << "*(&"; | |
577 | |
578 QualType ElemTy; | |
579 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { | |
580 Out << *VD; | |
581 ElemTy = VD->getType(); | |
582 } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { | |
583 TI.print(Out, Ctx.getPrintingPolicy()); | |
584 ElemTy = Base.getTypeInfoType(); | |
585 } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) { | |
586 Out << "{*new " | |
587 << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" | |
588 << DA.getIndex() << "}"; | |
589 ElemTy = Base.getDynamicAllocType(); | |
590 } else { | |
591 const Expr *E = Base.get<const Expr*>(); | |
592 assert(E != nullptr && "Expecting non-null Expr"); | |
593 E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); | |
594 // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue | |
595 // adjustment. | |
596 ElemTy = E->getType(); | |
597 } | |
598 | |
599 ArrayRef<LValuePathEntry> Path = getLValuePath(); | |
600 const CXXRecordDecl *CastToBase = nullptr; | |
601 for (unsigned I = 0, N = Path.size(); I != N; ++I) { | |
602 if (ElemTy->getAs<RecordType>()) { | |
603 // The lvalue refers to a class type, so the next path entry is a base | |
604 // or member. | |
605 const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); | |
606 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { | |
607 CastToBase = RD; | |
608 ElemTy = Ctx.getRecordType(RD); | |
609 } else { | |
610 const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); | |
611 Out << "."; | |
612 if (CastToBase) | |
613 Out << *CastToBase << "::"; | |
614 Out << *VD; | |
615 ElemTy = VD->getType(); | |
616 } | |
617 } else { | |
618 // The lvalue must refer to an array. | |
619 Out << '[' << Path[I].getAsArrayIndex() << ']'; | |
620 ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); | |
621 } | |
622 } | |
623 | |
624 // Handle formatting of one-past-the-end lvalues. | |
625 if (isLValueOnePastTheEnd()) { | |
626 // FIXME: If CastToBase is non-0, we should prefix the output with | |
627 // "(CastToBase*)". | |
628 Out << " + 1"; | |
629 if (IsReference) | |
630 Out << ')'; | |
631 } | |
632 return; | |
633 } | |
634 case APValue::Array: { | |
635 const ArrayType *AT = Ctx.getAsArrayType(Ty); | |
636 QualType ElemTy = AT->getElementType(); | |
637 Out << '{'; | |
638 if (unsigned N = getArrayInitializedElts()) { | |
639 getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); | |
640 for (unsigned I = 1; I != N; ++I) { | |
641 Out << ", "; | |
642 if (I == 10) { | |
643 // Avoid printing out the entire contents of large arrays. | |
644 Out << "..."; | |
645 break; | |
646 } | |
647 getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); | |
648 } | |
649 } | |
650 Out << '}'; | |
651 return; | |
652 } | |
653 case APValue::Struct: { | |
654 Out << '{'; | |
655 const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl(); | |
656 bool First = true; | |
657 if (unsigned N = getStructNumBases()) { | |
658 const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); | |
659 CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); | |
660 for (unsigned I = 0; I != N; ++I, ++BI) { | |
661 assert(BI != CD->bases_end()); | |
662 if (!First) | |
663 Out << ", "; | |
664 getStructBase(I).printPretty(Out, Ctx, BI->getType()); | |
665 First = false; | |
666 } | |
667 } | |
668 for (const auto *FI : RD->fields()) { | |
669 if (!First) | |
670 Out << ", "; | |
671 if (FI->isUnnamedBitfield()) continue; | |
672 getStructField(FI->getFieldIndex()). | |
673 printPretty(Out, Ctx, FI->getType()); | |
674 First = false; | |
675 } | |
676 Out << '}'; | |
677 return; | |
678 } | |
679 case APValue::Union: | |
680 Out << '{'; | |
681 if (const FieldDecl *FD = getUnionField()) { | |
682 Out << "." << *FD << " = "; | |
683 getUnionValue().printPretty(Out, Ctx, FD->getType()); | |
684 } | |
685 Out << '}'; | |
686 return; | |
687 case APValue::MemberPointer: | |
688 // FIXME: This is not enough to unambiguously identify the member in a | |
689 // multiple-inheritance scenario. | |
690 if (const ValueDecl *VD = getMemberPointerDecl()) { | |
691 Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; | |
692 return; | |
693 } | |
694 Out << "0"; | |
695 return; | |
696 case APValue::AddrLabelDiff: | |
697 Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); | |
698 Out << " - "; | |
699 Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); | |
700 return; | |
701 } | |
702 llvm_unreachable("Unknown APValue kind!"); | |
703 } | |
704 | |
705 std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const { | |
706 std::string Result; | |
707 llvm::raw_string_ostream Out(Result); | |
708 printPretty(Out, Ctx, Ty); | |
709 Out.flush(); | |
710 return Result; | |
711 } | |
712 | |
713 bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, | |
714 const ASTContext &Ctx) const { | |
715 if (isInt()) { | |
716 Result = getInt(); | |
717 return true; | |
718 } | |
719 | |
720 if (isLValue() && isNullPointer()) { | |
721 Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); | |
722 return true; | |
723 } | |
724 | |
725 if (isLValue() && !getLValueBase()) { | |
726 Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); | |
727 return true; | |
728 } | |
729 | |
730 return false; | |
731 } | |
732 | |
733 const APValue::LValueBase APValue::getLValueBase() const { | |
734 assert(isLValue() && "Invalid accessor"); | |
735 return ((const LV*)(const void*)Data.buffer)->Base; | |
736 } | |
737 | |
738 bool APValue::isLValueOnePastTheEnd() const { | |
739 assert(isLValue() && "Invalid accessor"); | |
740 return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; | |
741 } | |
742 | |
743 CharUnits &APValue::getLValueOffset() { | |
744 assert(isLValue() && "Invalid accessor"); | |
745 return ((LV*)(void*)Data.buffer)->Offset; | |
746 } | |
747 | |
748 bool APValue::hasLValuePath() const { | |
749 assert(isLValue() && "Invalid accessor"); | |
750 return ((const LV*)(const char*)Data.buffer)->hasPath(); | |
751 } | |
752 | |
753 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { | |
754 assert(isLValue() && hasLValuePath() && "Invalid accessor"); | |
755 const LV &LVal = *((const LV*)(const char*)Data.buffer); | |
756 return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); | |
757 } | |
758 | |
759 unsigned APValue::getLValueCallIndex() const { | |
760 assert(isLValue() && "Invalid accessor"); | |
761 return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); | |
762 } | |
763 | |
764 unsigned APValue::getLValueVersion() const { | |
765 assert(isLValue() && "Invalid accessor"); | |
766 return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); | |
767 } | |
768 | |
769 bool APValue::isNullPointer() const { | |
770 assert(isLValue() && "Invalid usage"); | |
771 return ((const LV*)(const char*)Data.buffer)->IsNullPtr; | |
772 } | |
773 | |
774 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, | |
775 bool IsNullPtr) { | |
776 assert(isLValue() && "Invalid accessor"); | |
777 LV &LVal = *((LV*)(char*)Data.buffer); | |
778 LVal.Base = B; | |
779 LVal.IsOnePastTheEnd = false; | |
780 LVal.Offset = O; | |
781 LVal.resizePath((unsigned)-1); | |
782 LVal.IsNullPtr = IsNullPtr; | |
783 } | |
784 | |
785 void APValue::setLValue(LValueBase B, const CharUnits &O, | |
786 ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, | |
787 bool IsNullPtr) { | |
788 assert(isLValue() && "Invalid accessor"); | |
789 LV &LVal = *((LV*)(char*)Data.buffer); | |
790 LVal.Base = B; | |
791 LVal.IsOnePastTheEnd = IsOnePastTheEnd; | |
792 LVal.Offset = O; | |
793 LVal.resizePath(Path.size()); | |
794 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); | |
795 LVal.IsNullPtr = IsNullPtr; | |
796 } | |
797 | |
798 const ValueDecl *APValue::getMemberPointerDecl() const { | |
799 assert(isMemberPointer() && "Invalid accessor"); | |
800 const MemberPointerData &MPD = | |
801 *((const MemberPointerData *)(const char *)Data.buffer); | |
802 return MPD.MemberAndIsDerivedMember.getPointer(); | |
803 } | |
804 | |
805 bool APValue::isMemberPointerToDerivedMember() const { | |
806 assert(isMemberPointer() && "Invalid accessor"); | |
807 const MemberPointerData &MPD = | |
808 *((const MemberPointerData *)(const char *)Data.buffer); | |
809 return MPD.MemberAndIsDerivedMember.getInt(); | |
810 } | |
811 | |
812 ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { | |
813 assert(isMemberPointer() && "Invalid accessor"); | |
814 const MemberPointerData &MPD = | |
815 *((const MemberPointerData *)(const char *)Data.buffer); | |
816 return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); | |
817 } | |
818 | |
819 void APValue::MakeLValue() { | |
820 assert(isAbsent() && "Bad state change"); | |
821 static_assert(sizeof(LV) <= DataSize, "LV too big"); | |
822 new ((void*)(char*)Data.buffer) LV(); | |
823 Kind = LValue; | |
824 } | |
825 | |
826 void APValue::MakeArray(unsigned InitElts, unsigned Size) { | |
827 assert(isAbsent() && "Bad state change"); | |
828 new ((void*)(char*)Data.buffer) Arr(InitElts, Size); | |
829 Kind = Array; | |
830 } | |
831 | |
832 void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, | |
833 ArrayRef<const CXXRecordDecl*> Path) { | |
834 assert(isAbsent() && "Bad state change"); | |
835 MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; | |
836 Kind = MemberPointer; | |
837 MPD->MemberAndIsDerivedMember.setPointer(Member); | |
838 MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); | |
839 MPD->resizePath(Path.size()); | |
840 memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); | |
841 } |