Tyker updated this revision to Diff 206464.
Tyker edited the summary of this revision.
Tyker added a comment.

Change:

- Add support for LValue, MemberPointer and AddrDiffExpr.
- Add tests for importing.

i wasn't able to test for some APValueKinds: FixePoint, ComplexInt, 
ComplexFloat, AddrLabelDiff.
LValue could need more tests. i am not sure all edges cases are covered.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63640/new/

https://reviews.llvm.org/D63640

Files:
  clang/include/clang/AST/APValue.h
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/ASTImporter.h
  clang/include/clang/AST/Expr.h
  clang/include/clang/AST/TextNodeDumper.h
  clang/include/clang/Serialization/ASTReader.h
  clang/lib/AST/APValue.cpp
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Decl.cpp
  clang/lib/AST/Expr.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTReaderStmt.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/ASTMerge/APValue/Inputs/APValue.cpp
  clang/test/ASTMerge/APValue/test.cpp
  clang/test/PCH/APValue.cpp

Index: clang/test/PCH/APValue.cpp
===================================================================
--- /dev/null
+++ clang/test/PCH/APValue.cpp
@@ -0,0 +1,210 @@
+
+// RUN: %clang_cc1 -std=gnu++2a -emit-pch %s -o %t.pch
+// RUN: %clang_cc1 -std=gnu++2a -x c++ -include-pch %t.pch -ast-dump-all | FileCheck %s
+
+#ifndef EMIT
+#define EMIT
+
+namespace Integer {
+
+constexpr int Unique_Int = int(6789);
+//CHECK:      VarDecl {{.*}} Unique_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'int' 6789
+
+constexpr __uint128_t Unique_Int128 = ((__uint128_t)0x75f17d6b3588f843 << 64) | 0xb13dea7c9c324e51;
+//CHECK:      VarDecl {{.*}} Unique_Int128 
+//CHECK-NEXT: ConstantExpr {{.*}} 'unsigned __int128' 156773562844924187900898496343692168785
+
+}
+
+namespace FloatingPoint {
+
+constexpr double Unique_Double = double(567890.67890);
+//CHECK:      VarDecl {{.*}} Unique_Double
+//CHECK-NEXT: ConstantExpr {{.*}} 'double' 5.678907e+05
+
+}
+
+// FIXME: Add test for FixePoint, ComplexInt, ComplexFloat, AddrLabelDiff.
+
+namespace Struct {
+
+struct B {
+  int i;
+  double d;
+};
+
+constexpr B Basic_Struct = B{1, 0.7};
+//CHECK:      VarDecl {{.*}} Basic_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Struct::B' {1, 7.000000e-01}
+
+struct C {
+  int i = 9;
+};
+
+struct A : B {
+  int i;
+  double d;
+  C c;
+};
+
+constexpr A Advanced_Struct = A{Basic_Struct, 1, 79.789, {}};
+//CHECK:      VarDecl {{.*}} Advanced_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Struct::A' {{[{][{]}}1, 7.000000e-01}, 1, 7.978900e+01, {9}}
+
+}
+
+namespace Vector {
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+constexpr v4si Vector_Int = (v4si){8, 2, 3};
+//CHECK:      VarDecl {{.*}} Vector_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'Vector::v4si':'__attribute__((__vector_size__(4 * sizeof(int)))) int' {8, 2, 3, 0}
+
+}
+
+namespace Array {
+
+constexpr int Array_Int[] = {1, 2, 3, 4, 5, 6};
+//CHECK:      VarDecl {{.*}} Array_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int [6]' {1, 2, 3, 4, 5, 6}
+
+struct A {
+  int i = 789;
+  double d = 67890.09876;
+};
+
+constexpr A Array2_Struct[][3] = {{{}, {-45678, 9.8}, {9}}, {{}}};
+//CHECK:      VarDecl {{.*}} Array2_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'Array::A const [2][3]' {{[{][{]}}{789, 6.789010e+04}, {-45678, 9.800000e+00}, {9, 6.789010e+04}}, {{[{][{]}}789, 6.789010e+04}, {789, 6.789010e+04}, {789, 6.789010e+04}}}
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+constexpr v4si Array_Vector[] = {{1, 2, 3, 4}, {4, 5, 6, 7}};
+//CHECK:      VarDecl {{.*}} Array_Vector
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Array::v4si [2]' {{[{][{]}}1, 2, 3, 4}, {4, 5, 6, 7}}
+
+}
+
+namespace Union {
+
+struct A {
+  int i = 6789;
+  float f = 987.9876;
+};
+
+union U {
+  int i;
+  A a{567890, 9876.5678f};
+};
+
+constexpr U Unique_Union1 = U{0};
+//CHECK:      VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Union::U' {.i = 0}
+
+constexpr U Unique_Union2 = U{};
+//CHECK:      VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Union::U' {.a = {567890, 9.876567e+03}}
+
+}
+
+namespace MemberPointer{
+
+struct A {
+  struct B {
+    struct C {
+      struct D {
+        struct E {
+          struct F {
+            struct G {
+              int i;
+            };
+          };
+        };
+      };
+    };
+  };
+};
+
+constexpr auto MemberPointer1 = &A::B::C::D::E::F::G::i;
+//CHECK:      VarDecl {{.*}} MemberPointer1
+//CHECK-NEXT: ConstantExpr {{.*}} 'int MemberPointer::A::B::C::D::E::F::G::*' &G::i
+
+struct A1 {
+  struct B1 {
+    int f() const {
+      return 0;
+    }
+  };
+
+};
+
+constexpr auto MemberPointer2 = &A1::B1::f;
+//CHECK:      VarDecl {{.*}} MemberPointer2
+//CHECK-NEXT: ConstantExpr {{.*}} 'int (MemberPointer::A1::B1::*)() const' &B1::f
+
+}
+
+namespace std {
+  struct type_info;
+};
+
+namespace LValue {
+
+constexpr int LValueInt = 0;
+constexpr const int& ConstIntRef = LValueInt;
+//CHECK:      VarDecl {{.*}} ConstIntRef
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &LValueInt
+constexpr const int* IntPtr = &LValueInt;
+//CHECK:      VarDecl {{.*}} IntPtr
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *' &LValueInt
+
+constexpr const int* NullPtr = nullptr;
+//CHECK:      VarDecl {{.*}} NullPtr
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *const' nullptr
+
+struct A {
+  int Arr[6] = {0, 1, 3, 4, 5, 9};
+  int i = 0;
+};
+
+constexpr A Arr[] = {{}, {}};
+
+constexpr const int& ArrayStructRef1 = Arr[0].i;
+//CHECK:      VarDecl {{.*}} ArrayStructRef1
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &Arr[0].i
+
+constexpr const int& ArrayStructRef2 = Arr[1].Arr[5];
+//CHECK:      VarDecl {{.*}} ArrayStructRef2
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &Arr[1].Arr[5]
+
+constexpr const int* ArrayStructRef3 = &ArrayStructRef2;
+//CHECK:      VarDecl {{.*}} ArrayStructRef3
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *' &Arr[1].Arr[5]
+
+struct B : A {
+};
+
+struct C {
+  B b;
+};
+
+constexpr C c;
+
+constexpr const int& StructPathRef = c.b.i;
+//CHECK:      VarDecl {{.*}} StructPathRef
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &c.b.A::i
+
+constexpr const std::type_info &TypeID = typeid(c);
+//CHECK:      VarDecl {{.*}} TypeID
+//CHECK-NEXT: ConstantExpr {{.*}} 'const std::type_info' lvalue &typeid(LValue::C)
+
+constexpr const std::type_info &TypeID2 = typeid(Arr[1].Arr[2]);
+//CHECK:      VarDecl {{.*}} TypeID2
+//CHECK-NEXT: ConstantExpr {{.*}} 'const std::type_info' lvalue &typeid(int)
+
+}
+
+#endif
+
Index: clang/test/ASTMerge/APValue/test.cpp
===================================================================
--- /dev/null
+++ clang/test/ASTMerge/APValue/test.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -x c++ -emit-pch -std=gnu++2a -o %t.1.ast %S/Inputs/APValue.cpp
+// RUN: %clang_cc1 -x c++ -std=gnu++2a -ast-merge %t.1.ast -ast-dump-all | FileCheck %s
+
+//CHECK:      VarDecl {{.*}} Unique_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'int' 6789
+
+//CHECK:      VarDecl {{.*}} Unique_Int128 
+//CHECK-NEXT: ConstantExpr {{.*}} 'unsigned __int128' 156773562844924187900898496343692168785
+
+//CHECK:      VarDecl {{.*}} Unique_Double
+//CHECK-NEXT: ConstantExpr {{.*}} 'double' 5.678907e+05
+
+//CHECK:      VarDecl {{.*}} Basic_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Struct::B' {1, 7.000000e-01}
+
+//CHECK:      VarDecl {{.*}} Advanced_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Struct::A' {{[{][{]}}1, 7.000000e-01}, 1, 7.978900e+01, {9}}
+
+//CHECK:      VarDecl {{.*}} Vector_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'Vector::v4si':'__attribute__((__vector_size__(4 * sizeof(int)))) int' {8, 2, 3, 0}
+
+//CHECK:      VarDecl {{.*}} Array_Int
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int [6]' {1, 2, 3, 4, 5, 6}
+
+//CHECK:      VarDecl {{.*}} Array2_Struct
+//CHECK-NEXT: ConstantExpr {{.*}} 'Array::A const [2][3]' {{[{][{]}}{789, 6.789010e+04}, {-45678, 9.800000e+00}, {9, 6.789010e+04}}, {{[{][{]}}789, 6.789010e+04}, {789, 6.789010e+04}, {789, 6.789010e+04}}}
+
+//CHECK:      VarDecl {{.*}} Array_Vector
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Array::v4si [2]' {{[{][{]}}1, 2, 3, 4}, {4, 5, 6, 7}}
+
+//CHECK:      VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Union::U' {.i = 0}
+
+//CHECK:      VarDecl {{.*}} Unique_Union
+//CHECK-NEXT: ConstantExpr {{.*}} 'const Union::U' {.a = {567890, 9.876567e+03}}
+
+//CHECK:      VarDecl {{.*}} MemberPointer1
+//CHECK-NEXT: ConstantExpr {{.*}} 'int MemberPointer::A::B::C::D::E::F::G::*' &G::i
+
+//CHECK:      VarDecl {{.*}} MemberPointer2
+//CHECK-NEXT: ConstantExpr {{.*}} 'int (MemberPointer::A1::B1::*)() const' &B1::f
+
+//CHECK:      VarDecl {{.*}} ConstIntRef
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &LValueInt
+
+//CHECK:      VarDecl {{.*}} IntPtr
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *' &LValueInt
+
+//CHECK:      VarDecl {{.*}} NullPtr
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *const' nullptr
+
+//CHECK:      VarDecl {{.*}} ArrayStructRef1
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &Arr[0].i
+
+//CHECK:      VarDecl {{.*}} ArrayStructRef2
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &Arr[1].Arr[5]
+
+//CHECK:      VarDecl {{.*}} ArrayStructRef3
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int *' &Arr[1].Arr[5]
+
+//CHECK:      VarDecl {{.*}} StructPathRef
+//CHECK-NEXT: ConstantExpr {{.*}} 'const int' lvalue &c.b.A::i
+
+//CHECK:      VarDecl {{.*}} TypeID
+//CHECK-NEXT: ConstantExpr {{.*}} 'const std::type_info' lvalue &typeid(LValue::C)
+
+//CHECK:      VarDecl {{.*}} TypeID2
+//CHECK-NEXT: ConstantExpr {{.*}} 'const std::type_info' lvalue &typeid(int)
Index: clang/test/ASTMerge/APValue/Inputs/APValue.cpp
===================================================================
--- /dev/null
+++ clang/test/ASTMerge/APValue/Inputs/APValue.cpp
@@ -0,0 +1,165 @@
+
+// RUN: %clang_cc1 -std=gnu++2a -emit-pch %s -o %t.pch
+// RUN: %clang_cc1 -std=gnu++2a -x c++ -include-pch %t.pch -ast-dump-all | FileCheck %s
+
+#ifndef EMIT
+#define EMIT
+
+namespace Integer {
+
+constexpr int Unique_Int = int(6789);
+
+constexpr __uint128_t Unique_Int128 = ((__uint128_t)0x75f17d6b3588f843 << 64) | 0xb13dea7c9c324e51;
+
+}
+
+namespace FloatingPoint {
+
+constexpr double Unique_Double = double(567890.67890);
+
+}
+
+// FIXME: Add test for FixePoint, ComplexInt, ComplexFloat, AddrLabelDiff.
+
+namespace Struct {
+
+struct B {
+  int i;
+  double d;
+};
+
+constexpr B Basic_Struct = B{1, 0.7};
+
+struct C {
+  int i = 9;
+};
+
+struct A : B {
+  int i;
+  double d;
+  C c;
+};
+
+constexpr A Advanced_Struct = A{Basic_Struct, 1, 79.789, {}};
+
+}
+
+namespace Vector {
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+constexpr v4si Vector_Int = (v4si){8, 2, 3};
+
+}
+
+namespace Array {
+
+constexpr int Array_Int[] = {1, 2, 3, 4, 5, 6};
+
+struct A {
+  int i = 789;
+  double d = 67890.09876;
+};
+
+constexpr A Array2_Struct[][3] = {{{}, {-45678, 9.8}, {9}}, {{}}};
+
+using v4si = int __attribute__((__vector_size__(16)));
+
+constexpr v4si Array_Vector[] = {{1, 2, 3, 4}, {4, 5, 6, 7}};
+
+}
+
+namespace Union {
+
+struct A {
+  int i = 6789;
+  float f = 987.9876;
+};
+
+union U {
+  int i;
+  A a{567890, 9876.5678f};
+};
+
+constexpr U Unique_Union1 = U{0};
+
+constexpr U Unique_Union2 = U{};
+
+}
+
+namespace MemberPointer{
+
+struct A {
+  struct B {
+    struct C {
+      struct D {
+        struct E {
+          struct F {
+            struct G {
+              int i;
+            };
+          };
+        };
+      };
+    };
+  };
+};
+
+constexpr auto MemberPointer1 = &A::B::C::D::E::F::G::i;
+
+struct A1 {
+  struct B1 {
+    int f() const {
+      return 0;
+    }
+  };
+
+};
+
+constexpr auto MemberPointer2 = &A1::B1::f;
+
+}
+
+namespace std {
+  struct type_info;
+};
+
+namespace LValue {
+
+constexpr int LValueInt = 0;
+constexpr const int& ConstIntRef = LValueInt;
+constexpr const int* IntPtr = &LValueInt;
+
+constexpr const int* NullPtr = nullptr;
+
+struct A {
+  int Arr[6] = {0, 1, 3, 4, 5, 9};
+  int i = 0;
+};
+
+constexpr A Arr[] = {{}, {}};
+
+constexpr const int& ArrayStructRef1 = Arr[0].i;
+
+constexpr const int& ArrayStructRef2 = Arr[1].Arr[5];
+
+constexpr const int* ArrayStructRef3 = &ArrayStructRef2;
+
+struct B : A {
+};
+
+struct C {
+  B b;
+};
+
+constexpr C c;
+
+constexpr const int& StructPathRef = c.b.i;
+
+constexpr const std::type_info &TypeID = typeid(c);
+
+constexpr const std::type_info &TypeID2 = typeid(Arr[1].Arr[2]);
+
+}
+
+#endif
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -5441,20 +5441,98 @@
     AddAPFloat(Value.getComplexFloatImag());
     return;
   }
