This revision was automatically updated to reflect the committed changes.
Closed by commit rG37e83bc6db3a: [NFC] Move readAPValue/writeAPValue up the 
inheritance hierarchy (authored by varungandhi-apple).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94196

Files:
  clang/include/clang/AST/APValue.h
  clang/include/clang/AST/AbstractBasicReader.h
  clang/include/clang/AST/AbstractBasicWriter.h
  clang/include/clang/AST/PropertiesBase.td
  clang/include/clang/Serialization/ASTRecordReader.h
  clang/include/clang/Serialization/ASTRecordWriter.h
  clang/include/clang/Serialization/ASTWriter.h
  clang/lib/AST/APValue.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/utils/TableGen/ClangASTPropertiesEmitter.cpp

Index: clang/utils/TableGen/ClangASTPropertiesEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangASTPropertiesEmitter.cpp
+++ clang/utils/TableGen/ClangASTPropertiesEmitter.cpp
@@ -708,15 +708,13 @@
   // Emit the Basic{Reader,Writer}Base template.
   Out << "template <class Impl>\n"
          "class Basic" << info.ClassSuffix << "Base {\n";
-  if (info.IsReader)
-    Out << "  ASTContext &C;\n";
+  Out << "  ASTContext &C;\n";
   Out << "protected:\n"
-         "  Basic" << info.ClassSuffix << "Base"
-                   << (info.IsReader ? "(ASTContext &ctx) : C(ctx)" : "()")
-                   << " {}\n"
+         "  Basic"
+      << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)")
+      << " {}\n"
          "public:\n";
-  if (info.IsReader)
-    Out << "  ASTContext &getASTContext() { return C; }\n";
+  Out << "  ASTContext &getASTContext() { return C; }\n";
   Out << "  Impl &asImpl() { return static_cast<Impl&>(*this); }\n";
 
   auto enterReaderWriterMethod = [&](StringRef cxxTypeName,
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -5121,144 +5121,6 @@
   AddAPInt(Value.bitcastToAPInt());
 }
 
-static void WriteFixedPointSemantics(ASTRecordWriter &Record,
-                                     llvm::FixedPointSemantics FPSema) {
-  Record.push_back(FPSema.getWidth());
-  Record.push_back(FPSema.getScale());
-  Record.push_back(FPSema.isSigned() | FPSema.isSaturated() << 1 |
-                   FPSema.hasUnsignedPadding() << 2);
-}
-
-void ASTRecordWriter::AddAPValue(const APValue &Value) {
-  APValue::ValueKind Kind = Value.getKind();
-  push_back(static_cast<uint64_t>(Kind));
-  switch (Kind) {
-  case APValue::None:
-  case APValue::Indeterminate:
-    return;
-  case APValue::Int:
-    AddAPSInt(Value.getInt());
-    return;
-  case APValue::Float:
-    push_back(static_cast<uint64_t>(
-        llvm::APFloatBase::SemanticsToEnum(Value.getFloat().getSemantics())));
-    AddAPFloat(Value.getFloat());
-    return;
-  case APValue::FixedPoint: {
-    WriteFixedPointSemantics(*this, Value.getFixedPoint().getSemantics());
-    AddAPSInt(Value.getFixedPoint().getValue());
-    return;
-  }
-  case APValue::ComplexInt: {
-    AddAPSInt(Value.getComplexIntReal());
-    AddAPSInt(Value.getComplexIntImag());
-    return;
-  }
-  case APValue::ComplexFloat: {
-    assert(llvm::APFloatBase::SemanticsToEnum(
-               Value.getComplexFloatImag().getSemantics()) ==
-           llvm::APFloatBase::SemanticsToEnum(
-               Value.getComplexFloatReal().getSemantics()));
-    push_back(static_cast<uint64_t>(llvm::APFloatBase::SemanticsToEnum(
-        Value.getComplexFloatReal().getSemantics())));
-    AddAPFloat(Value.getComplexFloatReal());
-    AddAPFloat(Value.getComplexFloatImag());
-    return;
-  }
-  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));
-    if (Value.hasArrayFiller())
-      AddAPValue(Value.getArrayFiller());
-    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:
-    AddDeclRef(Value.getUnionField());
-    AddAPValue(Value.getUnionValue());
-    return;
-  case APValue::AddrLabelDiff:
-    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()) {
-      assert(!Value.getLValueBase().is<DynamicAllocLValue>() &&
-             "in C++20 dynamic allocation are transient so they shouldn't "
-             "appear in the AST");
-      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");
-}
-
 void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {
   Record.push_back(getIdentifierRef(II));
 }
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -8941,165 +8941,6 @@
   return SourceRange(beg, end);
 }
 
