bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
                                           const ASTContext &Context) {
  const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);
  // Non-C++ records are always trivially constructible.
  if (!ClassDecl)
    return true;
  // A class with a user-provided default constructor is not trivially
  // constructible.
  if (ClassDecl->hasUserProvidedDefaultConstructor())
    return false;
  // A class is trivially constructible if it has a trivial default constructor.
  if (ClassDecl->hasTrivialDefaultConstructor())
    return true;

  // If all its fields are trivially constructible.
  for (const FieldDecl *Field : ClassDecl->fields()) {
    if (!isTriviallyDefaultConstructible(Field->getType(), Context))
      return false;
  }
  // If all its direct bases are trivially constructible.
  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
    if (!isTriviallyDefaultConstructible(Base.getType(), Context))
      return false;
  }

  return true;
}
// Based on QualType::isTrivial.
bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
  if (Type.isNull())
    return false;

  if (Type->isArrayType())
    return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
                                           Context);

  // Return false for incomplete types after skipping any incomplete array
  // types which are expressly allowed by the standard and thus our API.
  if (Type->isIncompleteType())
    return false;

  if (Context.getLangOpts().ObjCAutoRefCount) {
    switch (Type.getObjCLifetime()) {
    case Qualifiers::OCL_ExplicitNone:
      return true;

    case Qualifiers::OCL_Strong:
    case Qualifiers::OCL_Weak:
    case Qualifiers::OCL_Autoreleasing:
      return false;

    case Qualifiers::OCL_None:
      if (Type->isObjCLifetimeType())
        return false;
      break;
    }
  }

  QualType CanonicalType = Type.getCanonicalType();
  if (CanonicalType->isDependentType())
    return false;

  // As an extension, Clang treats vector types as Scalar types.
  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
    return true;

  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
    return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
  }

  // No other types can match.
  return false;
}
void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
  auto Construct =
      cxxConstructExpr(
          hasDeclaration(cxxConstructorDecl(hasParent(
              cxxRecordDecl(unless(isTriviallyDefaultConstructible()))))))
          .bind("construct");

  Finder->addMatcher(
      cxxConstructorDecl(
          unless(isDelegatingConstructor()),
          ofClass(unless(
              anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))),
          forEachConstructorInitializer(
              cxxCtorInitializer(isWritten(),
                                 withInitializer(ignoringImplicit(Construct)),
                                 unless(forField(hasType(isConstQualified()))))
                  .bind("init"))),
      this);
}