-  case APValue::LValue:
   case APValue::Vector:
+    push_back(Value.getVectorLength());
+    for (unsigned Idx = 0; Idx < Value.getVectorLength(); Idx++)
+      AddAPValue(Value.getVectorElt(Idx));
+    return;
   case APValue::Array:
+    push_back(Value.getArrayInitializedElts());
+    push_back(Value.getArraySize());
+    for (unsigned Idx = 0; Idx < Value.getArrayInitializedElts(); Idx++)
+      AddAPValue(Value.getArrayInitializedElt(Idx));
+    return;
   case APValue::Struct:
+    push_back(Value.getStructNumBases());
+    push_back(Value.getStructNumFields());
+    for (unsigned Idx = 0; Idx < Value.getStructNumBases(); Idx++)
+      AddAPValue(Value.getStructBase(Idx));
+    for (unsigned Idx = 0; Idx < Value.getStructNumFields(); Idx++)
+      AddAPValue(Value.getStructField(Idx));
+    return;
   case APValue::Union:
-  case APValue::MemberPointer:
+    AddDeclRef(Value.getUnionField());
+    AddAPValue(Value.getUnionValue());
+    return;
   case APValue::AddrLabelDiff:
-    // TODO : Handle all these APValue::ValueKind.
+    AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffLHS()));
+    AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffRHS()));
+    return;
+  case APValue::MemberPointer: {
+    push_back(Value.isMemberPointerToDerivedMember());
+    AddDeclRef(Value.getMemberPointerDecl());
+    ArrayRef<const CXXRecordDecl *> RecordPath = Value.getMemberPointerPath();
+    push_back(RecordPath.size());
+    for (auto Elem : RecordPath)
+      AddDeclRef(Elem);
+    return;
+  }
+  case APValue::LValue: {
+    uint64_t tmp = Value.hasLValuePath() | Value.isLValueOnePastTheEnd() << 1 |
+                   Value.getLValueBase().is<const Expr *>() << 2 |
+                   Value.getLValueBase().is<TypeInfoLValue>() << 3 |
+                   Value.isNullPointer() << 4 |
+                   static_cast<bool>(Value.getLValueBase()) << 5;
+    push_back(tmp);
+    QualType ElemTy;
+    if (Value.getLValueBase()) {
+      if (!Value.getLValueBase().is<TypeInfoLValue>()) {
+        push_back(Value.getLValueBase().getCallIndex());
+        push_back(Value.getLValueBase().getVersion());
+        if (auto *E = Value.getLValueBase().dyn_cast<const Expr *>()) {
+          AddStmt(const_cast<Expr *>(E));
+          ElemTy = E->getType();
+        } else {
+          AddDeclRef(Value.getLValueBase().get<const ValueDecl *>());
+          ElemTy = Value.getLValueBase().get<const ValueDecl *>()->getType();
+        }
+      } else {
+        AddTypeRef(
+            QualType(Value.getLValueBase().get<TypeInfoLValue>().getType(), 0));
+        AddTypeRef(Value.getLValueBase().getTypeInfoType());
+        ElemTy = Value.getLValueBase().getTypeInfoType();
+      }
+    }
+    push_back(Value.getLValueOffset().getQuantity());
+    push_back(Value.getLValuePath().size());
+    if (Value.hasLValuePath()) {
+      ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
+      for (auto Elem : Path) {
+        if (ElemTy->getAs<RecordType>()) {
+          push_back(Elem.getAsBaseOrMember().getInt());
+          const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer();
+          if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+            AddDeclRef(RD);
+            ElemTy = Writer->Context->getRecordType(RD);
+          } else {
+            const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
+            AddDeclRef(VD);
+            ElemTy = VD->getType();
+          }
+        } else {
+          push_back(Elem.getAsArrayIndex());
+          ElemTy = Writer->Context->getAsArrayType(ElemTy)->getElementType();
+        }
+      }
+    }
+  }
     return;
   }
   llvm_unreachable("Invalid APValue::ValueKind");
 }
 
