]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/APValue.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / AST / APValue.h
1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
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 defines the APValue class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_CLANG_AST_APVALUE_H
14 #define LLVM_CLANG_AST_APVALUE_H
15
16 #include "clang/Basic/FixedPoint.h"
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/APSInt.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 #include "llvm/ADT/PointerUnion.h"
22
23 namespace clang {
24   class AddrLabelExpr;
25   class ASTContext;
26   class CharUnits;
27   class CXXRecordDecl;
28   class Decl;
29   class DiagnosticBuilder;
30   class Expr;
31   class FieldDecl;
32   struct PrintingPolicy;
33   class Type;
34   class ValueDecl;
35
36 /// Symbolic representation of typeid(T) for some type T.
37 class TypeInfoLValue {
38   const Type *T;
39
40 public:
41   TypeInfoLValue() : T() {}
42   explicit TypeInfoLValue(const Type *T);
43
44   const Type *getType() const { return T; }
45   explicit operator bool() const { return T; }
46
47   void *getOpaqueValue() { return const_cast<Type*>(T); }
48   static TypeInfoLValue getFromOpaqueValue(void *Value) {
49     TypeInfoLValue V;
50     V.T = reinterpret_cast<const Type*>(Value);
51     return V;
52   }
53
54   void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
55 };
56 }
57
58 namespace llvm {
59 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
60   static void *getAsVoidPointer(clang::TypeInfoLValue V) {
61     return V.getOpaqueValue();
62   }
63   static clang::TypeInfoLValue getFromVoidPointer(void *P) {
64     return clang::TypeInfoLValue::getFromOpaqueValue(P);
65   }
66   // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
67   // to include Type.h.
68   static constexpr int NumLowBitsAvailable = 3;
69 };
70 }
71
72 namespace clang {
73 /// APValue - This class implements a discriminated union of [uninitialized]
74 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
75 /// [Vector: N * APValue], [Array: N * APValue]
76 class APValue {
77   typedef llvm::APSInt APSInt;
78   typedef llvm::APFloat APFloat;
79 public:
80   enum ValueKind {
81     /// There is no such object (it's outside its lifetime).
82     None,
83     /// This object has an indeterminate value (C++ [basic.indet]).
84     Indeterminate,
85     Int,
86     Float,
87     FixedPoint,
88     ComplexInt,
89     ComplexFloat,
90     LValue,
91     Vector,
92     Array,
93     Struct,
94     Union,
95     MemberPointer,
96     AddrLabelDiff
97   };
98
99   class LValueBase {
100     typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue>
101         PtrTy;
102
103   public:
104     LValueBase() : Local{} {}
105     LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
106     LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
107     static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
108
109     template <class T>
110     bool is() const { return Ptr.is<T>(); }
111
112     template <class T>
113     T get() const { return Ptr.get<T>(); }
114
115     template <class T>
116     T dyn_cast() const { return Ptr.dyn_cast<T>(); }
117
118     void *getOpaqueValue() const;
119
120     bool isNull() const;
121
122     explicit operator bool() const;
123
124     unsigned getCallIndex() const;
125     unsigned getVersion() const;
126     QualType getTypeInfoType() const;
127
128     friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
129     friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
130       return !(LHS == RHS);
131     }
132     friend llvm::hash_code hash_value(const LValueBase &Base);
133
134   private:
135     PtrTy Ptr;
136     struct LocalState {
137       unsigned CallIndex, Version;
138     };
139     union {
140       LocalState Local;
141       /// The type std::type_info, if this is a TypeInfoLValue.
142       void *TypeInfoType;
143     };
144   };
145
146   /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
147   /// mean a virtual or non-virtual base class subobject.
148   typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
149
150   /// A non-discriminated union of a base, field, or array index.
151   class LValuePathEntry {
152     static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
153                   "pointer doesn't fit in 64 bits?");
154     uint64_t Value;
155
156   public:
157     LValuePathEntry() : Value() {}
158     LValuePathEntry(BaseOrMemberType BaseOrMember)
159         : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
160     static LValuePathEntry ArrayIndex(uint64_t Index) {
161       LValuePathEntry Result;
162       Result.Value = Index;
163       return Result;
164     }
165
166     BaseOrMemberType getAsBaseOrMember() const {
167       return BaseOrMemberType::getFromOpaqueValue(
168           reinterpret_cast<void *>(Value));
169     }
170     uint64_t getAsArrayIndex() const { return Value; }
171
172     friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
173       return A.Value == B.Value;
174     }
175     friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
176       return A.Value != B.Value;
177     }
178     friend llvm::hash_code hash_value(LValuePathEntry A) {
179       return llvm::hash_value(A.Value);
180     }
181   };
182   struct NoLValuePath {};
183   struct UninitArray {};
184   struct UninitStruct {};
185
186   friend class ASTReader;
187   friend class ASTWriter;
188
189 private:
190   ValueKind Kind;
191
192   struct ComplexAPSInt {
193     APSInt Real, Imag;
194     ComplexAPSInt() : Real(1), Imag(1) {}
195   };
196   struct ComplexAPFloat {
197     APFloat Real, Imag;
198     ComplexAPFloat() : Real(0.0), Imag(0.0) {}
199   };
200   struct LV;
201   struct Vec {
202     APValue *Elts;
203     unsigned NumElts;
204     Vec() : Elts(nullptr), NumElts(0) {}
205     ~Vec() { delete[] Elts; }
206   };
207   struct Arr {
208     APValue *Elts;
209     unsigned NumElts, ArrSize;
210     Arr(unsigned NumElts, unsigned ArrSize);
211     ~Arr();
212   };
213   struct StructData {
214     APValue *Elts;
215     unsigned NumBases;
216     unsigned NumFields;
217     StructData(unsigned NumBases, unsigned NumFields);
218     ~StructData();
219   };
220   struct UnionData {
221     const FieldDecl *Field;
222     APValue *Value;
223     UnionData();
224     ~UnionData();
225   };
226   struct AddrLabelDiffData {
227     const AddrLabelExpr* LHSExpr;
228     const AddrLabelExpr* RHSExpr;
229   };
230   struct MemberPointerData;
231
232   // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
233   typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
234                                       ComplexAPFloat, Vec, Arr, StructData,
235                                       UnionData, AddrLabelDiffData> DataType;
236   static const size_t DataSize = sizeof(DataType);
237
238   DataType Data;
239
240 public:
241   APValue() : Kind(None) {}
242   explicit APValue(APSInt I) : Kind(None) {
243     MakeInt(); setInt(std::move(I));
244   }
245   explicit APValue(APFloat F) : Kind(None) {
246     MakeFloat(); setFloat(std::move(F));
247   }
248   explicit APValue(APFixedPoint FX) : Kind(None) {
249     MakeFixedPoint(std::move(FX));
250   }
251   explicit APValue(const APValue *E, unsigned N) : Kind(None) {
252     MakeVector(); setVector(E, N);
253   }
254   APValue(APSInt R, APSInt I) : Kind(None) {
255     MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
256   }
257   APValue(APFloat R, APFloat I) : Kind(None) {
258     MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
259   }
260   APValue(const APValue &RHS);
261   APValue(APValue &&RHS) : Kind(None) { swap(RHS); }
262   APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
263           bool IsNullPtr = false)
264       : Kind(None) {
265     MakeLValue(); setLValue(B, O, N, IsNullPtr);
266   }
267   APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
268           bool OnePastTheEnd, bool IsNullPtr = false)
269       : Kind(None) {
270     MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
271   }
272   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
273     MakeArray(InitElts, Size);
274   }
275   APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
276     MakeStruct(B, M);
277   }
278   explicit APValue(const FieldDecl *D, const APValue &V = APValue())
279       : Kind(None) {
280     MakeUnion(); setUnion(D, V);
281   }
282   APValue(const ValueDecl *Member, bool IsDerivedMember,
283           ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
284     MakeMemberPointer(Member, IsDerivedMember, Path);
285   }
286   APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
287       : Kind(None) {
288     MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
289   }
290   static APValue IndeterminateValue() {
291     APValue Result;
292     Result.Kind = Indeterminate;
293     return Result;
294   }
295
296   ~APValue() {
297     if (Kind != None && Kind != Indeterminate)
298       DestroyDataAndMakeUninit();
299   }
300
301   /// Returns whether the object performed allocations.
302   ///
303   /// If APValues are constructed via placement new, \c needsCleanup()
304   /// indicates whether the destructor must be called in order to correctly
305   /// free all allocated memory.
306   bool needsCleanup() const;
307
308   /// Swaps the contents of this and the given APValue.
309   void swap(APValue &RHS);
310
311   ValueKind getKind() const { return Kind; }
312
313   bool isAbsent() const { return Kind == None; }
314   bool isIndeterminate() const { return Kind == Indeterminate; }
315   bool hasValue() const { return Kind != None && Kind != Indeterminate; }
316
317   bool isInt() const { return Kind == Int; }
318   bool isFloat() const { return Kind == Float; }
319   bool isFixedPoint() const { return Kind == FixedPoint; }
320   bool isComplexInt() const { return Kind == ComplexInt; }
321   bool isComplexFloat() const { return Kind == ComplexFloat; }
322   bool isLValue() const { return Kind == LValue; }
323   bool isVector() const { return Kind == Vector; }
324   bool isArray() const { return Kind == Array; }
325   bool isStruct() const { return Kind == Struct; }
326   bool isUnion() const { return Kind == Union; }
327   bool isMemberPointer() const { return Kind == MemberPointer; }
328   bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
329
330   void dump() const;
331   void dump(raw_ostream &OS) const;
332
333   void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
334   std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
335
336   APSInt &getInt() {
337     assert(isInt() && "Invalid accessor");
338     return *(APSInt*)(char*)Data.buffer;
339   }
340   const APSInt &getInt() const {
341     return const_cast<APValue*>(this)->getInt();
342   }
343
344   /// Try to convert this value to an integral constant. This works if it's an
345   /// integer, null pointer, or offset from a null pointer. Returns true on
346   /// success.
347   bool toIntegralConstant(APSInt &Result, QualType SrcTy,
348                           const ASTContext &Ctx) const;
349
350   APFloat &getFloat() {
351     assert(isFloat() && "Invalid accessor");
352     return *(APFloat*)(char*)Data.buffer;
353   }
354   const APFloat &getFloat() const {
355     return const_cast<APValue*>(this)->getFloat();
356   }
357
358   APFixedPoint &getFixedPoint() {
359     assert(isFixedPoint() && "Invalid accessor");
360     return *(APFixedPoint *)(char *)Data.buffer;
361   }
362   const APFixedPoint &getFixedPoint() const {
363     return const_cast<APValue *>(this)->getFixedPoint();
364   }
365
366   APSInt &getComplexIntReal() {
367     assert(isComplexInt() && "Invalid accessor");
368     return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
369   }
370   const APSInt &getComplexIntReal() const {
371     return const_cast<APValue*>(this)->getComplexIntReal();
372   }
373
374   APSInt &getComplexIntImag() {
375     assert(isComplexInt() && "Invalid accessor");
376     return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
377   }
378   const APSInt &getComplexIntImag() const {
379     return const_cast<APValue*>(this)->getComplexIntImag();
380   }
381
382   APFloat &getComplexFloatReal() {
383     assert(isComplexFloat() && "Invalid accessor");
384     return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
385   }
386   const APFloat &getComplexFloatReal() const {
387     return const_cast<APValue*>(this)->getComplexFloatReal();
388   }
389
390   APFloat &getComplexFloatImag() {
391     assert(isComplexFloat() && "Invalid accessor");
392     return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
393   }
394   const APFloat &getComplexFloatImag() const {
395     return const_cast<APValue*>(this)->getComplexFloatImag();
396   }
397
398   const LValueBase getLValueBase() const;
399   CharUnits &getLValueOffset();
400   const CharUnits &getLValueOffset() const {
401     return const_cast<APValue*>(this)->getLValueOffset();
402   }
403   bool isLValueOnePastTheEnd() const;
404   bool hasLValuePath() const;
405   ArrayRef<LValuePathEntry> getLValuePath() const;
406   unsigned getLValueCallIndex() const;
407   unsigned getLValueVersion() const;
408   bool isNullPointer() const;
409
410   APValue &getVectorElt(unsigned I) {
411     assert(isVector() && "Invalid accessor");
412     assert(I < getVectorLength() && "Index out of range");
413     return ((Vec*)(char*)Data.buffer)->Elts[I];
414   }
415   const APValue &getVectorElt(unsigned I) const {
416     return const_cast<APValue*>(this)->getVectorElt(I);
417   }
418   unsigned getVectorLength() const {
419     assert(isVector() && "Invalid accessor");
420     return ((const Vec*)(const void *)Data.buffer)->NumElts;
421   }
422
423   APValue &getArrayInitializedElt(unsigned I) {
424     assert(isArray() && "Invalid accessor");
425     assert(I < getArrayInitializedElts() && "Index out of range");
426     return ((Arr*)(char*)Data.buffer)->Elts[I];
427   }
428   const APValue &getArrayInitializedElt(unsigned I) const {
429     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
430   }
431   bool hasArrayFiller() const {
432     return getArrayInitializedElts() != getArraySize();
433   }
434   APValue &getArrayFiller() {
435     assert(isArray() && "Invalid accessor");
436     assert(hasArrayFiller() && "No array filler");
437     return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
438   }
439   const APValue &getArrayFiller() const {
440     return const_cast<APValue*>(this)->getArrayFiller();
441   }
442   unsigned getArrayInitializedElts() const {
443     assert(isArray() && "Invalid accessor");
444     return ((const Arr*)(const void *)Data.buffer)->NumElts;
445   }
446   unsigned getArraySize() const {
447     assert(isArray() && "Invalid accessor");
448     return ((const Arr*)(const void *)Data.buffer)->ArrSize;
449   }
450
451   unsigned getStructNumBases() const {
452     assert(isStruct() && "Invalid accessor");
453     return ((const StructData*)(const char*)Data.buffer)->NumBases;
454   }
455   unsigned getStructNumFields() const {
456     assert(isStruct() && "Invalid accessor");
457     return ((const StructData*)(const char*)Data.buffer)->NumFields;
458   }
459   APValue &getStructBase(unsigned i) {
460     assert(isStruct() && "Invalid accessor");
461     return ((StructData*)(char*)Data.buffer)->Elts[i];
462   }
463   APValue &getStructField(unsigned i) {
464     assert(isStruct() && "Invalid accessor");
465     return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
466   }
467   const APValue &getStructBase(unsigned i) const {
468     return const_cast<APValue*>(this)->getStructBase(i);
469   }
470   const APValue &getStructField(unsigned i) const {
471     return const_cast<APValue*>(this)->getStructField(i);
472   }
473
474   const FieldDecl *getUnionField() const {
475     assert(isUnion() && "Invalid accessor");
476     return ((const UnionData*)(const char*)Data.buffer)->Field;
477   }
478   APValue &getUnionValue() {
479     assert(isUnion() && "Invalid accessor");
480     return *((UnionData*)(char*)Data.buffer)->Value;
481   }
482   const APValue &getUnionValue() const {
483     return const_cast<APValue*>(this)->getUnionValue();
484   }
485
486   const ValueDecl *getMemberPointerDecl() const;
487   bool isMemberPointerToDerivedMember() const;
488   ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
489
490   const AddrLabelExpr* getAddrLabelDiffLHS() const {
491     assert(isAddrLabelDiff() && "Invalid accessor");
492     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
493   }
494   const AddrLabelExpr* getAddrLabelDiffRHS() const {
495     assert(isAddrLabelDiff() && "Invalid accessor");
496     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
497   }
498
499   void setInt(APSInt I) {
500     assert(isInt() && "Invalid accessor");
501     *(APSInt *)(char *)Data.buffer = std::move(I);
502   }
503   void setFloat(APFloat F) {
504     assert(isFloat() && "Invalid accessor");
505     *(APFloat *)(char *)Data.buffer = std::move(F);
506   }
507   void setFixedPoint(APFixedPoint FX) {
508     assert(isFixedPoint() && "Invalid accessor");
509     *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
510   }
511   void setVector(const APValue *E, unsigned N) {
512     assert(isVector() && "Invalid accessor");
513     ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
514     ((Vec*)(char*)Data.buffer)->NumElts = N;
515     for (unsigned i = 0; i != N; ++i)
516       ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
517   }
518   void setComplexInt(APSInt R, APSInt I) {
519     assert(R.getBitWidth() == I.getBitWidth() &&
520            "Invalid complex int (type mismatch).");
521     assert(isComplexInt() && "Invalid accessor");
522     ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
523     ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
524   }
525   void setComplexFloat(APFloat R, APFloat I) {
526     assert(&R.getSemantics() == &I.getSemantics() &&
527            "Invalid complex float (type mismatch).");
528     assert(isComplexFloat() && "Invalid accessor");
529     ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
530     ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
531   }
532   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
533                  bool IsNullPtr);
534   void setLValue(LValueBase B, const CharUnits &O,
535                  ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
536                  bool IsNullPtr);
537   void setUnion(const FieldDecl *Field, const APValue &Value) {
538     assert(isUnion() && "Invalid accessor");
539     ((UnionData*)(char*)Data.buffer)->Field = Field;
540     *((UnionData*)(char*)Data.buffer)->Value = Value;
541   }
542   void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
543                         const AddrLabelExpr* RHSExpr) {
544     ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
545     ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
546   }
547
548   /// Assign by swapping from a copy of the RHS.
549   APValue &operator=(APValue RHS) {
550     swap(RHS);
551     return *this;
552   }
553
554 private:
555   void DestroyDataAndMakeUninit();
556   void MakeInt() {
557     assert(isAbsent() && "Bad state change");
558     new ((void*)Data.buffer) APSInt(1);
559     Kind = Int;
560   }
561   void MakeFloat() {
562     assert(isAbsent() && "Bad state change");
563     new ((void*)(char*)Data.buffer) APFloat(0.0);
564     Kind = Float;
565   }
566   void MakeFixedPoint(APFixedPoint &&FX) {
567     assert(isAbsent() && "Bad state change");
568     new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
569     Kind = FixedPoint;
570   }
571   void MakeVector() {
572     assert(isAbsent() && "Bad state change");
573     new ((void*)(char*)Data.buffer) Vec();
574     Kind = Vector;
575   }
576   void MakeComplexInt() {
577     assert(isAbsent() && "Bad state change");
578     new ((void*)(char*)Data.buffer) ComplexAPSInt();
579     Kind = ComplexInt;
580   }
581   void MakeComplexFloat() {
582     assert(isAbsent() && "Bad state change");
583     new ((void*)(char*)Data.buffer) ComplexAPFloat();
584     Kind = ComplexFloat;
585   }
586   void MakeLValue();
587   void MakeArray(unsigned InitElts, unsigned Size);
588   void MakeStruct(unsigned B, unsigned M) {
589     assert(isAbsent() && "Bad state change");
590     new ((void*)(char*)Data.buffer) StructData(B, M);
591     Kind = Struct;
592   }
593   void MakeUnion() {
594     assert(isAbsent() && "Bad state change");
595     new ((void*)(char*)Data.buffer) UnionData();
596     Kind = Union;
597   }
598   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
599                          ArrayRef<const CXXRecordDecl*> Path);
600   void MakeAddrLabelDiff() {
601     assert(isAbsent() && "Bad state change");
602     new ((void*)(char*)Data.buffer) AddrLabelDiffData();
603     Kind = AddrLabelDiff;
604   }
605 };
606
607 } // end namespace clang.
608
609 namespace llvm {
610 template<> struct DenseMapInfo<clang::APValue::LValueBase> {
611   static clang::APValue::LValueBase getEmptyKey();
612   static clang::APValue::LValueBase getTombstoneKey();
613   static unsigned getHashValue(const clang::APValue::LValueBase &Base);
614   static bool isEqual(const clang::APValue::LValueBase &LHS,
615                       const clang::APValue::LValueBase &RHS);
616 };
617 }
618
619 #endif