[NFC] Move readAPValue/writeAPValue up the inheritance hierarchy
authorVarun Gandhi <varun_gandhi@apple.com>
Wed, 6 Jan 2021 22:34:20 +0000 (14:34 -0800)
committerVarun Gandhi <varun_gandhi@apple.com>
Thu, 7 Jan 2021 00:44:50 +0000 (16:44 -0800)
The implementation for (de)serialization of APValues can be shared
between Clang and Swift, so we prefer pushing the methods up
the inheritance hierarchy, instead of having the methods live in
ASTReader/ASTWriter. Fixes rdar://72592937.

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D94196

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 eded34808ad7eaa5e7583b933eade98c972c8a34..f9b189926c76f98c98c210c57617866ae2cbec29 100644 (file)
 #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 @@ public:
       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;
 
index d7b3a9da88ec2e8da560d80318ec04221fcd554b..5505d661b44e2b411e04966664501f1bc0ea5909 100644 (file)
@@ -177,6 +177,40 @@ public:
     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 0a6730c86bbfee0aa699aa4f3436165242c91731..75aef734ba9b51d3637f3eb4211138ca47983b14 100644 (file)
@@ -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 @@ template <class Impl>
 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 @@ public:
       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 ba0f237a3bc3c921f9f5a47c1e7d333ccbbef9b7..a087cb406b290d5015dc7290a6de71929c4552e9 100644 (file)
@@ -72,6 +72,8 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
 
 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 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
     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 @@ class PropertyTypeCase<PropertyType type, string name> : HasProperties {
   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 3912ffe5e6b9183da9788ece75a61c547e840eb6..b85609bf4e05bc8db5a967d5327b17fb1b623597 100644 (file)
@@ -281,7 +281,7 @@ public:
   }
 
   /// Read an arbitrary constant value, advancing Idx.
-  APValue readAPValue();
+  // APValue readAPValue(); (inherited)
 
   /// Read an integral value, advancing Idx.
   // llvm::APInt readAPInt(); (inherited)
index e362463b2309637dfc6e977581b7c73471937619..0dc69bd3f3bdd70a17d7cc6d317749bcf555b21a 100644 (file)
@@ -55,13 +55,14 @@ class ASTRecordWriter
 
 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 @@ public:
   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 7a6664af65d894dbbdc47c2e26690a7cde957683..02fd72f77337660bab377b83c2240f8a496c5645 100644 (file)
@@ -555,6 +555,11 @@ public:
             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 c18f8854dc2b677d206488109f248028121c3c55..9a9233bc1ea7484ecf6bfb2d8c3027e0c943695f 100644 (file)
@@ -154,6 +154,14 @@ void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const {
   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 b48b23ce4a51f97a1b2d13a703d2c8cd75c8e5ca..eda286c454654a870c087b10fee579be0e0e978d 100644 (file)
@@ -8941,165 +8941,6 @@ ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
   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 3a281e492fde7e53104851e704400e4ed09c6d0e..27d41df28975ad152cf61c8469afc939f17d65fc 100644 (file)
@@ -5121,144 +5121,6 @@ void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) {
   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 256ca42e9aab9f8b4942210559945b8bce5e3fc3..caced02e1e1109e1d0d55ef40cea356a6bfa3cec 100644 (file)
@@ -708,15 +708,13 @@ ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) {
   // 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,