// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "nullability/forwarding_functions.h"

#include <cassert>

#include "absl/base/nullability.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/LLVM.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

namespace clang::tidy::nullability {

namespace {

bool isStdMakeUniqueWithNontrivalConstructor(const FunctionDecl &FD) {
  if (!FD.getDeclName().isIdentifier()) return false;
  if (FD.getName() != "make_unique") return false;
  const auto *Namespace = dyn_cast_or_null<NamespaceDecl>(FD.getDeclContext());
  if (Namespace == nullptr) return false;
  if (!Namespace->isStdNamespace()) return false;

  // Check if it is (a) make_unique<T>(args...), or (b) make_unique<T[]>(size).
  // The array version would just call the 0-arg constructor, which isn't
  // very interesting to diagnose. We also want T in the first version to
  // be a record type so that there is a constructor call to analyze.
  const TemplateArgumentList *TemplateArgs = FD.getTemplateSpecializationArgs();
  if (!TemplateArgs) return false;
  ArrayRef<TemplateArgument> TemplateArgsArray = TemplateArgs->asArray();
  if (TemplateArgsArray.empty()) return false;
  const TemplateArgument &FirstArg = TemplateArgsArray.front();
  assert(FirstArg.getKind() == TemplateArgument::Type);
  if (FirstArg.getKind() != TemplateArgument::Type) return false;
  return FirstArg.getAsType()->isRecordType();
}

const Expr *findMakeUniqueNewExprInitializer(const Stmt *absl_nonnull S) {
  // Do a simple walk over the children, which should be sufficient for
  // make_unique. RecursiveASTVisitor can also work but is supposed to be more
  // expensive to compile. make_unique should have a `new T( ... )` in its
  // body. Find that, and extract the Initializer.
  if (auto *NE = dyn_cast<CXXNewExpr>(S)) {
    return NE->getInitializer();
  }
  for (const Stmt *Child : S->children()) {
    if (auto *E = findMakeUniqueNewExprInitializer(Child)) return E;
  }
  // We expect to find a `new` in the body of make_unique (vs indirecting to
  // another function), since it's a fairly simple implementation.
  llvm::errs()
      << "Nullability: expected to find `new` in make_unique but did not\n";
  assert(false);
  return nullptr;
}

}  // namespace

const Expr *absl_nullable getUnderlyingInitExprInStdMakeUnique(
    const FunctionDecl &Decl) {
  if (!isStdMakeUniqueWithNontrivalConstructor(Decl)) return nullptr;
  if (Decl.getBody() == nullptr) return nullptr;
  return findMakeUniqueNewExprInitializer(Decl.getBody());
}

const FunctionDecl *absl_nullable getLastForwardingFunctionLayer(
    const FunctionDecl &Decl) {
  if (!isStdMakeUniqueWithNontrivalConstructor(Decl)) return nullptr;
  if (Decl.getBody() == nullptr) return nullptr;
  return &Decl;
}

}  // namespace clang::tidy::nullability