-void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {
+void ASTWriter::AddIdentifierRef(const IdentifierInfo *II,
+                                 RecordDataImpl &Record) {
   Record.push_back(getIdentifierRef(II));
 }
 
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -540,10 +540,11 @@
     uint64_t tmp = Record.readInt();
     E->ConstantExprBits.IsUnsigned = tmp & 0x1;
     E->ConstantExprBits.BitWidth = tmp >> 1;
+    E->ConstantExprBits.APValueKind = APValue::Int;
     break;
   }
   case ConstantExpr::RSK_APValue:
-    E->APValueResult() = Record.readAPValue();
+    E->SetResult(Record.readAPValue(), Record.getContext());
   }
   E->setSubExpr(Record.readSubExpr());
 }
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -9115,45 +9115,152 @@
                              HasUnsignedPadding);
 }
 
-APValue ASTReader::ReadAPValue(const RecordData &Record, unsigned &Idx) {
-  unsigned Kind = Record[Idx++];
+APValue ASTReader::ReadAPValue(ModuleFile &F, const RecordData &Record,
+                               unsigned &RecordIdx) {
+  auto Kind = static_cast<APValue::ValueKind>(Record[RecordIdx++]);
   switch (Kind) {
   case APValue::None:
     return APValue();
   case APValue::Indeterminate:
     return APValue::IndeterminateValue();
   case APValue::Int:
-    return APValue(ReadAPSInt(Record, Idx));
+    return APValue(ReadAPSInt(Record, RecordIdx));
   case APValue::Float: {
     const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
-        static_cast<llvm::APFloatBase::Semantics>(Record[Idx++]));
-    return APValue(ReadAPFloat(Record, FloatSema, Idx));
+        static_cast<llvm::APFloatBase::Semantics>(Record[RecordIdx++]));
+    return APValue(ReadAPFloat(Record, FloatSema, RecordIdx));
   }
   case APValue::FixedPoint: {
-    FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx);
-    return APValue(APFixedPoint(ReadAPInt(Record, Idx), FPSema));
+    FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, RecordIdx);
+    return APValue(APFixedPoint(ReadAPInt(Record, RecordIdx), FPSema));
   }
   case APValue::ComplexInt: {
-    llvm::APSInt First = ReadAPSInt(Record, Idx);
-    return APValue(std::move(First), ReadAPSInt(Record, Idx));
+    llvm::APSInt First = ReadAPSInt(Record, RecordIdx);
+    return APValue(std::move(First), ReadAPSInt(Record, RecordIdx));
   }
   case APValue::ComplexFloat: {
     const llvm::fltSemantics &FloatSema1 = llvm::APFloatBase::EnumToSemantics(
-        static_cast<llvm::APFloatBase::Semantics>(Record[Idx++]));
-    llvm::APFloat First = ReadAPFloat(Record, FloatSema1, Idx);
+        static_cast<llvm::APFloatBase::Semantics>(Record[RecordIdx++]));
+    llvm::APFloat First = ReadAPFloat(Record, FloatSema1, RecordIdx);
     const llvm::fltSemantics &FloatSema2 = llvm::APFloatBase::EnumToSemantics(
-        static_cast<llvm::APFloatBase::Semantics>(Record[Idx++]));
-    return APValue(std::move(First), ReadAPFloat(Record, FloatSema2, Idx));
-  }
-  case APValue::LValue:
-  case APValue::Vector:
-  case APValue::Array:
-  case APValue::Struct:
-  case APValue::Union:
-  case APValue::MemberPointer:
-  case APValue::AddrLabelDiff:
-    // TODO : Handle all these APValue::ValueKind.
-    return APValue();
+        static_cast<llvm::APFloatBase::Semantics>(Record[RecordIdx++]));
+    return APValue(std::move(First),
+                   ReadAPFloat(Record, FloatSema2, RecordIdx));
+  }
+  case APValue::Vector: {
+    APValue Result;
+    Result.MakeVector();
+    unsigned Length = Record[RecordIdx++];
+    Result.ReserveVector(Length);
+    for (unsigned LoopIdx = 0; LoopIdx < Length; LoopIdx++)
+      Result.getVectorElt(LoopIdx) = ReadAPValue(F, Record, RecordIdx);
+    return Result;
+  }
+  case APValue::Array: {
+    APValue Result;
+    unsigned InitLength = Record[RecordIdx++];
+    unsigned TotalLength = Record[RecordIdx++];
+    Result.MakeArray(InitLength, TotalLength);
+    for (unsigned LoopIdx = 0; LoopIdx < InitLength; LoopIdx++)
+      Result.getArrayInitializedElt(LoopIdx) =
+          ReadAPValue(F, Record, RecordIdx);
+    return Result;
+  }
+  case APValue::Struct: {
+    APValue Result;
+    unsigned BasesLength = Record[RecordIdx++];
+    unsigned FieldsLength = Record[RecordIdx++];
+    Result.MakeStruct(BasesLength, FieldsLength);
+    for (unsigned LoopIdx = 0; LoopIdx < BasesLength; LoopIdx++)
+      Result.getStructBase(LoopIdx) = ReadAPValue(F, Record, RecordIdx);
+    for (unsigned LoopIdx = 0; LoopIdx < FieldsLength; LoopIdx++)
+      Result.getStructField(LoopIdx) = ReadAPValue(F, Record, RecordIdx);
+    return Result;
+  }
+  case APValue::Union: {
+    FieldDecl *FDecl =
+        cast<FieldDecl>(GetDecl(ReadDeclID(F, Record, RecordIdx)));
+    APValue Value = ReadAPValue(F, Record, RecordIdx);
+    return APValue(FDecl, Value);
+  }
+  case APValue::AddrLabelDiff: {
+    AddrLabelExpr *LHS = cast<AddrLabelExpr>(ReadExpr(F));
+    AddrLabelExpr *RHS = cast<AddrLabelExpr>(ReadExpr(F));
+    return APValue(LHS, RHS);
+  }
+  case APValue::MemberPointer: {
+    APValue Result;
+    bool IsDerived = Record[RecordIdx++];
+    ValueDecl *Member =
+        cast<ValueDecl>(GetDecl(ReadDeclID(F, Record, RecordIdx)));
+    unsigned PathSize = Record[RecordIdx++];
+    Result.MakeEmptyMemberPointer(Member, IsDerived, PathSize);
+    CXXRecordDecl **PathArray = Result.getMemberPointerPathPtr();
+    for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
+      PathArray[LoopIdx] =
+          cast<CXXRecordDecl>(GetDecl(ReadDeclID(F, Record, RecordIdx)));
+    return Result;
+  }
+  case APValue::LValue: {
+    uint64_t tmp = Record[RecordIdx++];
+    bool hasLValuePath = tmp & 0x1;
+    bool isLValueOnePastTheEnd = tmp & 0x2;
+    bool isExpr = tmp & 0x4;
+    bool isTypeInfo = tmp & 0x8;
+    bool isNullPtr = tmp & 0x10;
+    bool hasBase = tmp & 0x20;
+    APValue::LValueBase Base;
+    QualType ElemTy;
+    assert(!isExpr || !isTypeInfo && "LValueBase cannot be both");
+    if (hasBase) {
+      if (!isTypeInfo) {
+        unsigned CallIndex = Record[RecordIdx++];
+        unsigned Version = Record[RecordIdx++];
+        if (isExpr) {
+          Base = APValue::LValueBase(ReadExpr(F), CallIndex, Version);
+          ElemTy = Base.get<const Expr *>()->getType();
+        } else {
+          Base = APValue::LValueBase(
+              cast<ValueDecl>(GetDecl(ReadDeclID(F, Record, RecordIdx))),
+              CallIndex, Version);
+          ElemTy = Base.get<const ValueDecl *>()->getType();
+        }
+      } else {
+        QualType TypeInfo = readType(F, Record, RecordIdx);
+        QualType Type = readType(F, Record, RecordIdx);
+        Base = APValue::LValueBase::getTypeInfo(
+            TypeInfoLValue(TypeInfo.getTypePtr()), Type);
+        Base.getTypeInfoType();
+      }
+    }
+    CharUnits Offset = CharUnits::fromQuantity(Record[RecordIdx++]);
+    unsigned PathLength = Record[RecordIdx++];
+    APValue Result;
+    Result.MakeLValue();
+    if (hasLValuePath) {
+      Result.setLValueEmptyPath(Base, Offset, PathLength, isLValueOnePastTheEnd,
+                                isNullPtr);
+      APValue::LValuePathEntry *Path = Result.getLValuePathPtr();
+      for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+        if (ElemTy->getAs<RecordType>()) {
+          unsigned Int = Record[RecordIdx++];
+          Decl *D = GetDecl(ReadDeclID(F, Record, RecordIdx));
+          if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+            ElemTy = ContextObj->getRecordType(RD);
+          else
+            ElemTy = cast<ValueDecl>(D)->getType();
+          Path[LoopIdx] =
+              APValue::LValuePathEntry(APValue::BaseOrMemberType(D, Int));
+        } else {
+          ElemTy = ContextObj->getAsArrayType(ElemTy)->getElementType();
+          Path[LoopIdx] =
+              APValue::LValuePathEntry::ArrayIndex(Record[RecordIdx++]);
+        }
+      }
+    } else
+      Result.setLValue(Base, Offset, APValue::NoLValuePath{}, isNullPtr);
+    return Result;
+  }
   }
   llvm_unreachable("Invalid APValue::ValueKind");
 }
