ahatanak updated this revision to Diff 134560.
ahatanak marked 3 inline comments as done.
ahatanak added a comment.

Address review comments.


https://reviews.llvm.org/D42776

Files:
  include/clang/AST/APValue.h
  lib/AST/APValue.cpp
  lib/AST/ExprConstant.cpp
  test/SemaCXX/constexpr-default-arg.cpp

Index: test/SemaCXX/constexpr-default-arg.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/constexpr-default-arg.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -std=c++1y -S -o - -emit-llvm -verify %s
+
+namespace default_arg_temporary {
+
+constexpr bool equals(const float& arg = 1.0f) {
+  return arg == 1.0f;
+}
+
+constexpr const int &x(const int &p = 0) {
+  return p;
+}
+
+struct S {
+  constexpr S(const int &a = 0) {}
+};
+
+void test_default_arg2() {
+  // This piece of code used to cause an assertion failure in
+  // CallStackFrame::createTemporary because the same MTE is used to initilize
+  // both elements of the array (see PR33140).
+  constexpr S s[2] = {};
+
+  // This piece of code used to cause an assertion failure in
+  // CallStackFrame::createTemporary because multiple CXXDefaultArgExpr share
+  // the same MTE (see PR33140).
+  static_assert(equals() && equals(), "");
+
+  // Test that constant expression evaluation produces distinct lvalues for
+  // each call.
+  static_assert(&x() != &x(), "");
+}
+
+// Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
+struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}}
+struct B { A x, y; };
+B b = {};
+
+}
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -438,7 +438,8 @@
 
     // Note that we intentionally use std::map here so that references to
     // values are stable.
-    typedef std::map<const void*, APValue> MapTy;
+    typedef std::pair<const void*, unsigned> KeyTy;
+    typedef std::map<KeyTy, APValue> MapTy;
     typedef MapTy::const_iterator temp_iterator;
     /// Temporaries - Temporary lvalues materialized within this stack frame.
     MapTy Temporaries;
@@ -449,6 +450,22 @@
     /// Index - The call index of this call.
     unsigned Index;
 
+    /// Keep track of the version of MTEs that are used by CXXDefaultArgExpr or
+    /// CXXDefaultInitExpr. The version number is updated every time
+    /// VisitCXXDefaultArgExpr or VisitCXXDefaultInitExpr is visited.
+    unsigned NextMTEVersion = 0;
+    SmallVector<unsigned, 2> MTEVersionStack = {0};
+
+    unsigned getMTEVersion() const { return MTEVersionStack.back(); }
+
+    void pushMTEVersion() {
+      MTEVersionStack.push_back(++NextMTEVersion);
+    }
+
+    void popMTEVersion() {
+      MTEVersionStack.pop_back();
+    }
+
     // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact
     // on the overall stack usage of deeply-recursing constexpr evaluataions.
     // (We should cache this map rather than recomputing it repeatedly.)
@@ -465,11 +482,12 @@
                    APValue *Arguments);
     ~CallStackFrame();
 
-    APValue *getTemporary(const void *Key) {
-      MapTy::iterator I = Temporaries.find(Key);
+    APValue *getTemporary(const void *Key, unsigned Version = 0) {
+      MapTy::iterator I = Temporaries.find(KeyTy(Key, Version));
       return I == Temporaries.end() ? nullptr : &I->second;
     }
-    APValue &createTemporary(const void *Key, bool IsLifetimeExtended);
+    APValue &createTemporary(const void *Key, bool IsLifetimeExtended,
+                             unsigned Version = 0);
   };
 
   /// Temporarily override 'this'.
@@ -1161,8 +1179,9 @@
 }
 
 APValue &CallStackFrame::createTemporary(const void *Key,
-                                         bool IsLifetimeExtended) {
-  APValue &Result = Temporaries[Key];
+                                         bool IsLifetimeExtended,
+                                         unsigned Version) {
+  APValue &Result = Temporaries[KeyTy(Key, Version)];
   assert(Result.isUninit() && "temporary created multiple times");
   Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended));
   return Result;
