void MustOverrideChecker::check(const MatchFinder::MatchResult &Result) {
  auto D = Result.Nodes.getNodeAs<CXXRecordDecl>("class");

  // Look through all of our immediate bases to find methods that need to be
  // overridden
  typedef std::vector<CXXMethodDecl *> OverridesVector;
  OverridesVector MustOverrides;
  for (const auto &Base : D->bases()) {
    // The base is either a class (CXXRecordDecl) or it's a templated class...
    CXXRecordDecl *Parent = Base.getType()
                                .getDesugaredType(D->getASTContext())
                                ->getAsCXXRecordDecl();
    // The parent might not be resolved to a type yet. In this case, we can't
    // do any checking here. For complete correctness, we should visit
    // template instantiations, but this case is likely to be rare, so we will
    // ignore it until it becomes important.
    if (!Parent) {
      continue;
    }
    Parent = Parent->getDefinition();
    for (const auto &M : Parent->methods()) {
      if (hasCustomAnnotation(M, "moz_must_override"))
        MustOverrides.push_back(M);
    }
  }

  for (auto &O : MustOverrides) {
    bool Overridden = false;
    for (const auto &M : D->methods()) {
      // The way that Clang checks if a method M overrides its parent method
      // is if the method has the same name but would not overload.
      if (getNameChecked(M) == getNameChecked(O) &&
          !CI->getSema().IsOverload(M, O, false)) {
        Overridden = true;
        break;
      }
    }
    if (!Overridden) {
      diag(D->getLocation(), "%0 must override %1", DiagnosticIDs::Error)
          << D->getDeclName() << O->getDeclName();
      diag(O->getLocation(), "function to override is here",
           DiagnosticIDs::Note);
    }
  }
}
CustomTypeAnnotation::AnnotationReason
CustomTypeAnnotation::directAnnotationReason(QualType T) {
  if (const TagDecl *D = T->getAsTagDecl()) {
    if (hasCustomAnnotation(D, Spelling)) {
      AnnotationReason Reason = {T, RK_Direct, nullptr, ""};
      return Reason;
    }

    std::string ImplAnnotReason = getImplicitReason(D);
    if (!ImplAnnotReason.empty()) {
      AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason};
      return Reason;
    }
  }

  // Check if we have a cached answer
  void *Key = T.getAsOpaquePtr();
  ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
  if (Cached != Cache.end()) {
    return Cached->second;
  }

  // Check if we have a type which we can recurse into
  if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) {
    if (hasEffectiveAnnotation(Array->getElementType())) {
      AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement,
                                 nullptr, ""};
      Cache[Key] = Reason;
      return Reason;
    }
  }

  // Recurse into Base classes
  if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) {
    if (Declaration->hasDefinition()) {
      Declaration = Declaration->getDefinition();

      for (const CXXBaseSpecifier &Base : Declaration->bases()) {
        if (hasEffectiveAnnotation(Base.getType())) {
          AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr, ""};
          Cache[Key] = Reason;
          return Reason;
        }
      }

      // Recurse into members
      for (const FieldDecl *Field : Declaration->fields()) {
        if (hasEffectiveAnnotation(Field->getType())) {
          AnnotationReason Reason = {Field->getType(), RK_Field, Field, ""};
          Cache[Key] = Reason;
          return Reason;
        }
      }

      // Recurse into template arguments if the annotation
      // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
      if (hasCustomAnnotation(
              Declaration, "moz_inherit_type_annotations_from_template_args")) {
        const ClassTemplateSpecializationDecl *Spec =
            dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
        if (Spec) {
          const TemplateArgumentList &Args = Spec->getTemplateArgs();

          AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray());
          if (Reason.Kind != RK_None) {
            Cache[Key] = Reason;
            return Reason;
          }
        }
      }
    }
  }

  AnnotationReason Reason = {QualType(), RK_None, nullptr, ""};
  Cache[Key] = Reason;
  return Reason;
}
bool OverrideBaseCallChecker::isRequiredBaseMethod(
    const CXXMethodDecl *Method) {
  return hasCustomAnnotation(Method, "moz_required_base_method");
}