-static llvm::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 llvm::FixedPointSemantics(Width, Scale, IsSigned, IsSaturated,
-                                   HasUnsignedPadding);
-}
-
-APValue ASTRecordReader::readAPValue() {
-  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(asImpl().readAPSInt());
-  case APValue::Float: {
-    const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
-        static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
-    return APValue(asImpl().readAPFloat(FloatSema));
-  }
-  case APValue::FixedPoint: {
-    llvm::FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx);
-    return APValue(llvm::APFixedPoint(readAPInt(), FPSema));
-  }
-  case APValue::ComplexInt: {
-    llvm::APSInt First = asImpl().readAPSInt();
-    return APValue(std::move(First), asImpl().readAPSInt());
-  }
-  case APValue::ComplexFloat: {
-    const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
-        static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
-    llvm::APFloat First = readAPFloat(FloatSema);
-    return APValue(std::move(First), asImpl().readAPFloat(FloatSema));
-  }
-  case APValue::Vector: {
-    APValue Result;
-    Result.MakeVector();
-    unsigned Length = asImpl().readUInt32();
-    (void)Result.setVectorUninit(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();
-    if (Result.hasArrayFiller())
-      Result.getArrayFiller() = 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();
-    const CXXRecordDecl **PathArray =
-        Result.setMemberPointerUninit(Member, IsDerived, PathSize).data();
-    for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
-      PathArray[LoopIdx] =
-          asImpl().readDeclAs<const CXXRecordDecl>()->getCanonicalDecl();
-    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) {
-      APValue::LValuePathEntry *Path =
-          Result
-              .setLValueUninit(Base, Offset, PathLength, IsLValueOnePastTheEnd,
-                               IsNullPtr)
-              .data();
-      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");
-}
-
 /// Read a floating-point value
 llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
   return llvm::APFloat(Sem, readAPInt());
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -154,6 +154,14 @@
   ID.AddInteger(Value);
 }
 
+APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(
+    ArrayRef<LValuePathEntry> Path, QualType ElemTy)
+    : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {}
+
+QualType APValue::LValuePathSerializationHelper::getType() {
+  return QualType::getFromOpaquePtr(ElemTy);
+}
+
 namespace {
   struct LVBase {
     APValue::LValueBase Base;
Index: clang/include/clang/Serialization/ASTWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTWriter.h
+++ clang/include/clang/Serialization/ASTWriter.h
@@ -555,6 +555,11 @@
             bool IncludeTimestamps = true);
   ~ASTWriter() override;
 
+  ASTContext &getASTContext() const {
+    assert(Context && "requested AST context when not writing AST");
+    return *Context;
+  }
+
   const LangOptions &getLangOpts() const;
 
   /// Get a timestamp for output into the AST file. The actual timestamp
Index: clang/include/clang/Serialization/ASTRecordWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTRecordWriter.h
+++ clang/include/clang/Serialization/ASTRecordWriter.h
@@ -55,13 +55,14 @@
 
 public:
   /// Construct a ASTRecordWriter that uses the default encoding scheme.
-  ASTRecordWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
-      : Writer(&Writer), Record(&Record) {}
+  ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record)
+      : DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {}
 
   /// Construct a ASTRecordWriter that uses the same encoding scheme as another
   /// ASTRecordWriter.
   ASTRecordWriter(ASTRecordWriter &Parent, ASTWriter::RecordDataImpl &Record)
-      : Writer(Parent.Writer), Record(&Record) {}
+      : DataStreamBasicWriter(Parent.getASTContext()), Writer(Parent.Writer),
+        Record(&Record) {}
 
   /// Copying an ASTRecordWriter is almost certainly a bug.
   ASTRecordWriter(const ASTRecordWriter &) = delete;
@@ -165,7 +166,7 @@
   void AddAPFloat(const llvm::APFloat &Value);
 
   /// Emit an APvalue.
