Commit 997a719d authored by Richard Smith's avatar Richard Smith
Browse files

PR48434: Work around crashes due to deserialization cycles via typedefs.

Ensure that we can deserialize a TypedefType even while in the middle of
deserializing its TypedefDecl, by removing the need to look at the
TypedefDecl while constructing the TypedefType.

This fixes all the currently-known failures for PR48434, but it's not a
complete fix, because we can still trigger deserialization cycles, which
are not supposed to happen.
parent baef18df
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1430,7 +1430,7 @@ public:
  /// Return the unique reference to the type for the specified
  /// typedef-name decl.
  QualType getTypedefType(const TypedefNameDecl *Decl,
                          QualType Canon = QualType()) const;
                          QualType Underlying = QualType()) const;

  QualType getRecordType(const RecordDecl *Decl) const;

+3 −2
Original line number Diff line number Diff line
@@ -4362,10 +4362,11 @@ public:
class TypedefType : public Type {
  TypedefNameDecl *Decl;

protected:
private:
  friend class ASTContext; // ASTContext creates these.

  TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can);
  TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying,
              QualType can);

public:
  TypedefNameDecl *getDecl() const { return Decl; }
+6 −2
Original line number Diff line number Diff line
@@ -484,8 +484,12 @@ let Class = TagType in {
    let Read = [{ node->isDependentType() }];
  }
  def : Property<"declaration", DeclRef> {
    // Serializing a reference to the canonical declaration is apparently
    // necessary to make module-merging work.
    // We don't know which declaration was originally referenced here, and we
    // cannot reference a declaration that follows the use (because that can
    // introduce deserialization cycles), so conservatively generate a
    // reference to the first declaration.
    // FIXME: If this is a reference to a class template specialization, that
    // can still introduce a deserialization cycle.
    let Read = [{ node->getDecl()->getCanonicalDecl() }];
  }
}
+6 −6
Original line number Diff line number Diff line
@@ -4449,15 +4449,15 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {

/// getTypedefType - Return the unique reference to the type for the
/// specified typedef name decl.
QualType
ASTContext::getTypedefType(const TypedefNameDecl *Decl,
                           QualType Canonical) const {
QualType ASTContext::getTypedefType(const TypedefNameDecl *Decl,
                                    QualType Underlying) const {
  if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);

  if (Canonical.isNull())
    Canonical = getCanonicalType(Decl->getUnderlyingType());
  if (Underlying.isNull())
    Underlying = Decl->getUnderlyingType();
  QualType Canonical = getCanonicalType(Underlying);
  auto *newType = new (*this, TypeAlignment)
    TypedefType(Type::Typedef, Decl, Canonical);
      TypedefType(Type::Typedef, Decl, Underlying, Canonical);
  Decl->TypeForDecl = newType;
  Types.push_back(newType);
  return QualType(newType, 0);
+3 −2
Original line number Diff line number Diff line
@@ -3369,8 +3369,9 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
          getExtProtoInfo(), Ctx, isCanonicalUnqualified());
}

TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
    : Type(tc, can, D->getUnderlyingType()->getDependence()),
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D,
                         QualType underlying, QualType can)
    : Type(tc, can, underlying->getDependence()),
      Decl(const_cast<TypedefNameDecl *>(D)) {
  assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
Loading