@@ -1254,40 +1273,39 @@
   struct LValue {
     APValue::LValueBase Base;
     CharUnits Offset;
-    unsigned InvalidBase : 1;
-    unsigned CallIndex : 31;
     SubobjectDesignator Designator;
-    bool IsNullPtr;
+    bool IsNullPtr : 1;
+    bool InvalidBase : 1;
 
     const APValue::LValueBase getLValueBase() const { return Base; }
     CharUnits &getLValueOffset() { return Offset; }
     const CharUnits &getLValueOffset() const { return Offset; }
-    unsigned getLValueCallIndex() const { return CallIndex; }
     SubobjectDesignator &getLValueDesignator() { return Designator; }
     const SubobjectDesignator &getLValueDesignator() const { return Designator;}
     bool isNullPointer() const { return IsNullPtr;}
 
+    unsigned getLValueCallIndex() const { return Base.getCallIndex(); }
+    unsigned getLValueVersion() const { return Base.getVersion(); }
+
     void moveInto(APValue &V) const {
       if (Designator.Invalid)
-        V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,
-                    IsNullPtr);
+        V = APValue(Base, Offset, APValue::NoLValuePath(), IsNullPtr);
       else {
         assert(!InvalidBase && "APValues can't handle invalid LValue bases");
         V = APValue(Base, Offset, Designator.Entries,
-                    Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
+                    Designator.IsOnePastTheEnd, IsNullPtr);
       }
     }
     void setFrom(ASTContext &Ctx, const APValue &V) {
       assert(V.isLValue() && "Setting LValue from a non-LValue?");
       Base = V.getLValueBase();
       Offset = V.getLValueOffset();
       InvalidBase = false;
-      CallIndex = V.getLValueCallIndex();
       Designator = SubobjectDesignator(Ctx, V);
       IsNullPtr = V.isNullPointer();
     }
 
-    void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
+    void set(APValue::LValueBase B, bool BInvalid = false) {
 #ifndef NDEBUG
       // We only allow a few types of invalid bases. Enforce that here.
       if (BInvalid) {
@@ -1300,22 +1318,20 @@
       Base = B;
       Offset = CharUnits::fromQuantity(0);
       InvalidBase = BInvalid;
-      CallIndex = I;
       Designator = SubobjectDesignator(getType(B));
       IsNullPtr = false;
     }
 
     void setNull(QualType PointerTy, uint64_t TargetVal) {
       Base = (Expr *)nullptr;
       Offset = CharUnits::fromQuantity(TargetVal);
       InvalidBase = false;
-      CallIndex = 0;
       Designator = SubobjectDesignator(PointerTy->getPointeeType());
       IsNullPtr = true;
     }
 
     void setInvalid(APValue::LValueBase B, unsigned I = 0) {
-      set(B, I, true);
+      set(B, true);
     }
 
     // Check that this LValue is not based on a null pointer. If it is, produce
@@ -1846,7 +1862,7 @@
 }
 
 static bool IsLiteralLValue(const LValue &Value) {
-  if (Value.CallIndex)
+  if (Value.getLValueCallIndex())
     return false;
   const Expr *E = Value.Base.dyn_cast<const Expr*>();
   return E && !isa<MaterializeTemporaryExpr>(E);
@@ -2992,8 +3008,8 @@
   }
 
   CallStackFrame *Frame = nullptr;
-  if (LVal.CallIndex) {
-    Frame = Info.getCallFrame(LVal.CallIndex);
+  if (LVal.getLValueCallIndex()) {
+    Frame = Info.getCallFrame(LVal.getLValueCallIndex());
     if (!Frame) {
       Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1)
         << AK << LVal.Base.is<const ValueDecl*>();
@@ -3147,7 +3163,7 @@
         return CompleteObject();
       }
     } else {
-      BaseVal = Frame->getTemporary(Base);
+      BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion());
       assert(BaseVal && "missing value for temporary");
     }
 
@@ -3167,7 +3183,8 @@
   // During the construction of an object, it is not yet 'const'.
   // FIXME: This doesn't do quite the right thing for const subobjects of the
   // object under construction.
-  if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.CallIndex)) {
+  if (Info.isEvaluatingConstructor(LVal.getLValueBase(),
+                                   LVal.getLValueCallIndex())) {
     BaseType = Info.Ctx.getCanonicalType(BaseType);
     BaseType.removeLocalConst();
   }
@@ -3204,7 +3221,7 @@
 
   // Check for special cases where there is no existing APValue to look at.
   const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
-  if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) {
+  if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) {
     if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) {
       // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
       // initializer until now for such expressions. Such an expression can't be
@@ -3700,7 +3717,7 @@
     return true;
 
   LValue Result;
-  Result.set(VD, Info.CurrentCall->Index);
+  Result.set({VD, Info.CurrentCall->Index});
   APValue &Val = Info.CurrentCall->createTemporary(VD, true);
 
   const Expr *InitE = VD->getInit();
@@ -4314,7 +4331,7 @@
   }
 
   EvalInfo::EvaluatingConstructorRAII EvalObj(
-      Info, {This.getLValueBase(), This.CallIndex});
+      Info, {This.getLValueBase(), This.getLValueCallIndex()});
   CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
 
   // FIXME: Creating an APValue just to hold a nonexistent return value is
