1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
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 | namespace { |
24 | struct LVBase { |
25 | APValue::LValueBase Base; |
26 | CharUnits Offset; |
27 | unsigned PathLength; |
28 | bool IsNullPtr : 1; |
29 | bool IsOnePastTheEnd : 1; |
30 | }; |
31 | } |
32 | |
33 | void *APValue::LValueBase::getOpaqueValue() const { |
34 | return Ptr.getOpaqueValue(); |
35 | } |
36 | |
37 | bool APValue::LValueBase::isNull() const { |
38 | return Ptr.isNull(); |
39 | } |
40 | |
41 | APValue::LValueBase::operator bool () const { |
42 | return static_cast<bool>(Ptr); |
43 | } |
44 | |
45 | clang::APValue::LValueBase |
46 | llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { |
47 | return clang::APValue::LValueBase( |
48 | DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(), |
49 | DenseMapInfo<unsigned>::getEmptyKey(), |
50 | DenseMapInfo<unsigned>::getEmptyKey()); |
51 | } |
52 | |
53 | clang::APValue::LValueBase |
54 | llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { |
55 | return clang::APValue::LValueBase( |
56 | DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(), |
57 | DenseMapInfo<unsigned>::getTombstoneKey(), |
58 | DenseMapInfo<unsigned>::getTombstoneKey()); |
59 | } |
60 | |
61 | unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( |
62 | const clang::APValue::LValueBase &Base) { |
63 | llvm::FoldingSetNodeID ID; |
64 | ID.AddPointer(Base.getOpaqueValue()); |
65 | ID.AddInteger(Base.getCallIndex()); |
66 | ID.AddInteger(Base.getVersion()); |
67 | return ID.ComputeHash(); |
68 | } |
69 | |
70 | bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( |
71 | const clang::APValue::LValueBase &LHS, |
72 | const clang::APValue::LValueBase &RHS) { |
73 | return LHS == RHS; |
74 | } |
75 | |
76 | struct APValue::LV : LVBase { |
77 | static const unsigned InlinePathSpace = |
78 | (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); |
79 | |
80 | |
81 | |
82 | |
83 | union { |
84 | LValuePathEntry Path[InlinePathSpace]; |
85 | LValuePathEntry *PathPtr; |
86 | }; |
87 | |
88 | LV() { PathLength = (unsigned)-1; } |
89 | ~LV() { resizePath(0); } |
90 | |
91 | void resizePath(unsigned Length) { |
92 | if (Length == PathLength) |
93 | return; |
94 | if (hasPathPtr()) |
95 | delete [] PathPtr; |
96 | PathLength = Length; |
97 | if (hasPathPtr()) |
98 | PathPtr = new LValuePathEntry[Length]; |
99 | } |
100 | |
101 | bool hasPath() const { return PathLength != (unsigned)-1; } |
102 | bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } |
103 | |
104 | LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } |
105 | const LValuePathEntry *getPath() const { |
106 | return hasPathPtr() ? PathPtr : Path; |
107 | } |
108 | }; |
109 | |
110 | namespace { |
111 | struct MemberPointerBase { |
112 | llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; |
113 | unsigned PathLength; |
114 | }; |
115 | } |
116 | |
117 | struct APValue::MemberPointerData : MemberPointerBase { |
118 | static const unsigned InlinePathSpace = |
119 | (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); |
120 | typedef const CXXRecordDecl *PathElem; |
121 | union { |
122 | PathElem Path[InlinePathSpace]; |
123 | PathElem *PathPtr; |
124 | }; |
125 | |
126 | MemberPointerData() { PathLength = 0; } |
127 | ~MemberPointerData() { resizePath(0); } |
128 | |
129 | void resizePath(unsigned Length) { |
130 | if (Length == PathLength) |
131 | return; |
132 | if (hasPathPtr()) |
133 | delete [] PathPtr; |
134 | PathLength = Length; |
135 | if (hasPathPtr()) |
136 | PathPtr = new PathElem[Length]; |
137 | } |
138 | |
139 | bool hasPathPtr() const { return PathLength > InlinePathSpace; } |
140 | |
141 | PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } |
142 | const PathElem *getPath() const { |
143 | return hasPathPtr() ? PathPtr : Path; |
144 | } |
145 | }; |
146 | |
147 | |
148 | |
149 | APValue::Arr::Arr(unsigned NumElts, unsigned Size) : |
150 | Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), |
151 | NumElts(NumElts), ArrSize(Size) {} |
152 | APValue::Arr::~Arr() { delete [] Elts; } |
153 | |
154 | APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : |
155 | Elts(new APValue[NumBases+NumFields]), |
156 | NumBases(NumBases), NumFields(NumFields) {} |
157 | APValue::StructData::~StructData() { |
158 | delete [] Elts; |
159 | } |
160 | |
161 | APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} |
162 | APValue::UnionData::~UnionData () { |
163 | delete Value; |
164 | } |
165 | |
166 | APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { |
167 | switch (RHS.getKind()) { |
168 | case Uninitialized: |
169 | break; |
170 | case Int: |
171 | MakeInt(); |
172 | setInt(RHS.getInt()); |
173 | break; |
174 | case Float: |
175 | MakeFloat(); |
176 | setFloat(RHS.getFloat()); |
177 | break; |
178 | case FixedPoint: { |
179 | APFixedPoint FXCopy = RHS.getFixedPoint(); |
180 | MakeFixedPoint(std::move(FXCopy)); |
181 | break; |
182 | } |
183 | case Vector: |
184 | MakeVector(); |
185 | setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, |
186 | RHS.getVectorLength()); |
187 | break; |
188 | case ComplexInt: |
189 | MakeComplexInt(); |
190 | setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); |
191 | break; |
192 | case ComplexFloat: |
193 | MakeComplexFloat(); |
194 | setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); |
195 | break; |
196 | case LValue: |
197 | MakeLValue(); |
198 | if (RHS.hasLValuePath()) |
199 | setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), |
200 | RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); |
201 | else |
202 | setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), |
203 | RHS.isNullPointer()); |
204 | break; |
205 | case Array: |
206 | MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); |
207 | for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) |
208 | getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); |
209 | if (RHS.hasArrayFiller()) |
210 | getArrayFiller() = RHS.getArrayFiller(); |
211 | break; |
212 | case Struct: |
213 | MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); |
214 | for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) |
215 | getStructBase(I) = RHS.getStructBase(I); |
216 | for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) |
217 | getStructField(I) = RHS.getStructField(I); |
218 | break; |
219 | case Union: |
220 | MakeUnion(); |
221 | setUnion(RHS.getUnionField(), RHS.getUnionValue()); |
222 | break; |
223 | case MemberPointer: |
224 | MakeMemberPointer(RHS.getMemberPointerDecl(), |
225 | RHS.isMemberPointerToDerivedMember(), |
226 | RHS.getMemberPointerPath()); |
227 | break; |
228 | case AddrLabelDiff: |
229 | MakeAddrLabelDiff(); |
230 | setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); |
231 | break; |
232 | } |
233 | } |
234 | |
235 | void APValue::DestroyDataAndMakeUninit() { |
236 | if (Kind == Int) |
237 | ((APSInt*)(char*)Data.buffer)->~APSInt(); |
238 | else if (Kind == Float) |
239 | ((APFloat*)(char*)Data.buffer)->~APFloat(); |
240 | else if (Kind == FixedPoint) |
241 | ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); |
242 | else if (Kind == Vector) |
243 | ((Vec*)(char*)Data.buffer)->~Vec(); |
244 | else if (Kind == ComplexInt) |
245 | ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); |
246 | else if (Kind == ComplexFloat) |
247 | ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); |
248 | else if (Kind == LValue) |
249 | ((LV*)(char*)Data.buffer)->~LV(); |
250 | else if (Kind == Array) |
251 | ((Arr*)(char*)Data.buffer)->~Arr(); |
252 | else if (Kind == Struct) |
253 | ((StructData*)(char*)Data.buffer)->~StructData(); |
254 | else if (Kind == Union) |
255 | ((UnionData*)(char*)Data.buffer)->~UnionData(); |
256 | else if (Kind == MemberPointer) |
257 | ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); |
258 | else if (Kind == AddrLabelDiff) |
259 | ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); |
260 | Kind = Uninitialized; |
261 | } |
262 | |
263 | bool APValue::needsCleanup() const { |
264 | switch (getKind()) { |
265 | case Uninitialized: |
266 | case AddrLabelDiff: |
267 | return false; |
268 | case Struct: |
269 | case Union: |
270 | case Array: |
271 | case Vector: |
272 | return true; |
273 | case Int: |
274 | return getInt().needsCleanup(); |
275 | case Float: |
276 | return getFloat().needsCleanup(); |
277 | case FixedPoint: |
278 | return getFixedPoint().getValue().needsCleanup(); |
279 | case ComplexFloat: |
280 | (0) . __assert_fail ("getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && \"In _Complex float types, real and imaginary values always have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 283, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getComplexFloatImag().needsCleanup() == |
281 | (0) . __assert_fail ("getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && \"In _Complex float types, real and imaginary values always have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 283, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> getComplexFloatReal().needsCleanup() && |
282 | (0) . __assert_fail ("getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && \"In _Complex float types, real and imaginary values always have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 283, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "In _Complex float types, real and imaginary values always have the " |
283 | (0) . __assert_fail ("getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && \"In _Complex float types, real and imaginary values always have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 283, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "same size."); |
284 | return getComplexFloatReal().needsCleanup(); |
285 | case ComplexInt: |
286 | (0) . __assert_fail ("getComplexIntImag().needsCleanup() == getComplexIntReal().needsCleanup() && \"In _Complex int types, real and imaginary values must have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 289, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getComplexIntImag().needsCleanup() == |
287 | (0) . __assert_fail ("getComplexIntImag().needsCleanup() == getComplexIntReal().needsCleanup() && \"In _Complex int types, real and imaginary values must have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 289, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> getComplexIntReal().needsCleanup() && |
288 | (0) . __assert_fail ("getComplexIntImag().needsCleanup() == getComplexIntReal().needsCleanup() && \"In _Complex int types, real and imaginary values must have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 289, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "In _Complex int types, real and imaginary values must have the " |
289 | (0) . __assert_fail ("getComplexIntImag().needsCleanup() == getComplexIntReal().needsCleanup() && \"In _Complex int types, real and imaginary values must have the \" \"same size.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 289, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "same size."); |
290 | return getComplexIntReal().needsCleanup(); |
291 | case LValue: |
292 | return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); |
293 | case MemberPointer: |
294 | return reinterpret_cast<const MemberPointerData *>(Data.buffer) |
295 | ->hasPathPtr(); |
296 | } |
297 | llvm_unreachable("Unknown APValue kind!"); |
298 | } |
299 | |
300 | void APValue::swap(APValue &RHS) { |
301 | std::swap(Kind, RHS.Kind); |
302 | char TmpData[DataSize]; |
303 | memcpy(TmpData, Data.buffer, DataSize); |
304 | memcpy(Data.buffer, RHS.Data.buffer, DataSize); |
305 | memcpy(RHS.Data.buffer, TmpData, DataSize); |
306 | } |
307 | |
308 | LLVM_DUMP_METHOD void APValue::dump() const { |
309 | dump(llvm::errs()); |
310 | llvm::errs() << '\n'; |
311 | } |
312 | |
313 | static double GetApproxValue(const llvm::APFloat &F) { |
314 | llvm::APFloat V = F; |
315 | bool ignored; |
316 | V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, |
317 | &ignored); |
318 | return V.convertToDouble(); |
319 | } |
320 | |
321 | void APValue::dump(raw_ostream &OS) const { |
322 | switch (getKind()) { |
323 | case Uninitialized: |
324 | OS << "Uninitialized"; |
325 | return; |
326 | case Int: |
327 | OS << "Int: " << getInt(); |
328 | return; |
329 | case Float: |
330 | OS << "Float: " << GetApproxValue(getFloat()); |
331 | return; |
332 | case FixedPoint: |
333 | OS << "FixedPoint : " << getFixedPoint(); |
334 | return; |
335 | case Vector: |
336 | OS << "Vector: "; |
337 | getVectorElt(0).dump(OS); |
338 | for (unsigned i = 1; i != getVectorLength(); ++i) { |
339 | OS << ", "; |
340 | getVectorElt(i).dump(OS); |
341 | } |
342 | return; |
343 | case ComplexInt: |
344 | OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); |
345 | return; |
346 | case ComplexFloat: |
347 | OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) |
348 | << ", " << GetApproxValue(getComplexFloatImag()); |
349 | return; |
350 | case LValue: |
351 | OS << "LValue: <todo>"; |
352 | return; |
353 | case Array: |
354 | OS << "Array: "; |
355 | for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { |
356 | getArrayInitializedElt(I).dump(OS); |
357 | if (I != getArraySize() - 1) OS << ", "; |
358 | } |
359 | if (hasArrayFiller()) { |
360 | OS << getArraySize() - getArrayInitializedElts() << " x "; |
361 | getArrayFiller().dump(OS); |
362 | } |
363 | return; |
364 | case Struct: |
365 | OS << "Struct "; |
366 | if (unsigned N = getStructNumBases()) { |
367 | OS << " bases: "; |
368 | getStructBase(0).dump(OS); |
369 | for (unsigned I = 1; I != N; ++I) { |
370 | OS << ", "; |
371 | getStructBase(I).dump(OS); |
372 | } |
373 | } |
374 | if (unsigned N = getStructNumFields()) { |
375 | OS << " fields: "; |
376 | getStructField(0).dump(OS); |
377 | for (unsigned I = 1; I != N; ++I) { |
378 | OS << ", "; |
379 | getStructField(I).dump(OS); |
380 | } |
381 | } |
382 | return; |
383 | case Union: |
384 | OS << "Union: "; |
385 | getUnionValue().dump(OS); |
386 | return; |
387 | case MemberPointer: |
388 | OS << "MemberPointer: <todo>"; |
389 | return; |
390 | case AddrLabelDiff: |
391 | OS << "AddrLabelDiff: <todo>"; |
392 | return; |
393 | } |
394 | llvm_unreachable("Unknown APValue kind!"); |
395 | } |
396 | |
397 | void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ |
398 | switch (getKind()) { |
399 | case APValue::Uninitialized: |
400 | Out << "<uninitialized>"; |
401 | return; |
402 | case APValue::Int: |
403 | if (Ty->isBooleanType()) |
404 | Out << (getInt().getBoolValue() ? "true" : "false"); |
405 | else |
406 | Out << getInt(); |
407 | return; |
408 | case APValue::Float: |
409 | Out << GetApproxValue(getFloat()); |
410 | return; |
411 | case APValue::FixedPoint: |
412 | Out << getFixedPoint(); |
413 | return; |
414 | case APValue::Vector: { |
415 | Out << '{'; |
416 | QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); |
417 | getVectorElt(0).printPretty(Out, Ctx, ElemTy); |
418 | for (unsigned i = 1; i != getVectorLength(); ++i) { |
419 | Out << ", "; |
420 | getVectorElt(i).printPretty(Out, Ctx, ElemTy); |
421 | } |
422 | Out << '}'; |
423 | return; |
424 | } |
425 | case APValue::ComplexInt: |
426 | Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; |
427 | return; |
428 | case APValue::ComplexFloat: |
429 | Out << GetApproxValue(getComplexFloatReal()) << "+" |
430 | << GetApproxValue(getComplexFloatImag()) << "i"; |
431 | return; |
432 | case APValue::LValue: { |
433 | bool IsReference = Ty->isReferenceType(); |
434 | QualType InnerTy |
435 | = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); |
436 | if (InnerTy.isNull()) |
437 | InnerTy = Ty; |
438 | |
439 | LValueBase Base = getLValueBase(); |
440 | if (!Base) { |
441 | if (isNullPointer()) { |
442 | Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); |
443 | } else if (IsReference) { |
444 | Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" |
445 | << getLValueOffset().getQuantity(); |
446 | } else { |
447 | Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" |
448 | << getLValueOffset().getQuantity(); |
449 | } |
450 | return; |
451 | } |
452 | |
453 | if (!hasLValuePath()) { |
454 | |
455 | CharUnits O = getLValueOffset(); |
456 | CharUnits S = Ctx.getTypeSizeInChars(InnerTy); |
457 | if (!O.isZero()) { |
458 | if (IsReference) |
459 | Out << "*("; |
460 | if (O % S) { |
461 | Out << "(char*)"; |
462 | S = CharUnits::One(); |
463 | } |
464 | Out << '&'; |
465 | } else if (!IsReference) |
466 | Out << '&'; |
467 | |
468 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) |
469 | Out << *VD; |
470 | else { |
471 | (0) . __assert_fail ("Base.get() != nullptr && \"Expecting non-null Expr\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 472, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Base.get<const Expr *>() != nullptr && |
472 | (0) . __assert_fail ("Base.get() != nullptr && \"Expecting non-null Expr\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 472, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Expecting non-null Expr"); |
473 | Base.get<const Expr*>()->printPretty(Out, nullptr, |
474 | Ctx.getPrintingPolicy()); |
475 | } |
476 | |
477 | if (!O.isZero()) { |
478 | Out << " + " << (O / S); |
479 | if (IsReference) |
480 | Out << ')'; |
481 | } |
482 | return; |
483 | } |
484 | |
485 | |
486 | if (!IsReference) |
487 | Out << '&'; |
488 | else if (isLValueOnePastTheEnd()) |
489 | Out << "*(&"; |
490 | |
491 | QualType ElemTy; |
492 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { |
493 | Out << *VD; |
494 | ElemTy = VD->getType(); |
495 | } else { |
496 | const Expr *E = Base.get<const Expr*>(); |
497 | (0) . __assert_fail ("E != nullptr && \"Expecting non-null Expr\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 497, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E != nullptr && "Expecting non-null Expr"); |
498 | E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); |
499 | ElemTy = E->getType(); |
500 | } |
501 | |
502 | ArrayRef<LValuePathEntry> Path = getLValuePath(); |
503 | const CXXRecordDecl *CastToBase = nullptr; |
504 | for (unsigned I = 0, N = Path.size(); I != N; ++I) { |
505 | if (ElemTy->getAs<RecordType>()) { |
506 | |
507 | |
508 | const Decl *BaseOrMember = |
509 | BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer(); |
510 | if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { |
511 | CastToBase = RD; |
512 | ElemTy = Ctx.getRecordType(RD); |
513 | } else { |
514 | const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); |
515 | Out << "."; |
516 | if (CastToBase) |
517 | Out << *CastToBase << "::"; |
518 | Out << *VD; |
519 | ElemTy = VD->getType(); |
520 | } |
521 | } else { |
522 | |
523 | Out << '[' << Path[I].ArrayIndex << ']'; |
524 | ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); |
525 | } |
526 | } |
527 | |
528 | |
529 | if (isLValueOnePastTheEnd()) { |
530 | |
531 | |
532 | Out << " + 1"; |
533 | if (IsReference) |
534 | Out << ')'; |
535 | } |
536 | return; |
537 | } |
538 | case APValue::Array: { |
539 | const ArrayType *AT = Ctx.getAsArrayType(Ty); |
540 | QualType ElemTy = AT->getElementType(); |
541 | Out << '{'; |
542 | if (unsigned N = getArrayInitializedElts()) { |
543 | getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); |
544 | for (unsigned I = 1; I != N; ++I) { |
545 | Out << ", "; |
546 | if (I == 10) { |
547 | |
548 | Out << "..."; |
549 | break; |
550 | } |
551 | getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); |
552 | } |
553 | } |
554 | Out << '}'; |
555 | return; |
556 | } |
557 | case APValue::Struct: { |
558 | Out << '{'; |
559 | const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); |
560 | bool First = true; |
561 | if (unsigned N = getStructNumBases()) { |
562 | const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); |
563 | CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); |
564 | for (unsigned I = 0; I != N; ++I, ++BI) { |
565 | bases_end()", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 565, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BI != CD->bases_end()); |
566 | if (!First) |
567 | Out << ", "; |
568 | getStructBase(I).printPretty(Out, Ctx, BI->getType()); |
569 | First = false; |
570 | } |
571 | } |
572 | for (const auto *FI : RD->fields()) { |
573 | if (!First) |
574 | Out << ", "; |
575 | if (FI->isUnnamedBitfield()) continue; |
576 | getStructField(FI->getFieldIndex()). |
577 | printPretty(Out, Ctx, FI->getType()); |
578 | First = false; |
579 | } |
580 | Out << '}'; |
581 | return; |
582 | } |
583 | case APValue::Union: |
584 | Out << '{'; |
585 | if (const FieldDecl *FD = getUnionField()) { |
586 | Out << "." << *FD << " = "; |
587 | getUnionValue().printPretty(Out, Ctx, FD->getType()); |
588 | } |
589 | Out << '}'; |
590 | return; |
591 | case APValue::MemberPointer: |
592 | |
593 | |
594 | if (const ValueDecl *VD = getMemberPointerDecl()) { |
595 | Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; |
596 | return; |
597 | } |
598 | Out << "0"; |
599 | return; |
600 | case APValue::AddrLabelDiff: |
601 | Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); |
602 | Out << " - "; |
603 | Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); |
604 | return; |
605 | } |
606 | llvm_unreachable("Unknown APValue kind!"); |
607 | } |
608 | |
609 | std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { |
610 | std::string Result; |
611 | llvm::raw_string_ostream Out(Result); |
612 | printPretty(Out, Ctx, Ty); |
613 | Out.flush(); |
614 | return Result; |
615 | } |
616 | |
617 | bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, |
618 | const ASTContext &Ctx) const { |
619 | if (isInt()) { |
620 | Result = getInt(); |
621 | return true; |
622 | } |
623 | |
624 | if (isLValue() && isNullPointer()) { |
625 | Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); |
626 | return true; |
627 | } |
628 | |
629 | if (isLValue() && !getLValueBase()) { |
630 | Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); |
631 | return true; |
632 | } |
633 | |
634 | return false; |
635 | } |
636 | |
637 | const APValue::LValueBase APValue::getLValueBase() const { |
638 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 638, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
639 | return ((const LV*)(const void*)Data.buffer)->Base; |
640 | } |
641 | |
642 | bool APValue::isLValueOnePastTheEnd() const { |
643 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 643, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
644 | return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; |
645 | } |
646 | |
647 | CharUnits &APValue::getLValueOffset() { |
648 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 648, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
649 | return ((LV*)(void*)Data.buffer)->Offset; |
650 | } |
651 | |
652 | bool APValue::hasLValuePath() const { |
653 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 653, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
654 | return ((const LV*)(const char*)Data.buffer)->hasPath(); |
655 | } |
656 | |
657 | ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { |
658 | (0) . __assert_fail ("isLValue() && hasLValuePath() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 658, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && hasLValuePath() && "Invalid accessor"); |
659 | const LV &LVal = *((const LV*)(const char*)Data.buffer); |
660 | return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); |
661 | } |
662 | |
663 | unsigned APValue::getLValueCallIndex() const { |
664 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 664, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
665 | return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); |
666 | } |
667 | |
668 | unsigned APValue::getLValueVersion() const { |
669 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 669, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
670 | return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); |
671 | } |
672 | |
673 | bool APValue::isNullPointer() const { |
674 | (0) . __assert_fail ("isLValue() && \"Invalid usage\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 674, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid usage"); |
675 | return ((const LV*)(const char*)Data.buffer)->IsNullPtr; |
676 | } |
677 | |
678 | void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, |
679 | bool IsNullPtr) { |
680 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 680, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
681 | LV &LVal = *((LV*)(char*)Data.buffer); |
682 | LVal.Base = B; |
683 | LVal.IsOnePastTheEnd = false; |
684 | LVal.Offset = O; |
685 | LVal.resizePath((unsigned)-1); |
686 | LVal.IsNullPtr = IsNullPtr; |
687 | } |
688 | |
689 | void APValue::setLValue(LValueBase B, const CharUnits &O, |
690 | ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, |
691 | bool IsNullPtr) { |
692 | (0) . __assert_fail ("isLValue() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 692, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isLValue() && "Invalid accessor"); |
693 | LV &LVal = *((LV*)(char*)Data.buffer); |
694 | LVal.Base = B; |
695 | LVal.IsOnePastTheEnd = IsOnePastTheEnd; |
696 | LVal.Offset = O; |
697 | LVal.resizePath(Path.size()); |
698 | memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); |
699 | LVal.IsNullPtr = IsNullPtr; |
700 | } |
701 | |
702 | const ValueDecl *APValue::getMemberPointerDecl() const { |
703 | (0) . __assert_fail ("isMemberPointer() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 703, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isMemberPointer() && "Invalid accessor"); |
704 | const MemberPointerData &MPD = |
705 | *((const MemberPointerData *)(const char *)Data.buffer); |
706 | return MPD.MemberAndIsDerivedMember.getPointer(); |
707 | } |
708 | |
709 | bool APValue::isMemberPointerToDerivedMember() const { |
710 | (0) . __assert_fail ("isMemberPointer() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 710, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isMemberPointer() && "Invalid accessor"); |
711 | const MemberPointerData &MPD = |
712 | *((const MemberPointerData *)(const char *)Data.buffer); |
713 | return MPD.MemberAndIsDerivedMember.getInt(); |
714 | } |
715 | |
716 | ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { |
717 | (0) . __assert_fail ("isMemberPointer() && \"Invalid accessor\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 717, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isMemberPointer() && "Invalid accessor"); |
718 | const MemberPointerData &MPD = |
719 | *((const MemberPointerData *)(const char *)Data.buffer); |
720 | return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); |
721 | } |
722 | |
723 | void APValue::MakeLValue() { |
724 | (0) . __assert_fail ("isUninit() && \"Bad state change\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 724, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isUninit() && "Bad state change"); |
725 | static_assert(sizeof(LV) <= DataSize, "LV too big"); |
726 | new ((void*)(char*)Data.buffer) LV(); |
727 | Kind = LValue; |
728 | } |
729 | |
730 | void APValue::MakeArray(unsigned InitElts, unsigned Size) { |
731 | (0) . __assert_fail ("isUninit() && \"Bad state change\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 731, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isUninit() && "Bad state change"); |
732 | new ((void*)(char*)Data.buffer) Arr(InitElts, Size); |
733 | Kind = Array; |
734 | } |
735 | |
736 | void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, |
737 | ArrayRef<const CXXRecordDecl*> Path) { |
738 | (0) . __assert_fail ("isUninit() && \"Bad state change\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/APValue.cpp", 738, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isUninit() && "Bad state change"); |
739 | MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; |
740 | Kind = MemberPointer; |
741 | MPD->MemberAndIsDerivedMember.setPointer(Member); |
742 | MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); |
743 | MPD->resizePath(Path.size()); |
744 | memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); |
745 | } |
746 | |