@@ -10883,18 +10990,6 @@
           break;
         }
 
-        if (FirstInit && SecondInit &&
-            ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
-          ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
-                       VarDifferentInitializer)
-              << FirstName << FirstInit->getSourceRange();
-          ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
-                      VarDifferentInitializer)
-              << SecondName << SecondInit->getSourceRange();
-          Diagnosed = true;
-          break;
-        }
-
         const bool FirstIsConstexpr = FirstVD->isConstexpr();
         const bool SecondIsConstexpr = SecondVD->isConstexpr();
         if (FirstIsConstexpr != SecondIsConstexpr) {
@@ -10907,6 +11002,19 @@
           Diagnosed = true;
           break;
         }
+
+        if (FirstInit && SecondInit &&
+            ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+          ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(),
+                       VarDifferentInitializer)
+              << FirstName << FirstInit->getSourceRange();
+          ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(),
+                      VarDifferentInitializer)
+              << SecondName << SecondInit->getSourceRange();
+          Diagnosed = true;
+          break;
+        }
+
         break;
       }
       case Friend: {
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -11287,6 +11287,12 @@
         FSI->markSafeWeakUse(Init);
   }
 
+  if (VDecl->isConstexpr()) {
+    Init = ConstantExpr::Create(
+        Context, Init,
+        ConstantExpr::getStorageKind(VDecl->getType()->getAs<Type>(), Context));
+  }
+
   // The initialization is usually a full-expression.
   //
   // FIXME: If this is a braced initialization of an aggregate, it is not
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -685,10 +685,13 @@
 }
 
 void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
