/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"

using namespace clang::tooling;
using namespace llvm;

using namespace clang;
using namespace clang::ast_matchers;

namespace {
StatementMatcher CXXNewMatcher = cxxNewExpr().bind("useNew");
StatementMatcher CXXDeleteMatcher = cxxDeleteExpr().bind("useDelete");
} // namespace

class AllocLinter : public MatchFinder::MatchCallback {
public:
  virtual void run(const MatchFinder::MatchResult& Result) {
    auto& Context = *Result.Context;
    auto& DiagnosticsEngine = Context.getDiagnostics();
    auto& SourceManager = Context.getSourceManager();

    const auto* NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>("useNew");
    if (NewExpr &&
        !SourceManager.isInSystemHeader(NewExpr->getLocStart()) && // Not in system headers
        NewExpr->getNumPlacementArgs() == 0) {                     // Not placement new
      FunctionDecl* NewFuncDecl = NewExpr->getOperatorNew();
      if (NewExpr->isGlobalNew()) {
        diag(NewExpr->getLocStart(), "Using global `::operator new%0()`", DiagnosticsEngine)
            << (NewExpr->isArray() ? "[]" : "");
      } else if (NewFuncDecl && SourceManager.isInSystemHeader(NewFuncDecl->getLocation())) {
        diag(NewExpr->getLocStart(), "Using `operator new%0()` from %1", DiagnosticsEngine)
            << (NewExpr->isArray() ? "[]" : "")
            << NewFuncDecl->getLocation().printToString(SourceManager);
      }
    }

    const auto* DeleteExpr = Result.Nodes.getNodeAs<CXXDeleteExpr>("useDelete");
    if (DeleteExpr && !DeleteExpr->getDestroyedType().isNull() &&
        !DeleteExpr->getDestroyedType()->isVoidType() &&
        !SourceManager.isInSystemHeader(DeleteExpr->getLocStart())) { // Not in system headers
      FunctionDecl* DeleteFuncDecl = DeleteExpr->getOperatorDelete();
      if (DeleteExpr->isGlobalDelete()) {
        diag(DeleteExpr->getLocStart(), "Using global `::operator delete%0()`", DiagnosticsEngine)
            << (DeleteExpr->isArrayForm() ? "[]" : "");
      } else if (DeleteFuncDecl && SourceManager.isInSystemHeader(DeleteFuncDecl->getLocation())) {
        diag(DeleteExpr->getLocStart(), "Using `operator delete%0()` from %1", DiagnosticsEngine)
            << (DeleteExpr->isArrayForm() ? "[]" : "")
            << DeleteFuncDecl->getLocation().printToString(SourceManager);
      }
    }
  }

  DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
                         DiagnosticsEngine& DiagnosticsEngine) {
    auto ID = DiagnosticsEngine.getDiagnosticIDs()->getCustomDiagID(clang::DiagnosticIDs::Error,
                                                                    Description);
    return DiagnosticsEngine.Report(Loc, ID);
  }
};

static llvm::cl::OptionCategory AllocLinterToolCategory("alloc-linter options");

static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

static cl::extrahelp MoreHelp("\nThis is a tool for finding global "
                              "use of operator new/delete (from either global\n"
                              "or from the standard library) and other forms "
                              "of global allocation.\n");

int main(int argc, const char** argv) {
  CommonOptionsParser OptionsParser(argc, argv, AllocLinterToolCategory);
  ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());

  AllocLinter Linter;
  MatchFinder Finder;
  Finder.addMatcher(CXXNewMatcher, &Linter);
  Finder.addMatcher(CXXDeleteMatcher, &Linter);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}
