//===---------- ASTUtils.cpp - clang-tidy ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ASTUtils.h"

#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"

namespace clang::tidy::utils {
using namespace ast_matchers;

const FunctionDecl *getSurroundingFunction(ASTContext &Context,
                                           const Stmt &Statement) {
  return selectFirst<const FunctionDecl>(
      "function", match(stmt(hasAncestor(functionDecl().bind("function"))),
                        Statement, Context));
}

bool isBinaryOrTernary(const Expr *E) {
  const Expr *EBase = E->IgnoreImpCasts();
  if (isa<BinaryOperator>(EBase) || isa<ConditionalOperator>(EBase)) {
    return true;
  }

  if (const auto *Operator = dyn_cast<CXXOperatorCallExpr>(EBase)) {
    return Operator->isInfixBinaryOp();
  }

  return false;
}

bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,
                                const LangOptions &LangOpts,
                                StringRef FlagName) {
  // If the Flag is an integer constant, check it.
  if (isa<IntegerLiteral>(Flags)) {
    if (!SM.isMacroBodyExpansion(Flags->getBeginLoc()) &&
        !SM.isMacroArgExpansion(Flags->getBeginLoc()))
      return false;

    // Get the macro name.
    auto MacroName = Lexer::getSourceText(
        CharSourceRange::getTokenRange(Flags->getSourceRange()), SM, LangOpts);

    return MacroName == FlagName;
  }
  // If it's a binary OR operation.
  if (const auto *BO = dyn_cast<BinaryOperator>(Flags))
    if (BO->getOpcode() == BinaryOperatorKind::BO_Or)
      return exprHasBitFlagWithSpelling(BO->getLHS()->IgnoreParenCasts(), SM,
                                        LangOpts, FlagName) ||
             exprHasBitFlagWithSpelling(BO->getRHS()->IgnoreParenCasts(), SM,
                                        LangOpts, FlagName);

  // Otherwise, assume it has the flag.
  return true;
}

bool rangeIsEntirelyWithinMacroArgument(SourceRange Range,
                                        const SourceManager *SM) {
  // Check if the range is entirely contained within a macro argument.
  SourceLocation MacroArgExpansionStartForRangeBegin;
  SourceLocation MacroArgExpansionStartForRangeEnd;
  bool RangeIsEntirelyWithinMacroArgument =
      SM &&
      SM->isMacroArgExpansion(Range.getBegin(),
                              &MacroArgExpansionStartForRangeBegin) &&
      SM->isMacroArgExpansion(Range.getEnd(),
                              &MacroArgExpansionStartForRangeEnd) &&
      MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;

  return RangeIsEntirelyWithinMacroArgument;
}

bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM) {
  return rangeIsEntirelyWithinMacroArgument(Range, SM) ||
         Range.getBegin().isMacroID() || Range.getEnd().isMacroID();
}

bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM) {
  return utils::rangeIsEntirelyWithinMacroArgument(Range, SM) ||
         !utils::rangeContainsMacroExpansion(Range, SM);
}

bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt,
                            const ASTContext &Context, bool Canonical) {
  if (!FirstStmt || !SecondStmt)
    return false;

  if (FirstStmt == SecondStmt)
    return true;

  if (FirstStmt->getStmtClass() != FirstStmt->getStmtClass())
    return false;

  if (isa<Expr>(FirstStmt) && isa<Expr>(SecondStmt)) {
    // If we have errors in expressions, we will be unable
    // to accurately profile and compute hashes for each statements.
    if (llvm::cast<Expr>(FirstStmt)->containsErrors() ||
        llvm::cast<Expr>(SecondStmt)->containsErrors())
      return false;
  }

  llvm::FoldingSetNodeID DataFirst, DataSecond;
  FirstStmt->Profile(DataFirst, Context, Canonical);
  SecondStmt->Profile(DataSecond, Context, Canonical);
  return DataFirst == DataSecond;
}

const IndirectFieldDecl *
findOutermostIndirectFieldDeclForField(const FieldDecl *FD) {
  const RecordDecl *Record = FD->getParent();
  assert(Record->isAnonymousStructOrUnion() &&
         "FD must be a field in an anonymous record");

  const DeclContext *Context = Record;
  while (isa<RecordDecl>(Context) &&
         cast<RecordDecl>(Context)->isAnonymousStructOrUnion()) {
    Context = Context->getParent();
  }

  // Search for the target IndirectFieldDecl within the located context.
  for (const auto *D : Context->decls()) {
    const auto *IFD = dyn_cast<IndirectFieldDecl>(D);
    if (!IFD)
      continue;
    if (IFD->getAnonField() == FD)
      return IFD;
  }

  return nullptr;
}

} // namespace clang::tidy::utils