@@ -4529,6 +4546,18 @@
 
   bool ZeroInitialization(const Expr *E) { return Error(E); }
 
+  struct DefaultArgRAII {
+    CallStackFrame &Frame;
+
+    DefaultArgRAII(CallStackFrame &Frame) : Frame(Frame) {
+      Frame.pushMTEVersion();
+    }
+
+    ~DefaultArgRAII() {
+      Frame.popMTEVersion();
+    }
+  };
+
 public:
   ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
 
@@ -4563,9 +4592,12 @@
     { return StmtVisitorTy::Visit(E->getResultExpr()); }
   bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
     { return StmtVisitorTy::Visit(E->getReplacement()); }
-  bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
-    { return StmtVisitorTy::Visit(E->getExpr()); }
+  bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
+    DefaultArgRAII RAII(*Info.CurrentCall);
+    return StmtVisitorTy::Visit(E->getExpr());
+  }
   bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
+    DefaultArgRAII RAII(*Info.CurrentCall);
     // The initializer may not have been parsed yet, or might be erroneous.
     if (!E->getExpr())
       return Error(E);
@@ -5201,7 +5233,7 @@
 
   if (!VD->getType()->isReferenceType()) {
     if (Frame) {
-      Result.set(VD, Frame->Index);
+      Result.set({VD, Frame->Index});
       return true;
     }
     return Success(VD);
@@ -5240,9 +5272,10 @@
     *Value = APValue();
     Result.set(E);
   } else {
+    unsigned Version = Info.CurrentCall->getMTEVersion();
     Value = &Info.CurrentCall->
-        createTemporary(E, E->getStorageDuration() == SD_Automatic);
-    Result.set(E, Info.CurrentCall->Index);
+        createTemporary(E, E->getStorageDuration() == SD_Automatic, Version);
+    Result.set({E, Info.CurrentCall->Index, Version});
   }
 
   QualType Type = Inner->getType();
@@ -5721,7 +5754,6 @@
       Result.Base = (Expr*)nullptr;
       Result.InvalidBase = false;
       Result.Offset = CharUnits::fromQuantity(N);
-      Result.CallIndex = 0;
       Result.Designator.setInvalid();
       Result.IsNullPtr = false;
       return true;
@@ -5737,7 +5769,7 @@
       if (!evaluateLValue(SubExpr, Result))
         return false;
     } else {
-      Result.set(SubExpr, Info.CurrentCall->Index);
+      Result.set({SubExpr, Info.CurrentCall->Index});
       if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false),
                            Info, Result, SubExpr))
         return false;
@@ -6505,7 +6537,7 @@
 
   /// Visit an expression which constructs the value of this temporary.
   bool VisitConstructExpr(const Expr *E) {
-    Result.set(E, Info.CurrentCall->Index);
+    Result.set({E, Info.CurrentCall->Index});
     return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false),
                            Info, Result, E);
   }
@@ -7981,6 +8013,9 @@
   if (!B.getLValueBase())
     return false;
 
+  if (A.getLValueBase().getVersion() != B.getLValueBase().getVersion())
+    return false;
+
   if (A.getLValueBase().getOpaqueValue() !=
       B.getLValueBase().getOpaqueValue()) {
     const Decl *ADecl = GetLValueBaseDecl(A);
@@ -7992,7 +8027,8 @@
   }
 
   return IsGlobalLValue(A.getLValueBase()) ||
-         A.getLValueCallIndex() == B.getLValueCallIndex();
+         (A.getLValueCallIndex() == B.getLValueCallIndex() &&
+          A.getLValueVersion() == B.getLValueVersion());
 }
 
 /// \brief Determine whether this is a pointer past the end of the complete
