Tyker updated this revision to Diff 236707.
Tyker added a comment.

rebased


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/PrettyPrinter.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/lib/Serialization/ASTWriterStmt.cpp
  clang/test/AST/ast-dump-color.cpp

Index: clang/test/AST/ast-dump-color.cpp
===================================================================
--- clang/test/AST/ast-dump-color.cpp
+++ clang/test/AST/ast-dump-color.cpp
@@ -49,13 +49,13 @@
 //CHECK: {{^}}[[Blue]]| |   |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:11[[RESET]]> [[Green]]'int'[[RESET]][[Cyan:.\[0;36m]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |   `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:14[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:3[[RESET]], [[Yellow]]line:12:27[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] Int: 1[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |     | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |     | `-[[RESET]][[MAGENTA]]AttributedStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:12:5[[RESET]], [[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   |-[[RESET]][[BLUE]]FallThroughAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:7[[RESET]], [[Yellow]]col:14[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     `-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:3[[RESET]], [[Yellow]]line:14:5[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] Int: 2[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |       | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |       `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:14:5[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:8:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -473,7 +473,8 @@
   case ConstantExpr::RSK_Int64:
     Record.push_back(E->Int64Result());
     Record.push_back(E->ConstantExprBits.IsUnsigned |
-                     E->ConstantExprBits.BitWidth << 1);
+                     E->ConstantExprBits.BitWidth << 1 |
+                     E->ConstantExprBits.APValueKind << 8);
     break;
   case ConstantExpr::RSK_APValue:
     Record.AddAPValue(E->APValueResult());
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -5065,14 +5065,90 @@
     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: {
+    push_back(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);
+    QualType ElemTy;
+    if (Value.getLValueBase()) {
+      if (!Value.getLValueBase().is<TypeInfoLValue>()) {
+        push_back(Value.getLValueBase().getCallIndex());
+        push_back(Value.getLValueBase().getVersion());
+        if (const 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 auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+            AddDeclRef(RD);
+            ElemTy = Writer->Context->getRecordType(RD);
+          } else {
+            const auto *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");
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -527,13 +527,14 @@
   switch (E->ConstantExprBits.ResultKind) {
   case ConstantExpr::RSK_Int64: {
     E->Int64Result() = Record.readInt();
-    uint64_t tmp = Record.readInt();
-    E->ConstantExprBits.IsUnsigned = tmp & 0x1;
-    E->ConstantExprBits.BitWidth = tmp >> 1;
+    uint64_t Bits = Record.readInt();
+    E->ConstantExprBits.IsUnsigned = Bits & 0x1;
+    E->ConstantExprBits.BitWidth = (Bits >> 1) & 0x7f;
+    E->ConstantExprBits.APValueKind = (Bits >> 8);
     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
@@ -8804,61 +8804,152 @@
   return SourceRange(beg, end);
 }
 
-static FixedPointSemantics
-ReadFixedPointSemantics(const SmallVectorImpl<uint64_t> &Record,
-                        unsigned &Idx) {
-  unsigned Width = Record[Idx++];
-  unsigned Scale = Record[Idx++];
-  uint64_t Tmp = Record[Idx++];
-  bool IsSigned = Tmp & 0x1;
-  bool IsSaturated = Tmp & 0x2;
-  bool HasUnsignedPadding = Tmp & 0x4;
-  return FixedPointSemantics(Width, Scale, IsSigned, IsSaturated,
-                             HasUnsignedPadding);
-}
-
-static const llvm::fltSemantics &
-readAPFloatSemantics(ASTRecordReader &reader) {
-  return llvm::APFloatBase::EnumToSemantics(
-    static_cast<llvm::APFloatBase::Semantics>(reader.readInt()));
-}
-
 APValue ASTRecordReader::readAPValue() {
-  unsigned Kind = readInt();
-  switch ((APValue::ValueKind) Kind) {
+  auto Kind = static_cast<APValue::ValueKind>(asImpl().readUInt32());
+  switch (Kind) {
   case APValue::None:
     return APValue();
   case APValue::Indeterminate:
     return APValue::IndeterminateValue();
   case APValue::Int:
-    return APValue(readAPSInt());
+    return APValue(asImpl().readAPSInt());
   case APValue::Float: {
-    const llvm::fltSemantics &FloatSema = readAPFloatSemantics(*this);
-    return APValue(readAPFloat(FloatSema));
+    const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
+        static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
+    return APValue(asImpl().readAPFloat(FloatSema));
   }
   case APValue::FixedPoint: {
-    FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx);
-    return APValue(APFixedPoint(readAPInt(), FPSema));
+    unsigned Width = asImpl().readUInt32();
+    unsigned Scale = asImpl().readUInt32();
+    unsigned Tmp = asImpl().readUInt32();
+    bool IsSigned = Tmp & 0x1;
+    bool IsSaturated = Tmp & 0x2;
+    bool HasUnsignedPadding = Tmp & 0x4;
+    FixedPointSemantics FPSema = FixedPointSemantics(
+        Width, Scale, IsSigned, IsSaturated, HasUnsignedPadding);
+    return APValue(APFixedPoint(asImpl().readAPInt(), FPSema));
   }
   case APValue::ComplexInt: {
-    llvm::APSInt First = readAPSInt();
-    return APValue(std::move(First), readAPSInt());
+    llvm::APSInt First = asImpl().readAPSInt();
+    return APValue(std::move(First), asImpl().readAPSInt());
   }
   case APValue::ComplexFloat: {
-    const llvm::fltSemantics &FloatSema1 = readAPFloatSemantics(*this);
+    const llvm::fltSemantics &FloatSema1 = llvm::APFloatBase::EnumToSemantics(
+        static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
     llvm::APFloat First = readAPFloat(FloatSema1);
-    const llvm::fltSemantics &FloatSema2 = readAPFloatSemantics(*this);
-    return APValue(std::move(First), readAPFloat(FloatSema2));
-  }
-  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();
+    const llvm::fltSemantics &FloatSema2 = llvm::APFloatBase::EnumToSemantics(
+        static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
+    return APValue(std::move(First), asImpl().readAPFloat(FloatSema2));
+  }
+  case APValue::Vector: {
+    APValue Result;
+    Result.MakeVector();
+    unsigned Length = asImpl().readUInt32();
+    Result.ReserveVector(Length);
+    for (unsigned LoopIdx = 0; LoopIdx < Length; LoopIdx++)
+      Result.getVectorElt(LoopIdx) = asImpl().readAPValue();
+    return Result;
+  }
+  case APValue::Array: {
+    APValue Result;
+    unsigned InitLength = asImpl().readUInt32();
+    unsigned TotalLength = asImpl().readUInt32();
+    Result.MakeArray(InitLength, TotalLength);
+    for (unsigned LoopIdx = 0; LoopIdx < InitLength; LoopIdx++)
+      Result.getArrayInitializedElt(LoopIdx) = asImpl().readAPValue();
+    return Result;
+  }
+  case APValue::Struct: {
+    APValue Result;
+    unsigned BasesLength = asImpl().readUInt32();
+    unsigned FieldsLength = asImpl().readUInt32();
+    Result.MakeStruct(BasesLength, FieldsLength);
+    for (unsigned LoopIdx = 0; LoopIdx < BasesLength; LoopIdx++)
+      Result.getStructBase(LoopIdx) = asImpl().readAPValue();
+    for (unsigned LoopIdx = 0; LoopIdx < FieldsLength; LoopIdx++)
+      Result.getStructField(LoopIdx) = asImpl().readAPValue();
+    return Result;
+  }
+  case APValue::Union: {
+    auto *FDecl = asImpl().readDeclAs<FieldDecl>();
+    APValue Value = asImpl().readAPValue();
+    return APValue(FDecl, std::move(Value));
+  }
+  case APValue::AddrLabelDiff: {
+    auto *LHS = cast<AddrLabelExpr>(asImpl().readExpr());
+    auto *RHS = cast<AddrLabelExpr>(asImpl().readExpr());
+    return APValue(LHS, RHS);
+  }
+  case APValue::MemberPointer: {
+    APValue Result;
+    bool IsDerived = asImpl().readUInt32();
+    auto *Member = asImpl().readDeclAs<ValueDecl>();
+    unsigned PathSize = asImpl().readUInt32();
+    Result.MakeEmptyMemberPointer(Member, IsDerived, PathSize);
+    const CXXRecordDecl **PathArray = Result.GetInternalMemberPointerPathPtr();
+    for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
+      PathArray[LoopIdx] = asImpl().readDeclAs<const CXXRecordDecl>();
+    return Result;
+  }
+  case APValue::LValue: {
+    uint64_t Bits = asImpl().readUInt32();
+    bool HasLValuePath = Bits & 0x1;
+    bool IsLValueOnePastTheEnd = Bits & 0x2;
+    bool IsExpr = Bits & 0x4;
+    bool IsTypeInfo = Bits & 0x8;
+    bool IsNullPtr = Bits & 0x10;
+    bool HasBase = Bits & 0x20;
+    APValue::LValueBase Base;
+    QualType ElemTy;
+    assert((!IsExpr || !IsTypeInfo) && "LValueBase cannot be both");
+    if (HasBase) {
+      if (!IsTypeInfo) {
+        unsigned CallIndex = asImpl().readUInt32();
+        unsigned Version = asImpl().readUInt32();
+        if (IsExpr) {
+          Base = APValue::LValueBase(asImpl().readExpr(), CallIndex, Version);
+          ElemTy = Base.get<const Expr *>()->getType();
+        } else {
+          Base = APValue::LValueBase(asImpl().readDeclAs<const ValueDecl>(),
+                                     CallIndex, Version);
+          ElemTy = Base.get<const ValueDecl *>()->getType();
+        }
+      } else {
+        QualType TypeInfo = asImpl().readType();
+        QualType Type = asImpl().readType();
+        Base = APValue::LValueBase::getTypeInfo(
+            TypeInfoLValue(TypeInfo.getTypePtr()), Type);
+        Base.getTypeInfoType();
+      }
+    }
+    CharUnits Offset = CharUnits::fromQuantity(asImpl().readUInt32());
+    unsigned PathLength = asImpl().readUInt32();
+    APValue Result;
+    Result.MakeLValue();
+    if (HasLValuePath) {
+      Result.SetLValueEmptyPath(Base, Offset, PathLength, IsLValueOnePastTheEnd,
+                                IsNullPtr);
+      APValue::LValuePathEntry *Path = Result.GetInternalLValuePathPtr();
+      for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+        if (ElemTy->getAs<RecordType>()) {
+          unsigned Int = asImpl().readUInt32();
+          Decl *D = asImpl().readDeclAs<Decl>();
+          if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+            ElemTy = getASTContext().getRecordType(RD);
+          else
+            ElemTy = cast<ValueDecl>(D)->getType();
+          Path[LoopIdx] =
+              APValue::LValuePathEntry(APValue::BaseOrMemberType(D, Int));
+        } else {
+          ElemTy = getASTContext().getAsArrayType(ElemTy)->getElementType();
+          Path[LoopIdx] =
+              APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32());
+        }
+      }
+    } else
+      Result.setLValue(Base, Offset, APValue::NoLValuePath{}, IsNullPtr);
+    return Result;
+  }
   }
   llvm_unreachable("Invalid APValue::ValueKind");
 }
@@ -10589,18 +10680,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) {
@@ -10613,6 +10692,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
@@ -11864,6 +11864,11 @@
         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
@@ -690,7 +690,7 @@
   if (Node->getResultAPValueKind() != APValue::None) {
     ColorScope Color(OS, ShowColors, ValueColor);
     OS << " ";
-    Node->getAPValueResult().dump(OS);
+    Node->getAPValueResult().dumpPretty(OS, Node->getType(), PrintPolicy);
   }
 }
 
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -269,6 +269,8 @@
 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)
     ::new (getTrailingObjects<APValue>()) APValue();
@@ -287,8 +289,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,
@@ -317,12 +318,14 @@
 }
 
 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;
+    llvm_unreachable("invalid APValue");
   case RSK_Int64:
     Int64Result() = *Value.getInt().getRawData();
     ConstantExprBits.BitWidth = Value.getInt().getBitWidth();
@@ -352,6 +355,10 @@
 }
 
 APValue ConstantExpr::getAPValueResult() const {
+  if (ConstantExprBits.APValueKind == APValue::None)
+    return APValue();
+  else if (ConstantExprBits.APValueKind == APValue::Indeterminate)
+    return APValue::IndeterminateValue();
   switch (ConstantExprBits.ResultKind) {
   case ConstantExpr::RSK_APValue:
     return APValueResult();
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -2387,6 +2387,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
@@ -6613,21 +6613,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) {
@@ -8897,6 +8891,198 @@
   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();
+    llvm::Expected<const Decl *> ImpFDecl = Import(FromValue.getUnionField());
+    if (!ImpFDecl) {
+      Error = ImpFDecl.takeError();
+      break;
+    }
+    llvm::Expected<APValue> ImpValue = Import(FromValue.getUnionValue());
+    if (!ImpValue) {
+      Error = ImpValue.takeError();
+      break;
+    }
+    Result.setUnion(cast<FieldDecl>(ImpFDecl.get()), ImpValue.get());
+    break;
+  }
+  case APValue::AddrLabelDiff: {
+    Result.MakeAddrLabelDiff();
+    llvm::Expected<Expr *> ImpLHS =
+        Import(const_cast<AddrLabelExpr *>(FromValue.getAddrLabelDiffLHS()));
+    if (!ImpLHS) {
+      Error = ImpLHS.takeError();
+      break;
+    }
+    llvm::Expected<Expr *> 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: {
+    llvm::Expected<const Decl *> 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();
+    const CXXRecordDecl **ToPath = Result.GetInternalMemberPointerPathPtr();
+    for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size();
+         Idx++) {
+      llvm::Expected<const Decl *> ImpDecl = Import(FromPath[Idx]);
+      if (!ImpDecl) {
+        Error = ImpDecl.takeError();
+        break;
+      }
+      ToPath[Idx] =
+          cast<const 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();
+          llvm::Expected<Expr *> 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();
+          llvm::Expected<const Decl *> 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();
+        llvm::Expected<QualType> ImpTypeInfo = Import(QualType(
+            FromValue.getLValueBase().get<TypeInfoLValue>().getType(), 0));
+        if (!ImpTypeInfo) {
+          Error = ImpTypeInfo.takeError();
+          break;
+        }
+        llvm::Expected<QualType> 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.GetInternalLValuePathPtr();
+      for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
+        if (FromElemTy->getAs<RecordType>()) {
+          const Decl *FromDecl =
+              FromPath[LoopIdx].getAsBaseOrMember().getPointer();
+          llvm::Expected<const Decl *> 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;
+}
+
 Expected<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
@@ -910,9 +910,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
@@ -470,9 +470,10 @@
   llvm_unreachable("Unknown APValue kind!");
 }
 
-void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
-                          QualType Ty) const {
-  switch (getKind()) {
+static void InternalPrinter(raw_ostream &Out, const APValue &Value, QualType Ty,
+                            const ASTContext *Ctx,
+                            const clang::PrintingPolicy &Policy) {
+  switch (Value.getKind()) {
   case APValue::None:
     Out << "<out of lifetime>";
     return;
@@ -481,33 +482,33 @@
     return;
   case APValue::Int:
     if (Ty->isBooleanType())
-      Out << (getInt().getBoolValue() ? "true" : "false");
+      Out << (Value.getInt().getBoolValue() ? "true" : "false");
     else
-      Out << getInt();
+      Out << Value.getInt();
     return;
   case APValue::Float:
-    Out << GetApproxValue(getFloat());
+    Out << GetApproxValue(Value.getFloat());
     return;
   case APValue::FixedPoint:
-    Out << getFixedPoint();
+    Out << Value.getFixedPoint();
     return;
   case APValue::Vector: {
     Out << '{';
     QualType ElemTy = Ty->castAs<VectorType>()->getElementType();
-    getVectorElt(0).printPretty(Out, Ctx, ElemTy);
-    for (unsigned i = 1; i != getVectorLength(); ++i) {
+    ::InternalPrinter(Out, Value.getVectorElt(0), ElemTy, Ctx, Policy);
+    for (unsigned i = 1; i != Value.getVectorLength(); ++i) {
       Out << ", ";
-      getVectorElt(i).printPretty(Out, Ctx, ElemTy);
+      ::InternalPrinter(Out, Value.getVectorElt(i), ElemTy, Ctx, Policy);
     }
     Out << '}';
     return;
   }
   case APValue::ComplexInt:
-    Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
+    Out << Value.getComplexIntReal() << "+" << Value.getComplexIntImag() << "i";
     return;
   case APValue::ComplexFloat:
-    Out << GetApproxValue(getComplexFloatReal()) << "+"
-        << GetApproxValue(getComplexFloatImag()) << "i";
+    Out << GetApproxValue(Value.getComplexFloatReal()) << "+"
+        << GetApproxValue(Value.getComplexFloatImag()) << "i";
     return;
   case APValue::LValue: {
     bool IsReference = Ty->isReferenceType();
@@ -516,28 +517,30 @@
     if (InnerTy.isNull())
       InnerTy = Ty;
 
-    LValueBase Base = getLValueBase();
+    APValue::LValueBase Base = Value.getLValueBase();
     if (!Base) {
-      if (isNullPointer()) {
-        Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0");
+      if (Value.isNullPointer()) {
+        Out << (Policy.UseNullptr ? "nullptr" : "NULL");
       } else if (IsReference) {
-        Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)"
-            << getLValueOffset().getQuantity();
+        Out << "*(" << InnerTy.stream(Policy) << "*)"
+            << Value.getLValueOffset().getQuantity();
       } else {
-        Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")"
-            << getLValueOffset().getQuantity();
+        Out << "(" << Ty.stream(Policy) << ")"
+            << Value.getLValueOffset().getQuantity();
       }
       return;
     }
 
-    if (!hasLValuePath()) {
+    if (!Value.hasLValuePath()) {
       // No lvalue path: just print the offset.
-      CharUnits O = getLValueOffset();
-      CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
+      CharUnits O = Value.getLValueOffset();
+      CharUnits S;
+      if (Ctx)
+        S = Ctx->getTypeSizeInChars(InnerTy);
       if (!O.isZero()) {
         if (IsReference)
           Out << "*(";
-        if (O % S) {
+        if (!Ctx || O % S) {
           Out << "(char*)";
           S = CharUnits::One();
         }
@@ -546,23 +549,21 @@
         Out << '&';
       }
 
-      if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
+      if (const auto *VD = Base.dyn_cast<const ValueDecl *>())
         Out << *VD;
       else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
-        TI.print(Out, Ctx.getPrintingPolicy());
+        TI.print(Out, Policy);
       } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {
-        Out << "{*new "
-            << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#"
+        Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#"
             << DA.getIndex() << "}";
       } else {
         assert(Base.get<const Expr *>() != nullptr &&
                "Expecting non-null Expr");
-        Base.get<const Expr*>()->printPretty(Out, nullptr,
-                                             Ctx.getPrintingPolicy());
+        Base.get<const Expr *>()->printPretty(Out, nullptr, Policy);
       }
 
       if (!O.isZero()) {
-        Out << " + " << (O / S);
+        Out << " + " << (Ctx ? (O / S) : O.getQuantity());
         if (IsReference)
           Out << ')';
       }
@@ -572,42 +573,44 @@
     // We have an lvalue path. Print it out nicely.
     if (!IsReference)
       Out << '&';
-    else if (isLValueOnePastTheEnd())
+    else if (Value.isLValueOnePastTheEnd())
       Out << "*(&";
 
     QualType ElemTy;
-    if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
+    bool IsRecord = false;
+    if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
       Out << *VD;
       ElemTy = VD->getType();
     } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
-      TI.print(Out, Ctx.getPrintingPolicy());
+      TI.print(Out, Policy);
       ElemTy = Base.getTypeInfoType();
     } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {
-      Out << "{*new "
-          << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#"
+      Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#"
           << DA.getIndex() << "}";
       ElemTy = Base.getDynamicAllocType();
     } else {
       const Expr *E = Base.get<const Expr*>();
       assert(E != nullptr && "Expecting non-null Expr");
-      E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
+      E->printPretty(Out, nullptr, Policy);
       // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue
       // adjustment.
       ElemTy = E->getType();
     }
 
-    ArrayRef<LValuePathEntry> Path = getLValuePath();
+    ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
     const CXXRecordDecl *CastToBase = nullptr;
     for (unsigned I = 0, N = Path.size(); I != N; ++I) {
-      if (ElemTy->getAs<RecordType>()) {
+      if (IsRecord || ElemTy->getAs<RecordType>()) {
+        IsRecord = false;
         // The lvalue refers to a class type, so the next path entry is a base
         // or member.
         const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
-        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+        if (const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
           CastToBase = RD;
-          ElemTy = Ctx.getRecordType(RD);
+          ElemTy = QualType();
+          IsRecord = true;
         } else {
-          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
+          const auto *VD = cast<ValueDecl>(BaseOrMember);
           Out << ".";
           if (CastToBase)
             Out << *CastToBase << "::";
@@ -617,12 +620,12 @@
       } else {
         // The lvalue must refer to an array.
         Out << '[' << Path[I].getAsArrayIndex() << ']';
-        ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
+        ElemTy = cast<ArrayType>(ElemTy.getCanonicalType())->getElementType();
       }
     }
 
     // Handle formatting of one-past-the-end lvalues.
-    if (isLValueOnePastTheEnd()) {
+    if (Value.isLValueOnePastTheEnd()) {
       // FIXME: If CastToBase is non-0, we should prefix the output with
       // "(CastToBase*)".
       Out << " + 1";
@@ -632,11 +635,12 @@
     return;
   }
   case APValue::Array: {
-    const ArrayType *AT = Ctx.getAsArrayType(Ty);
+    const auto *AT = cast<ArrayType>(Ty.getCanonicalType());
     QualType ElemTy = AT->getElementType();
     Out << '{';
-    if (unsigned N = getArrayInitializedElts()) {
-      getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
+    if (unsigned N = Value.getArrayInitializedElts()) {
+      ::InternalPrinter(Out, Value.getArrayInitializedElt(0), ElemTy, Ctx,
+                        Policy);
       for (unsigned I = 1; I != N; ++I) {
         Out << ", ";
         if (I == 10) {
@@ -644,7 +648,8 @@
           Out << "...";
           break;
         }
-        getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
+        ::InternalPrinter(Out, Value.getArrayInitializedElt(I), ElemTy, Ctx,
+                          Policy);
       }
     }
     Out << '}';
@@ -654,14 +659,15 @@
     Out << '{';
     const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();
     bool First = true;
-    if (unsigned N = getStructNumBases()) {
-      const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
+    if (unsigned N = Value.getStructNumBases()) {
+      const auto *CD = cast<CXXRecordDecl>(RD);
       CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
       for (unsigned I = 0; I != N; ++I, ++BI) {
         assert(BI != CD->bases_end());
         if (!First)
           Out << ", ";
-        getStructBase(I).printPretty(Out, Ctx, BI->getType());
+        ::InternalPrinter(Out, Value.getStructBase(I), BI->getType(), Ctx,
+                          Policy);
         First = false;
       }
     }
@@ -669,8 +675,8 @@
       if (!First)
         Out << ", ";
       if (FI->isUnnamedBitfield()) continue;
-      getStructField(FI->getFieldIndex()).
-        printPretty(Out, Ctx, FI->getType());
+      ::InternalPrinter(Out, Value.getStructField(FI->getFieldIndex()),
+                        FI->getType(), Ctx, Policy);
       First = false;
     }
     Out << '}';
@@ -678,30 +684,40 @@
   }
   case APValue::Union:
     Out << '{';
-    if (const FieldDecl *FD = getUnionField()) {
+    if (const FieldDecl *FD = Value.getUnionField()) {
       Out << "." << *FD << " = ";
-      getUnionValue().printPretty(Out, Ctx, FD->getType());
+      ::InternalPrinter(Out, Value.getUnionValue(), FD->getType(), Ctx, Policy);
     }
     Out << '}';
     return;
   case APValue::MemberPointer:
     // FIXME: This is not enough to unambiguously identify the member in a
     // multiple-inheritance scenario.
-    if (const ValueDecl *VD = getMemberPointerDecl()) {
+    if (const ValueDecl *VD = Value.getMemberPointerDecl()) {
       Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
       return;
     }
     Out << "0";
     return;
   case APValue::AddrLabelDiff:
-    Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
+    Out << "&&" << Value.getAddrLabelDiffLHS()->getLabel()->getName();
     Out << " - ";
-    Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
+    Out << "&&" << Value.getAddrLabelDiffRHS()->getLabel()->getName();
     return;
   }
   llvm_unreachable("Unknown APValue kind!");
 }
 
+void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
+                          QualType Ty) const {
+  ::InternalPrinter(Out, *this, Ty, &Ctx, Ctx.getPrintingPolicy());
+}
+
+void APValue::dumpPretty(raw_ostream &OS, QualType Ty,
+                         const clang::PrintingPolicy &Policy) const {
+  ::InternalPrinter(OS, *this, Ty, nullptr, Policy);
+}
+
 std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const {
   std::string Result;
   llvm::raw_string_ostream Out(Result);
@@ -771,6 +787,10 @@
   return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
 }
 
+APValue::LValuePathEntry *APValue::GetInternalLValuePathPtr() {
+  return ((LV *)(char *)Data.buffer)->getPath();
+}
+
 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
                         bool IsNullPtr) {
   assert(isLValue() && "Invalid accessor");
@@ -782,17 +802,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 {
@@ -829,13 +856,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 *));
+}
+
+const CXXRecordDecl **APValue::GetInternalMemberPointerPathPtr() {
+  return ((MemberPointerData *)(char *)Data.buffer)->getPath();
 }
Index: clang/include/clang/AST/PrettyPrinter.h
===================================================================
--- clang/include/clang/AST/PrettyPrinter.h
+++ clang/include/clang/AST/PrettyPrinter.h
@@ -58,9 +58,9 @@
         UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false),
         PolishForDeclaration(false), Half(LO.Half),
         MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
-        MSVCFormatting(false), ConstantsAsWritten(false),
-        SuppressImplicitBase(false), FullyQualifiedName(false),
-        PrintCanonicalTypes(false) {}
+        MSVCFormatting(false), UseNullptr(LO.CPlusPlus11),
+        ConstantsAsWritten(false), SuppressImplicitBase(false),
+        FullyQualifiedName(false), PrintCanonicalTypes(false) {}
 
   /// Adjust this printing policy for cases where it's known that we're
   /// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -209,6 +209,9 @@
   /// after template arguments.
   unsigned MSVCFormatting : 1;
 
+  /// Whether null pointers should be printed as nullptr or as NULL.
+  unsigned UseNullptr : 1;
+
   /// Whether we should print the constant expressions as written in the
   /// sources.
   ///
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -984,6 +984,8 @@
 
 public:
   /// Describes the kind of result that can be trail-allocated.
+  /// Enumerators need to stay ordered by size of their storage.
+  /// Smallest storage first.
   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/DeclBase.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/NestedNameSpecifier.h"
@@ -498,6 +499,13 @@
     /// "to" context, or the import error.
     llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec);
 
+    /// Import the given APValue from the "from" context into
+    /// the "to" context.
+    ///
+    /// \return the equivalent APValue in the "to" context 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
@@ -263,9 +263,6 @@
   /// Mapping from __block VarDecls to BlockVarCopyInit.
   llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
 
-  /// 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
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_AST_APVALUE_H
 #define LLVM_CLANG_AST_APVALUE_H
 
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/APFloat.h"
@@ -227,8 +228,9 @@
   struct UninitArray {};
   struct UninitStruct {};
 
-  friend class ASTReader;
+  friend class ASTRecordReader;
   friend class ASTWriter;
+  friend class ASTImporter;
 
 private:
   ValueKind Kind;
@@ -374,6 +376,10 @@
   void dump() const;
   void dump(raw_ostream &OS) const;
 
+  void dumpPretty(raw_ostream &OS, QualType Ty,
+                  const clang::PrintingPolicy &Policy =
+                      PrintingPolicy(LangOptions())) const;
+
   void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
   std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
 
@@ -553,9 +559,7 @@
     *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
   }
   void setVector(const APValue *E, unsigned N) {
-    assert(isVector() && "Invalid accessor");
-    ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
-    ((Vec*)(char*)Data.buffer)->NumElts = N;
+    ReserveVector(N);
     for (unsigned i = 0; i != N; ++i)
       ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
   }
@@ -646,6 +650,21 @@
     new ((void*)(char*)Data.buffer) AddrLabelDiffData();
     Kind = AddrLabelDiff;
   }
+
+  /// The following functions are used as part of initialization. during
+  /// Deserialization and Importing. Reserve the space then write element
+  /// directly in place as after importing/deserialization then.
+  void ReserveVector(unsigned N) {
+    assert(isVector() && "Invalid accessor");
+    ((Vec *)(char *)Data.buffer)->Elts = new APValue[N];
+    ((Vec *)(char *)Data.buffer)->NumElts = N;
+  }
+  void MakeEmptyMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+                              unsigned Size);
+  void SetLValueEmptyPath(LValueBase B, const CharUnits &O, unsigned Size,
+                          bool OnePastTheEnd, bool IsNullPtr);
+  const CXXRecordDecl **GetInternalMemberPointerPathPtr();
+  LValuePathEntry *GetInternalLValuePathPtr();
 };
 
 } // 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