-  if (Node->getResultAPValueKind() != APValue::None) {
+  if (Node->getResultStorageKind() != ConstantExpr::RSK_None) {
     ColorScope Color(OS, ShowColors, ValueColor);
     OS << " ";
-    Node->getAPValueResult().printPretty(OS, *Context, Node->getType());
+    if (Context)
+      Node->getAPValueResult().printPretty(OS, *Context, Node->getType());
+    else
+      Node->getAPValueResult().dump(OS);
   }
 }
 
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -260,8 +260,10 @@
 void ConstantExpr::DefaultInit(ResultStorageKind StorageKind) {
   ConstantExprBits.ResultKind = StorageKind;
   ConstantExprBits.APValueKind = APValue::None;
+  ConstantExprBits.BitWidth = 0;
+  ConstantExprBits.IsUnsigned = false;
   ConstantExprBits.HasCleanup = false;
-  if (StorageKind == ConstantExpr::RSK_APValue)
+  if (StorageKind == RSK_APValue)
     ::new (getTrailingObjects<APValue>()) APValue();
 }
 
@@ -278,8 +280,7 @@
       StorageKind == ConstantExpr::RSK_APValue,
       StorageKind == ConstantExpr::RSK_Int64);
   void *Mem = Context.Allocate(Size, alignof(ConstantExpr));