@@ -9935,14 +9971,14 @@
     return true;
   } else if (T->isArrayType()) {
     LValue LV;
-    LV.set(E, Info.CurrentCall->Index);
+    LV.set({E, Info.CurrentCall->Index});
     APValue &Value = Info.CurrentCall->createTemporary(E, false);
     if (!EvaluateArray(E, LV, Value, Info))
       return false;
     Result = Value;
   } else if (T->isRecordType()) {
     LValue LV;
-    LV.set(E, Info.CurrentCall->Index);
+    LV.set({E, Info.CurrentCall->Index});
     APValue &Value = Info.CurrentCall->createTemporary(E, false);
     if (!EvaluateRecord(E, LV, Value, Info))
       return false;
@@ -9957,7 +9993,7 @@
     QualType Unqual = T.getAtomicUnqualifiedType();
     if (Unqual->isArrayType() || Unqual->isRecordType()) {
       LValue LV;
-      LV.set(E, Info.CurrentCall->Index);
+      LV.set({E, Info.CurrentCall->Index});
       APValue &Value = Info.CurrentCall->createTemporary(E, false);
       if (!EvaluateAtomic(E, &LV, Value, Info))
         return false;
@@ -10780,7 +10816,7 @@
   // is a temporary being used as the 'this' pointer.
   LValue This;
   ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy);
-  This.set(&VIE, Info.CurrentCall->Index);
+  This.set({&VIE, Info.CurrentCall->Index});
 
   ArrayRef<const Expr*> Args;
 
Index: lib/AST/APValue.cpp
===================================================================
--- lib/AST/APValue.cpp
+++ lib/AST/APValue.cpp
@@ -23,14 +23,57 @@
 
 namespace {
   struct LVBase {
-    llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
+    APValue::LValueBase Base;
     CharUnits Offset;
     unsigned PathLength;
-    unsigned CallIndex;
-    bool IsNullPtr;
+    bool IsNullPtr : 1;
+    bool IsOnePastTheEnd : 1;
   };
 }
 
+void *APValue::LValueBase::getOpaqueValue() const {
+  return Ptr.getOpaqueValue();
+}
+
+bool APValue::LValueBase::isNull() const {
+  return Ptr.isNull();
+}
+
+APValue::LValueBase::operator bool () const {
+  return static_cast<bool>(Ptr);
+}
+
+clang::APValue::LValueBase
+llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
+  return clang::APValue::LValueBase(
+      DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(),
+      DenseMapInfo<unsigned>::getEmptyKey(),
+      DenseMapInfo<unsigned>::getEmptyKey());
+}
+
+clang::APValue::LValueBase
+llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
+  return clang::APValue::LValueBase(
+      DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(),
+      DenseMapInfo<unsigned>::getTombstoneKey(),
+      DenseMapInfo<unsigned>::getTombstoneKey());
+}
+
+unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue(
+    const clang::APValue::LValueBase &Base) {
+  llvm::FoldingSetNodeID ID;
+  ID.AddPointer(Base.getOpaqueValue());
+  ID.AddInteger(Base.getCallIndex());
+  ID.AddInteger(Base.getVersion());
+  return ID.ComputeHash();
+}
+
+bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(
+    const clang::APValue::LValueBase &LHS,
+    const clang::APValue::LValueBase &RHS) {
+  return LHS == RHS;
+}
+
 struct APValue::LV : LVBase {
   static const unsigned InlinePathSpace =
       (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
@@ -150,11 +193,10 @@
     MakeLValue();
     if (RHS.hasLValuePath())
       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
-                RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(),
-                RHS.isNullPointer());
+                RHS.isLValueOnePastTheEnd(), RHS.isNullPointer());
     else
       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
-                RHS.getLValueCallIndex(), RHS.isNullPointer());
+                RHS.isNullPointer());
     break;
   case Array:
     MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
@@ -552,12 +594,12 @@
 
 const APValue::LValueBase APValue::getLValueBase() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer();
+  return ((const LV*)(const void*)Data.buffer)->Base;
 }
 
 bool APValue::isLValueOnePastTheEnd() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt();