-  void AddAPValue(const APValue &Value);
+  void AddAPValue(const APValue &Value) { writeAPValue(Value); }
 
   /// Emit a reference to an identifier.
   void AddIdentifierRef(const IdentifierInfo *II) {
Index: clang/include/clang/Serialization/ASTRecordReader.h
===================================================================
--- clang/include/clang/Serialization/ASTRecordReader.h
+++ clang/include/clang/Serialization/ASTRecordReader.h
@@ -281,7 +281,7 @@
   }
 
   /// Read an arbitrary constant value, advancing Idx.
-  APValue readAPValue();
+  // APValue readAPValue(); (inherited)
 
   /// Read an integral value, advancing Idx.
   // llvm::APInt readAPInt(); (inherited)
Index: clang/include/clang/AST/PropertiesBase.td
===================================================================
--- clang/include/clang/AST/PropertiesBase.td
+++ clang/include/clang/AST/PropertiesBase.td
@@ -72,6 +72,8 @@
 
 def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
 def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
+def APValue : PropertyType { let PassByReference = 1; }
+def APValueKind : EnumPropertyType<"APValue::ValueKind">;
 def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
 def AttrKind : EnumPropertyType<"attr::Kind">;
 def AutoTypeKeyword : EnumPropertyType;
@@ -109,7 +111,15 @@
     SubclassPropertyType<"ValueDecl", DeclRef>;
 def ElaboratedTypeKeyword : EnumPropertyType;
 def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
+def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
+  let PassByReference = 1;
+}
 def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
+def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
+def LValuePathSerializationHelper :
+    PropertyType<"APValue::LValuePathSerializationHelper"> {
+  let BufferElementTypes = [ LValuePathEntry ];
+}
 def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
 def NestedNameSpecifierKind :
   EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
@@ -237,6 +247,304 @@
   string Name = name;
 }
 