-  ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind);
-  return Self;
+  return new (Mem) ConstantExpr(E, StorageKind);
 }
 
 ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
@@ -308,9 +309,11 @@
 }
 
 void ConstantExpr::MoveIntoResult(APValue &Value, const ASTContext &Context) {
-  assert(getStorageKind(Value) == ConstantExprBits.ResultKind &&
+  assert(getStorageKind(Value) <= ConstantExprBits.ResultKind &&
          "Invalid storage for this value kind");
   ConstantExprBits.APValueKind = Value.getKind();
+  if (!Value.hasValue())
+    return;
   switch (ConstantExprBits.ResultKind) {
   case RSK_None:
     return;
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -2347,6 +2347,11 @@
   else if (Eval->Evaluated.needsCleanup())
     getASTContext().addDestruction(&Eval->Evaluated);
 
+  if (auto *ConstantInit = dyn_cast<ConstantExpr>(Eval->Value))
+    if (ConstantExpr::getStorageKind(Eval->Evaluated) <=
+        ConstantInit->getResultStorageKind())
+      ConstantInit->SetResult(Eval->Evaluated, getASTContext());
+
   Eval->IsEvaluating = false;
   Eval->WasEvaluated = true;
 
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6369,21 +6369,15 @@
 }
 
 ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
-  auto Imp = importSeq(E->getSubExpr());
+  auto Imp = importSeq(E->getSubExpr(), E->getAPValueResult());
   if (!Imp)
     return Imp.takeError();
 
   Expr *ToSubExpr;
-  std::tie(ToSubExpr) = *Imp;
+  APValue ToResult;
+  std::tie(ToSubExpr, ToResult) = *Imp;
 
-  // TODO : Handle APValue::ValueKind that require importing.
-  APValue::ValueKind Kind = E->getResultAPValueKind();
-  if (Kind == APValue::Int || Kind == APValue::Float ||
-      Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat ||
-      Kind == APValue::ComplexInt)
-    return ConstantExpr::Create(Importer.getToContext(), ToSubExpr,
-                                E->getAPValueResult());
-  return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
+  return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult);
 }
 
 ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
@@ -8506,6 +8500,195 @@
   return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
 }
 
+llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) {
+  APValue Result;
+  llvm::Error Error = llvm::Error::success();
+  auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) {
+    for (unsigned Idx = 0; Idx < Size; Idx++) {
+      llvm::Expected<APValue> Tmp = Import(From[Idx]);
+      if (!Tmp) {
+        Error = Tmp.takeError();
+        return;
+      }
+      To[Idx] = std::move(Tmp.get());
+    }
+  };
+  switch (FromValue.getKind()) {
+  case APValue::None:
+  case APValue::Indeterminate:
+  case APValue::Int:
+  case APValue::Float:
+  case APValue::FixedPoint:
+  case APValue::ComplexInt:
+  case APValue::ComplexFloat:
+    Result = FromValue;
+    break;
+  case APValue::Vector:
+    Result.MakeVector();
+    Result.ReserveVector(FromValue.getVectorLength());
+    ImportLoop(
+        ((const APValue::Vec *)(const char *)FromValue.Data.buffer)->Elts,
+        ((const APValue::Vec *)(const char *)Result.Data.buffer)->Elts,
+        FromValue.getVectorLength());
+    break;
+  case APValue::Array:
+    Result.MakeArray(FromValue.getArrayInitializedElts(),
+                     FromValue.getArraySize());
+    ImportLoop(
+        ((const APValue::Arr *)(const char *)FromValue.Data.buffer)->Elts,
+        ((const APValue::Arr *)(const char *)Result.Data.buffer)->Elts,
+        FromValue.getArrayInitializedElts());
+    break;
+  case APValue::Struct:
+    Result.MakeStruct(FromValue.getStructNumBases(),
+                      FromValue.getStructNumFields());
+    ImportLoop(
+        ((const APValue::StructData *)(const char *)FromValue.Data.buffer)
+            ->Elts,
+        ((const APValue::StructData *)(const char *)Result.Data.buffer)->Elts,
+        FromValue.getStructNumBases() + FromValue.getStructNumFields());
+    break;
+  case APValue::Union: {
+    Result.MakeUnion();
+    auto ImpFDecl = Import(FromValue.getUnionField());
+    if (!ImpFDecl) {
+      Error = ImpFDecl.takeError();
+      break;
+    }
+    auto ImpValue = Import(FromValue.getUnionValue());
+    if (!ImpValue) {
+      Error = ImpValue.takeError();
+      break;
+    }
+    Result.setUnion(cast<FieldDecl>(ImpFDecl.get()), ImpValue.get());
+    break;
+  }
+  case APValue::AddrLabelDiff: {
+    Result.MakeAddrLabelDiff();
+    auto ImpLHS =
+        Import(const_cast<AddrLabelExpr *>(FromValue.getAddrLabelDiffLHS()));
+    if (!ImpLHS) {
+      Error = ImpLHS.takeError();
+      break;
+    }
+    auto ImpRHS =
+        Import(const_cast<AddrLabelExpr *>(FromValue.getAddrLabelDiffRHS()));
+    if (!ImpRHS) {
+      Error = ImpRHS.takeError();
+      break;
+    }
+    Result.setAddrLabelDiff(cast<AddrLabelExpr>(ImpLHS.get()),
+                            cast<AddrLabelExpr>(ImpRHS.get()));
+    break;
+  }
+  case APValue::MemberPointer: {
+    auto ImpMemPtrDecl = Import(FromValue.getMemberPointerDecl());
+    if (!ImpMemPtrDecl) {
+      Error = ImpMemPtrDecl.takeError();
+      break;
+    }
+    Result.MakeEmptyMemberPointer(cast<const ValueDecl>(ImpMemPtrDecl.get()),
+                                  FromValue.isMemberPointerToDerivedMember(),
+                                  FromValue.getMemberPointerPath().size());
+    llvm::ArrayRef<const CXXRecordDecl *> FromPath =
+        Result.getMemberPointerPath();
+    CXXRecordDecl **ToPath = Result.getMemberPointerPathPtr();
+    for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size();
+         Idx++) {
+      auto ImpDecl = Import(FromPath[Idx]);
+      if (!ImpDecl) {
+        Error = ImpDecl.takeError();
+        break;
+      }
+      ToPath[Idx] = cast<CXXRecordDecl>(const_cast<Decl *>(ImpDecl.get()));
+    }
+    break;
+  }
+  case APValue::LValue:
+    APValue::LValueBase Base;
+    QualType FromElemTy;
+    if (FromValue.getLValueBase()) {
+      if (!FromValue.getLValueBase().is<TypeInfoLValue>()) {
+        if (auto *E = FromValue.getLValueBase().dyn_cast<const Expr *>()) {
+          FromElemTy = E->getType();
+          auto ImpExpr = Import(const_cast<Expr *>(E));
+          if (!ImpExpr) {
+            Error = ImpExpr.takeError();
+            break;
+          }
+          Base = APValue::LValueBase(ImpExpr.get(),
+                                     FromValue.getLValueBase().getCallIndex(),
+                                     FromValue.getLValueBase().getVersion());
+        } else {
+          FromElemTy =
+              FromValue.getLValueBase().get<const ValueDecl *>()->getType();
+          auto ImpDecl =
+              Import(FromValue.getLValueBase().get<const ValueDecl *>());
+          if (!ImpDecl) {
+            Error = ImpDecl.takeError();
+            break;
+          }
+          Base = APValue::LValueBase(cast<ValueDecl>(ImpDecl.get()),
+                                     FromValue.getLValueBase().getCallIndex(),
+                                     FromValue.getLValueBase().getVersion());
+        }
+      } else {
+        FromElemTy = FromValue.getLValueBase().getTypeInfoType();
+        auto ImpTypeInfo = Import(QualType(
+            FromValue.getLValueBase().get<TypeInfoLValue>().getType(), 0));
+        if (!ImpTypeInfo) {
+          Error = ImpTypeInfo.takeError();
+          break;
+        }
+        auto ImpType = Import(FromValue.getLValueBase().getTypeInfoType());
+        if (!ImpType) {
+          Error = ImpType.takeError();
+          break;
+        }
+        Base = APValue::LValueBase::getTypeInfo(
+            TypeInfoLValue(ImpTypeInfo.get().getTypePtr()), ImpType.get());
+      }
+    }
+    CharUnits Offset = FromValue.getLValueOffset();
+    unsigned PathLength = FromValue.getLValuePath().size();
+    Result.MakeLValue();
+    if (FromValue.hasLValuePath()) {
+      Result.setLValueEmptyPath(Base, Offset, PathLength,
+                                FromValue.isLValueOnePastTheEnd(),
+                                FromValue.isNullPointer());
+      llvm::ArrayRef<APValue::LValuePathEntry> FromPath =
+          FromValue.getLValuePath();
+      APValue::LValuePathEntry *ToPath = Result.getLValuePathPtr();
+      for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+        if (FromElemTy->getAs<RecordType>()) {
+          const Decl *FromDecl =
+              FromPath[LoopIdx].getAsBaseOrMember().getPointer();
+          auto ImpDecl = Import(FromDecl);
+          if (!ImpDecl) {
+            Error = ImpDecl.takeError();
+            break;
+          }
+          if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl))
+            FromElemTy = FromContext.getRecordType(RD);
+          else
+            FromElemTy = cast<ValueDecl>(FromDecl)->getType();
+          ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType(
+              ImpDecl.get(), FromPath[LoopIdx].getAsBaseOrMember().getInt()));
+        } else {
+          FromElemTy = FromContext.getAsArrayType(FromElemTy)->getElementType();
+          ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex(
+              FromPath[LoopIdx].getAsArrayIndex());
+        }
+      }
+    } else
+      Result.setLValue(Base, Offset, APValue::NoLValuePath{},
+                       FromValue.isNullPointer());
+  }
+  if (Error)
+    return std::move(Error);
+  return Result;
+}
+
 DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name,
                                                 DeclContext *DC,
                                                 unsigned IDNS,
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -827,9 +827,6 @@
 
   for (const auto &Value : ModuleInitializers)
     Value.second->~PerModuleInitializers();