+  return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd;
 }
 
 CharUnits &APValue::getLValueOffset() {
@@ -578,35 +620,38 @@
 
 unsigned APValue::getLValueCallIndex() const {
   assert(isLValue() && "Invalid accessor");
-  return ((const LV*)(const char*)Data.buffer)->CallIndex;
+  return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex();
+}
+
+unsigned APValue::getLValueVersion() const {
+  assert(isLValue() && "Invalid accessor");
+  return ((const LV*)(const char*)Data.buffer)->Base.getVersion();
 }
 
 bool APValue::isNullPointer() const {
   assert(isLValue() && "Invalid usage");
   return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
 }
 
 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
-                        unsigned CallIndex, bool IsNullPtr) {
+                        bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
   LV &LVal = *((LV*)(char*)Data.buffer);
-  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
-  LVal.BaseAndIsOnePastTheEnd.setInt(false);
+  LVal.Base = B;
+  LVal.IsOnePastTheEnd = false;
   LVal.Offset = O;
-  LVal.CallIndex = CallIndex;
   LVal.resizePath((unsigned)-1);
   LVal.IsNullPtr = IsNullPtr;
 }
 
 void APValue::setLValue(LValueBase B, const CharUnits &O,
                         ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
-                        unsigned CallIndex, bool IsNullPtr) {
+                        bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
   LV &LVal = *((LV*)(char*)Data.buffer);
-  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
-  LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
+  LVal.Base = B;
+  LVal.IsOnePastTheEnd = IsOnePastTheEnd;
   LVal.Offset = O;
-  LVal.CallIndex = CallIndex;
   LVal.resizePath(Path.size());
   memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
   LVal.IsNullPtr = IsNullPtr;
Index: include/clang/AST/APValue.h
===================================================================
--- include/clang/AST/APValue.h
+++ include/clang/AST/APValue.h
@@ -53,7 +53,58 @@
     MemberPointer,
     AddrLabelDiff
   };
-  typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
+
+  class LValueBase {
+  public:
+    typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy;
+
+    LValueBase() : CallIndex(0), Version(0) {}
+
+    template <class T>
+    LValueBase(T P, unsigned I = 0, unsigned V = 0)
+        : Ptr(P), CallIndex(I), Version(V) {}
+
+    template <class T>
+    bool is() const { return Ptr.is<T>(); }
+
+    template <class T>
+    T get() const { return Ptr.get<T>(); }
+
+    template <class T>
+    T dyn_cast() const { return Ptr.dyn_cast<T>(); }
+
+    void *getOpaqueValue() const;
+
+    bool isNull() const;
+
+    explicit operator bool () const;
+
+    PtrTy getPointer() const {
+      return Ptr;
+    }
+
+    unsigned getCallIndex() const {
+      return CallIndex;
+    }
+
+    void setCallIndex(unsigned Index) {
+      CallIndex = Index;
+    }
+
+    unsigned getVersion() const {
+      return Version;
+    }
+
+    bool operator==(const LValueBase &Other) const {
+      return Ptr == Other.Ptr && CallIndex == Other.CallIndex &&
+             Version == Other.Version;
+    }
+
+  private:
+    PtrTy Ptr;
+    unsigned CallIndex, Version;
+  };
+
   typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
   union LValuePathEntry {
     /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
@@ -135,15 +186,15 @@
   }
   APValue(const APValue &RHS);
   APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
-  APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex,
+  APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
           bool IsNullPtr = false)
       : Kind(Uninitialized) {
-    MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr);
+    MakeLValue(); setLValue(B, O, N, IsNullPtr);
   }
   APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
-          bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false)
+          bool OnePastTheEnd, bool IsNullPtr = false)
       : Kind(Uninitialized) {
-    MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr);
+    MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
   }
   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
     MakeArray(InitElts, Size);
@@ -255,6 +306,7 @@
   bool hasLValuePath() const;
   ArrayRef<LValuePathEntry> getLValuePath() const;
   unsigned getLValueCallIndex() const;
+  unsigned getLValueVersion() const;
   bool isNullPointer() const;
 
   APValue &getVectorElt(unsigned I) {
@@ -376,10 +428,10 @@
     ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
   }
   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
-                 unsigned CallIndex, bool IsNullPtr);
+                 bool IsNullPtr);
   void setLValue(LValueBase B, const CharUnits &O,
                  ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
-                 unsigned CallIndex, bool IsNullPtr);
+                 bool IsNullPtr);
   void setUnion(const FieldDecl *Field, const APValue &Value) {
     assert(isUnion() && "Invalid accessor");
     ((UnionData*)(char*)Data.buffer)->Field = Field;
@@ -451,4 +503,14 @@
 
 } // end namespace clang.
 
+namespace llvm {
+template<> struct DenseMapInfo<clang::APValue::LValueBase> {
+  static clang::APValue::LValueBase getEmptyKey();
+  static clang::APValue::LValueBase getTombstoneKey();
+  static unsigned getHashValue(const clang::APValue::LValueBase &Base);
+  static bool isEqual(const clang::APValue::LValueBase &LHS,
+                      const clang::APValue::LValueBase &RHS);
+};
+}
+
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to