+// Type cases for APValue.
+def : PropertyTypeKind<APValue, APValueKind,
+                       "node.getKind()">;
+let Class = PropertyTypeCase<APValue, "None"> in {
+  def : Creator<[{ return APValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Indeterminate"> in {
+  def : Creator<[{ return APValue::IndeterminateValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Int"> in {
+  def : Property<"value", APSInt> {
+    let Read = [{ node.getInt() }];
+  }
+  def : Creator<[{ return APValue(value); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Float"> in {
+  def : Property<"semantics", UInt32> {
+    let Read = [{
+      static_cast<uint32_t>(
+        llvm::APFloatBase::SemanticsToEnum(node.getFloat().getSemantics()))
+    }];
+  }
+  def : Property<"value", APInt> {
+    let Read = [{ node.getFloat().bitcastToAPInt() }];
+  }
+  def : Creator<[{
+    const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics(
+        static_cast<llvm::APFloatBase::Semantics>(semantics));
+    return APValue(llvm::APFloat(floatSema, value));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "FixedPoint"> in {
+  def : Property<"semantics", FixedPointSemantics> {
+    let Read = [{ node.getFixedPoint().getSemantics() }];
+  }
+  def : Property<"value", APSInt> {
+    let Read = [{ node.getFixedPoint().getValue() }];
+  }
+  def : Creator<[{
+    return APValue(llvm::APFixedPoint(std::move(value), semantics));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "ComplexInt"> in {
+  def : Property<"real", APSInt> {
+    let Read = [{ node.getComplexIntReal() }];
+  }
+  def : Property<"imag", APSInt> {
+    let Read = [{ node.getComplexIntImag() }];
+  }
+  def : Creator<[{ return APValue(real, imag); }]>;
+}
+let Class = PropertyTypeCase<APValue, "ComplexFloat"> in {
+  def : ReadHelper<[{
+    auto sema = llvm::APFloatBase::SemanticsToEnum(
+        node.getComplexFloatReal().getSemantics());
+    assert(sema == llvm::APFloatBase::SemanticsToEnum(
+        node.getComplexFloatImag().getSemantics()));
+  }]>;
+  def : Property<"semantics", UInt32> {
+    let Read = [{ static_cast<uint32_t>(sema) }];
+  }
+  def : Property<"real", APInt> {
+    let Read = [{ node.getComplexFloatReal().bitcastToAPInt() }];
+  }
+  def : Property<"imag", APInt> {
+    let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }];
+  }
+  def : Creator<[{
+    const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics(
+        static_cast<llvm::APFloatBase::Semantics>(semantics));
+    return APValue(llvm::APFloat(sema, real),
+                   llvm::APFloat(sema, imag));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "Vector"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> buffer;
+    unsigned len = node.getVectorLength();
+    for (unsigned i = 0; i < len; ++i)
+      buffer.push_back(node.getVectorElt(i));
+  }]>;
+  def : Property<"elements", Array<APValue>> {
+    let Read = [{ buffer }];
+  }
+  def : Creator<[{
+    APValue result;
+    result.MakeVector();
+    unsigned length = elements.size();
+    (void)result.setVectorUninit(length);
+    for (unsigned i = 0; i < length; i++)
+      result.getVectorElt(i) = elements[i];
+    return result;
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "Array"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> buffer{};
+    unsigned initLength = node.getArrayInitializedElts();
+    for (unsigned i = 0; i < initLength; ++i)
+      buffer.push_back(node.getArrayInitializedElt(i));
+    if (node.hasArrayFiller())
+      buffer.push_back(node.getArrayFiller());
+  }]>;
+  def : Property<"totalLength", UInt32> {
+    let Read = [{ node.getArraySize() }];
+  }
+  def : Property<"hasFiller", Bool> {
+    let Read = [{ node.hasArrayFiller() }];
+  }
+  def : Property<"elements", Array<APValue>> {
+    let Read = [{ buffer }];
+  }
+  def : Creator<[{
+    APValue result;
+    unsigned initLength = elements.size() - (hasFiller ? 1 : 0);
+    result.MakeArray(initLength, totalLength);
+    for (unsigned i = 0; i < initLength; ++i)
+      result.getArrayInitializedElt(i) = elements[i];
+    if (hasFiller)
+      result.getArrayFiller() = elements.back();
+    return result;
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "Struct"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> structBases;
+    unsigned numBases = node.getStructNumBases();
+    for (unsigned i = 0; i < numBases; ++i)
+      structBases.push_back(node.getStructBase(i));
+    SmallVector<APValue, 4> structFields;
+    unsigned numFields = node.getStructNumFields();
+    for (unsigned i = 0; i < numFields; ++i)
+      structFields.push_back(node.getStructField(i));
+  }]>;
+  def : Property<"bases", Array<APValue>> {
+    let Read = [{ structBases }];
+  }
+  def : Property<"fields", Array<APValue>> {
+    let Read = [{ structFields }];
+  }
+  def : Creator<[{
+    APValue result;
+    result.MakeStruct(bases.size(), fields.size());
+    for (unsigned i = 0; i < bases.size(); ++i)
+      result.getStructBase(i) = bases[i];
+    for (unsigned i = 0; i < fields.size(); ++i)
+      result.getStructField(i) = fields[i];
+    return result;
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "Union"> in {
+  def : Property<"fieldDecl", DeclRef> {
+    let Read = [{ node.getUnionField() }];
+  }
+  def : Property<"value", APValue> {
+    let Read = [{ node.getUnionValue() }];
+  }
+  def : Creator<[{
+    return APValue(cast<clang::FieldDecl>(fieldDecl), std::move(value));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "AddrLabelDiff"> in {
+  def : Property<"lhs", StmtRef> {
+    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffLHS()) }];
+  }
+  def : Property<"rhs", StmtRef> {
+    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffRHS()) }];
+  }
+  def : Creator<[{
+    return APValue(cast<AddrLabelExpr>(lhs), cast<AddrLabelExpr>(rhs));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "MemberPointer"> in {
+  def : Property<"isDerived", Bool> {
+    let Read = [{ node.isMemberPointerToDerivedMember() }];
+  }
+  def : Property<"member", ValueDeclRef> {
+    let Read = [{ node.getMemberPointerDecl() }];
+  }
+  def : Property<"memberPath", Array<CXXRecordDeclRef>> {
+    let Read = [{ node.getMemberPointerPath() }];
+  }
+  def : Creator<[{
+    APValue result;
+    unsigned pathSize = memberPath.size();
+    const CXXRecordDecl **pathArray =
+        result.setMemberPointerUninit(member, isDerived, pathSize).data();
+    for (unsigned i = 0; i < pathSize; ++i)
+      pathArray[i] = memberPath[i]->getCanonicalDecl();
+    return result;
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "LValue"> in {
+  def : ReadHelper<[{
+    auto lvalueBase = node.getLValueBase();
+    const Expr *expr =
+        lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
+    bool lvalueBaseIsExpr = (bool) expr;
+    bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
+    QualType elemTy;
+    if (lvalueBase) {
+      if (lvalueBaseIsTypeInfo) {
+        elemTy = lvalueBase.getTypeInfoType();
+      } else if (lvalueBaseIsExpr) {
+        elemTy = expr->getType();
+      } else {
+        elemTy = lvalueBase.get<const ValueDecl *>()->getType();
+      }
+    }
+  }]>;
+  def : Property<"hasLValuePath", Bool> {
+    let Read = [{ node.hasLValuePath() }];
+  }
+  def : Property<"isLValueOnePastTheEnd", Bool> {
+    let Read = [{ node.isLValueOnePastTheEnd() }];
+  }
+  def : Property<"isExpr", Bool> {
+    let Read = [{ lvalueBaseIsExpr }];
+  }
+  def : Property<"isTypeInfo", Bool> {
+    let Read = [{ lvalueBaseIsTypeInfo }];
+  }
+  def : Property<"hasBase", Bool> {
+    let Read = [{ static_cast<bool>(lvalueBase) }];
+  }
+  def : Property<"isNullPtr", Bool> {
+    let Read = [{ node.isNullPointer() }];
+  }
+  def : Property<"typeInfo", QualType> {
+    let Conditional = [{ hasBase && isTypeInfo }];
+    let Read = [{
+      QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0)
+    }];
+  }
+  def : Property<"type", QualType> {
+    let Conditional = [{ hasBase && isTypeInfo }];
+    let Read = [{ node.getLValueBase().getTypeInfoType() }];
+  }
+  def : Property<"callIndex", UInt32> {
+    let Conditional = [{ hasBase && !isTypeInfo }];
+    let Read = [{ node.getLValueBase().getCallIndex() }];
+  }
+  def : Property<"version", UInt32> {
+    let Conditional = [{ hasBase && !isTypeInfo }];
+    let Read = [{ node.getLValueBase().getVersion() }];
+  }
+  def : Property<"stmt", StmtRef> {
+    let Conditional = [{ hasBase && !isTypeInfo && isExpr }];
+    let Read = [{ const_cast<Expr *>(expr) }];
+  }
+  def : Property<"decl", DeclRef> {
+    let Conditional = [{ hasBase && !isTypeInfo && !isExpr }];
+    let Read = [{ lvalueBase.get<const ValueDecl *>() }];
+  }
+  def : Property<"offsetQuantity", UInt32> {
+    let Read = [{ node.getLValueOffset().getQuantity() }];
+  }
+  def : Property<"lvaluePath", LValuePathSerializationHelper> {
+    let Conditional = [{ hasLValuePath }];
+    let Read = [{
+      APValue::LValuePathSerializationHelper(node.getLValuePath(), elemTy)
+    }];
+  }
+  def : Creator<[{
+    (void)ctx;
+    APValue::LValueBase base;
+    QualType elemTy;
+    if (hasBase) {
+      if (isTypeInfo) {
+        base = APValue::LValueBase::getTypeInfo(
+            TypeInfoLValue(typeInfo.getValue().getTypePtr()), type.getValue());
+        elemTy = base.getTypeInfoType();
+      } else if (isExpr) {
+        base = APValue::LValueBase(cast<Expr>(stmt.getValue()),
+                                   callIndex.getValue(), version.getValue());
+        elemTy = base.get<const Expr *>()->getType();
+      } else {
+        base = APValue::LValueBase(cast<ValueDecl>(decl.getValue()),
+                                   callIndex.getValue(), version.getValue());
+        elemTy = base.get<const ValueDecl *>()->getType();
+      }
+    }
+    CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
+    APValue result;
+    result.MakeLValue();
+    if (!hasLValuePath) {
+      result.setLValue(base, offset, APValue::NoLValuePath{}, isNullPtr);
+      return result;
+    }
+    auto pathLength = lvaluePath->Path.size();
+    APValue::LValuePathEntry *path = result.setLValueUninit(
+        base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
+    assert(lvaluePath->getType() == elemTy && "Unexpected type reference!");
+    llvm::copy(lvaluePath->Path, path);
+    return result;
+  }]>;
+}
+
 // Type cases for DeclarationName.
 def : PropertyTypeKind<DeclarationName, DeclarationNameKind,
                        "node.getNameKind()">;
Index: clang/include/clang/AST/AbstractBasicWriter.h
===================================================================
--- clang/include/clang/AST/AbstractBasicWriter.h
+++ clang/include/clang/AST/AbstractBasicWriter.h
@@ -9,6 +9,7 @@
 #ifndef CLANG_AST_ABSTRACTBASICWRITER_H
 #define CLANG_AST_ABSTRACTBASICWRITER_H
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclTemplate.h"
 
 namespace clang {
@@ -121,6 +122,7 @@
 class DataStreamBasicWriter : public BasicWriterBase<Impl> {
 protected:
   using BasicWriterBase<Impl>::asImpl;
+  DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
 
 public:
   /// Implement property-find by ignoring it.  We rely on properties being
@@ -163,6 +165,39 @@
       asImpl().writeUInt64(words[i]);
   }
 
+  void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
+    asImpl().writeUInt32(sema.getWidth());
+    asImpl().writeUInt32(sema.getScale());
+    asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
+                         sema.hasUnsignedPadding() << 2);
+  }
+
+  void writeLValuePathSerializationHelper(
+      APValue::LValuePathSerializationHelper lvaluePath) {
+    ArrayRef<APValue::LValuePathEntry> path = lvaluePath.Path;
+    QualType elemTy = lvaluePath.getType();
+    asImpl().writeQualType(elemTy);
+    asImpl().writeUInt32(path.size());
+    auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
+    for (auto elem : path) {
+      if (elemTy->getAs<RecordType>()) {
+        asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
+        const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
+        if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
+          asImpl().writeDeclRef(recordDecl);
+          elemTy = ctx.getRecordType(recordDecl);
+        } else {
+          const auto *valueDecl = cast<ValueDecl>(baseOrMember);
+          asImpl().writeDeclRef(valueDecl);
+          elemTy = valueDecl->getType();
+        }
+      } else {
+        asImpl().writeUInt32(elem.getAsArrayIndex());
+        elemTy = ctx.getAsArrayType(elemTy)->getElementType();
+      }
+    }
+  }
+
   void writeQualifiers(Qualifiers value) {
     static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
                   "update this if the value size changes");
Index: clang/include/clang/AST/AbstractBasicReader.h
===================================================================
--- clang/include/clang/AST/AbstractBasicReader.h
+++ clang/include/clang/AST/AbstractBasicReader.h
@@ -177,6 +177,40 @@
     return llvm::APInt(bitWidth, numWords, &data[0]);
   }
 
+  llvm::FixedPointSemantics readFixedPointSemantics() {
+    unsigned width = asImpl().readUInt32();
+    unsigned scale = asImpl().readUInt32();
+    unsigned tmp = asImpl().readUInt32();
+    bool isSigned = tmp & 0x1;
+    bool isSaturated = tmp & 0x2;
+    bool hasUnsignedPadding = tmp & 0x4;
+    return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
+                                     hasUnsignedPadding);
+  }
+
+  APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
+      SmallVectorImpl<APValue::LValuePathEntry> &path) {
+    auto elemTy = asImpl().readQualType();
+    unsigned pathLength = asImpl().readUInt32();
+    for (unsigned i = 0; i < pathLength; ++i) {
+      if (elemTy->template getAs<RecordType>()) {
+        unsigned int_ = asImpl().readUInt32();
+        Decl *decl = asImpl().template readDeclAs<Decl>();
+        if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
+          elemTy = getASTContext().getRecordType(recordDecl);
+        else
+          elemTy = cast<ValueDecl>(decl)->getType();
+        path.push_back(
+            APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
+      } else {
+        elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
+        path.push_back(
+            APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
+      }
+    }
+    return APValue::LValuePathSerializationHelper(path, elemTy);
+  }
+
   Qualifiers readQualifiers() {
     static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
                   "update this if the value size changes");
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -23,6 +23,10 @@
 #include "llvm/Support/AlignOf.h"
 
 namespace clang {
+namespace serialization {
+template <typename T> class BasicReaderBase;
+} // end namespace serialization
+
   class AddrLabelExpr;
   class ASTContext;
   class CharUnits;
@@ -233,12 +237,20 @@
       return llvm::hash_value(A.Value);
     }
   };
+  class LValuePathSerializationHelper {
+    const void *ElemTy;
+
+  public:
+    ArrayRef<LValuePathEntry> Path;
+
+    LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
+    QualType getType();
+  };
   struct NoLValuePath {};
   struct UninitArray {};
   struct UninitStruct {};
 
-  friend class ASTRecordReader;
-  friend class ASTWriter;
+  template <typename Impl> friend class clang::serialization::BasicReaderBase;
   friend class ASTImporter;
   friend class ASTNodeImporter;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to