-
-  for (APValue *Value : APValueCleanups)
-    Value->~APValue();
 }
 
 class ASTContext::ParentMap {
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -172,8 +172,8 @@
 
 struct APValue::MemberPointerData : MemberPointerBase {
   static const unsigned InlinePathSpace =
-      (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
-  typedef const CXXRecordDecl *PathElem;
+      (DataSize - sizeof(MemberPointerBase)) / sizeof(CXXRecordDecl *);
+  typedef CXXRecordDecl *PathElem;
   union {
     PathElem Path[InlinePathSpace];
     PathElem *PathPtr;
@@ -745,6 +745,10 @@
   return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
 }
 
+APValue::LValuePathEntry *APValue::getLValuePathPtr() {
+  return ((LV *)(char *)Data.buffer)->getPath();
+}
+
 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
                         bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
@@ -756,17 +760,24 @@
   LVal.IsNullPtr = IsNullPtr;
 }
 
-void APValue::setLValue(LValueBase B, const CharUnits &O,
-                        ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
-                        bool IsNullPtr) {
+void APValue::setLValueEmptyPath(LValueBase B, const CharUnits &O,
+                                 unsigned Size, bool IsOnePastTheEnd,
+                                 bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
-  LV &LVal = *((LV*)(char*)Data.buffer);
+  LV &LVal = *((LV *)(char *)Data.buffer);
   LVal.Base = B;
   LVal.IsOnePastTheEnd = IsOnePastTheEnd;
   LVal.Offset = O;
-  LVal.resizePath(Path.size());
-  memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
   LVal.IsNullPtr = IsNullPtr;
+  LVal.resizePath(Size);
+}
+
+void APValue::setLValue(LValueBase B, const CharUnits &O,
+                        ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
+                        bool IsNullPtr) {
+  setLValueEmptyPath(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr);
+  memcpy(((LV *)(char *)Data.buffer)->getPath(), Path.data(),
+         Path.size() * sizeof(LValuePathEntry));
 }
 
 const ValueDecl *APValue::getMemberPointerDecl() const {
@@ -803,13 +814,23 @@
   Kind = Array;
 }
 
-void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
-                                ArrayRef<const CXXRecordDecl*> Path) {
+void APValue::MakeEmptyMemberPointer(const ValueDecl *Member,
+                                     bool IsDerivedMember, unsigned Size) {
   assert(isAbsent() && "Bad state change");
   MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
   Kind = MemberPointer;
   MPD->MemberAndIsDerivedMember.setPointer(Member);
   MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
-  MPD->resizePath(Path.size());
-  memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
+  MPD->resizePath(Size);
+}
+
+void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+                                ArrayRef<const CXXRecordDecl *> Path) {
+  MakeEmptyMemberPointer(Member, IsDerivedMember, Path.size());
+  memcpy(((MemberPointerData *)(char *)Data.buffer)->getPath(), Path.data(),
+         Path.size() * sizeof(const CXXRecordDecl *));
+}
+
+CXXRecordDecl **APValue::getMemberPointerPathPtr() {
+  return ((MemberPointerData *)(char *)Data.buffer)->getPath();
 }
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -2221,7 +2221,7 @@
                             const llvm::fltSemantics &Sem, unsigned &Idx);
 
   /// Read an APValue
-  APValue ReadAPValue(const RecordData &Record, unsigned &Idx);
+  APValue ReadAPValue(ModuleFile &F, const RecordData &Record, unsigned &Idx);
 
   // Read a string
   static std::string ReadString(const RecordData &Record, unsigned &Idx);
@@ -2615,7 +2615,7 @@
     return Reader->ReadSourceRange(*F, Record, Idx);
   }
 
-  APValue readAPValue() { return Reader->ReadAPValue(Record, Idx); }
+  APValue readAPValue() { return Reader->ReadAPValue(*F, Record, Idx); }
 
   /// Read an integral value, advancing Idx.
   llvm::APInt readAPInt() {
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -146,7 +146,7 @@
 
   const comments::CommandTraits *Traits;
 
-  const ASTContext *Context;
+  const ASTContext *Context = nullptr;
 
   const char *getCommandName(unsigned CommandID);
 
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -954,6 +954,7 @@
 
 public:
   /// Describes the kind of result that can be trail-allocated.
+  /// Enumerator need to stay ordered by size of there storage.
   enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue };
 
 private:
Index: clang/include/clang/AST/ASTImporter.h
===================================================================
--- clang/include/clang/AST/ASTImporter.h
+++ clang/include/clang/AST/ASTImporter.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_AST_ASTIMPORTER_H
 #define LLVM_CLANG_AST_ASTIMPORTER_H
 
+#include "clang/AST/APValue.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateName.h"
@@ -324,6 +325,13 @@
     /// "to" context, or the import error.
     llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec);
 
+    /// Import the gieven APValue from the "from" context into
+    /// the "to" context.
+    ///
+    /// \return the equivalent APValue in the "from" Constext or the import
+    /// error.
+    llvm::Expected<APValue> Import(const APValue &FromValue);
+
     /// Import the definition of the given declaration, including all of
     /// the declarations it contains.
     LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From);
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -271,9 +271,6 @@
   llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
     MaterializedTemporaryValues;
 
-  /// Used to cleanups APValues stored in the AST.
-  mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
-
   /// A cache mapping a string value to a StringLiteral object with the same
   /// value.
   ///
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -185,6 +185,7 @@
 
   friend class ASTReader;
   friend class ASTWriter;
+  friend class ASTImporter;
 
 private:
   ValueKind Kind;
@@ -508,10 +509,13 @@
     assert(isFixedPoint() && "Invalid accessor");
     *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
   }
-  void setVector(const APValue *E, unsigned N) {
+  void ReserveVector(unsigned N) {
     assert(isVector() && "Invalid accessor");
     ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
     ((Vec*)(char*)Data.buffer)->NumElts = N;
+  }
+  void setVector(const APValue *E, unsigned N) {
+    ReserveVector(N);
     for (unsigned i = 0; i != N; ++i)
       ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
   }
@@ -529,6 +533,13 @@
     ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
     ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
   }
+
+private:
+  void setLValueEmptyPath(LValueBase B, const CharUnits &O, unsigned Size,
+                          bool OnePastTheEnd, bool IsNullPtr);
+  LValuePathEntry *getLValuePathPtr();
+
+public:
   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
                  bool IsNullPtr);
   void setLValue(LValueBase B, const CharUnits &O,
@@ -595,13 +606,16 @@
     new ((void*)(char*)Data.buffer) UnionData();
     Kind = Union;
   }
+  void MakeEmptyMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+                              unsigned Size);
   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
-                         ArrayRef<const CXXRecordDecl*> Path);
+                         ArrayRef<const CXXRecordDecl *> Path);
   void MakeAddrLabelDiff() {
     assert(isAbsent() && "Bad state change");
-    new ((void*)(char*)Data.buffer) AddrLabelDiffData();
+    new ((void *)(char *)Data.buffer) AddrLabelDiffData();
     Kind = AddrLabelDiff;
   }
+  CXXRecordDecl **getMemberPointerPathPtr();
 };
 
 } // end namespace clang.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to