//===----------------------------------------------------------------------===//
//
// 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 "LoopConvertUtils.h"
#include "../utils/ASTUtils.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <cstddef>
#include <optional>
#include <string>
#include <utility>

using namespace clang::ast_matchers;

namespace clang::tidy::modernize {

/// Tracks a stack of parent statements during traversal.
///
/// All this really does is inject push_back() before running
/// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop
/// the stack is the parent of the current statement (NULL for the topmost
/// statement).
bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) {
  StmtAncestors.insert(std::make_pair(Statement, StmtStack.back()));
  StmtStack.push_back(Statement);
  RecursiveASTVisitor<StmtAncestorASTVisitor>::TraverseStmt(Statement);
  StmtStack.pop_back();
  return true;
}

/// Keep track of the DeclStmt associated with each VarDecl.
///
/// Combined with StmtAncestors, this provides roughly the same information as
/// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree
/// using StmtAncestors.
bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Statement) {
  for (const auto *Decl : Statement->decls()) {
    if (const auto *V = dyn_cast<VarDecl>(Decl))
      DeclParents.insert(std::make_pair(V, Statement));
  }
  return true;
}

/// record the DeclRefExpr as part of the parent expression.
bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
  Components.push_back(E);
  return true;
}

/// record the MemberExpr as part of the parent expression.
bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) {
  Components.push_back(Member);
  return true;
}

/// Forward any DeclRefExprs to a check on the referenced variable
/// declaration.
bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
  if (auto *V = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
    return VisitVarDecl(V);
  return true;
}

/// Determine if any this variable is declared inside the ContainingStmt.
bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) {
  const Stmt *Curr = DeclParents->lookup(V);
  // First, see if the variable was declared within an inner scope of the loop.
  while (Curr != nullptr) {
    if (Curr == ContainingStmt) {
      DependsOnInsideVariable = true;
      return false;
    }
    Curr = StmtParents->lookup(Curr);
  }

  // Next, check if the variable was removed from existence by an earlier
  // iteration.
  for (const auto &I : *ReplacedVars) {
    if (I.second == V) {
      DependsOnInsideVariable = true;
      return false;
    }
  }
  return true;
}

/// If we already created a variable for TheLoop, check to make sure
/// that the name was not already taken.
bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) {
  StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop);
  if (I != GeneratedDecls->end() && I->second == Name) {
    Found = true;
    return false;
  }
  return true;
}

/// If any named declaration within the AST subtree has the same name,
/// then consider Name already taken.
bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *D) {
  const IdentifierInfo *Ident = D->getIdentifier();
  if (Ident && Ident->getName() == Name) {
    Found = true;
    return false;
  }
  return true;
}

/// Forward any declaration references to the actual check on the
/// referenced declaration.
bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
  if (auto *D = dyn_cast<NamedDecl>(DeclRef->getDecl()))
    return VisitNamedDecl(D);
  return true;
}

/// If the new variable name conflicts with any type used in the loop,
/// then we mark that variable name as taken.
bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) {
  QualType QType = TL.getType();

  // Check if our name conflicts with a type, to handle for typedefs.
  if (QType.getAsString() == Name) {
    Found = true;
    return false;
  }
  // Check for base type conflicts. For example, when a struct is being
  // referenced in the body of the loop, the above getAsString() will return the
  // whole type (ex. "struct s"), but will be caught here.
  if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) {
    if (Ident->getName() == Name) {
      Found = true;
      return false;
    }
  }
  return true;
}

/// Look through conversion/copy constructors and member functions to find the
/// explicit initialization expression, returning it is found.
///
/// The main idea is that given
///   vector<int> v;
/// we consider either of these initializations
///   vector<int>::iterator it = v.begin();
///   vector<int>::iterator it(v.begin());
///   vector<int>::const_iterator it(v.begin());
/// and retrieve `v.begin()` as the expression used to initialize `it` but do
/// not include
///   vector<int>::iterator it;
///   vector<int>::iterator it(v.begin(), 0); // if this constructor existed
/// as being initialized from `v.begin()`
const Expr *digThroughConstructorsConversions(const Expr *E) {
  if (!E)
    return nullptr;
  E = E->IgnoreImplicit();
  if (const auto *ConstructExpr = dyn_cast<CXXConstructExpr>(E)) {
    // The initial constructor must take exactly one parameter, but base class
    // and deferred constructors can take more.
    if (ConstructExpr->getNumArgs() != 1 ||
        ConstructExpr->getConstructionKind() != CXXConstructionKind::Complete)
      return nullptr;
    E = ConstructExpr->getArg(0);
    if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E))
      E = Temp->getSubExpr();
    return digThroughConstructorsConversions(E);
  }
  // If this is a conversion (as iterators commonly convert into their const
  // iterator counterparts), dig through that as well.
  if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E))
    if (isa<CXXConversionDecl>(ME->getMethodDecl()))
      return digThroughConstructorsConversions(ME->getImplicitObjectArgument());
  return E;
}

/// Returns true when two Exprs are equivalent.
bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {
  return utils::areStatementsIdentical(First, Second, *Context, true);
}

/// Returns the DeclRefExpr represented by E, or NULL if there isn't one.
const DeclRefExpr *getDeclRef(const Expr *E) {
  return dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
}

/// Returns true when two ValueDecls are the same variable.
bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
  return First && Second &&
         First->getCanonicalDecl() == Second->getCanonicalDecl();
}

/// Determines if an expression is a declaration reference to a
/// particular variable.
static bool exprReferencesVariable(const ValueDecl *Target, const Expr *E) {
  if (!Target || !E)
    return false;
  const DeclRefExpr *Decl = getDeclRef(E);
  return Decl && areSameVariable(Target, Decl->getDecl());
}

/// If the expression is a dereference or call to operator*(), return the
/// operand. Otherwise, return NULL.
static const Expr *getDereferenceOperand(const Expr *E) {
  if (const auto *Uop = dyn_cast<UnaryOperator>(E))
    return Uop->getOpcode() == UO_Deref ? Uop->getSubExpr() : nullptr;

  if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
    return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1
               ? OpCall->getArg(0)
               : nullptr;
  }

  return nullptr;
}

/// Returns true when the Container contains an Expr equivalent to E.
template <typename ContainerT>
static bool containsExpr(ASTContext *Context, const ContainerT *Container,
                         const Expr *E) {
  llvm::FoldingSetNodeID ID;
  E->Profile(ID, *Context, true);
  for (const auto &I : *Container) {
    if (ID == I.second)
      return true;
  }
  return false;
}

/// Returns true when the index expression is a declaration reference to
/// IndexVar.
///
/// If the index variable is `index`, this function returns true on
///    arrayExpression[index];
///    containerExpression[index];
/// but not
///    containerExpression[notIndex];
static bool isIndexInSubscriptExpr(const Expr *IndexExpr,
                                   const VarDecl *IndexVar) {
  const DeclRefExpr *Idx = getDeclRef(IndexExpr);
  return Idx && Idx->getType()->isIntegerType() &&
         areSameVariable(IndexVar, Idx->getDecl());
}

/// Returns true when the index expression is a declaration reference to
/// IndexVar, Obj is the same expression as SourceExpr after all parens and
/// implicit casts are stripped off.
///
/// If PermitDeref is true, IndexExpression may
/// be a dereference (overloaded or builtin operator*).
///
/// This function is intended for array-like containers, as it makes sure that
/// both the container and the index match.
/// If the loop has index variable `index` and iterates over `container`, then
/// isIndexInSubscriptExpr returns true for
/// \code
///   container[index]
///   container.at(index)
///   container->at(index)
/// \endcode
/// but not for
/// \code
///   container[notIndex]
///   notContainer[index]
/// \endcode
/// If PermitDeref is true, then isIndexInSubscriptExpr additionally returns
/// true on these expressions:
/// \code
///   (*container)[index]
///   (*container).at(index)
/// \endcode
static bool isIndexInSubscriptExpr(ASTContext *Context, const Expr *IndexExpr,
                                   const VarDecl *IndexVar, const Expr *Obj,
                                   const Expr *SourceExpr, bool PermitDeref) {
  if (!SourceExpr || !Obj || !isIndexInSubscriptExpr(IndexExpr, IndexVar))
    return false;

  if (areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
                  Obj->IgnoreParenImpCasts()))
    return true;

  if (const Expr *InnerObj = getDereferenceOperand(Obj->IgnoreParenImpCasts()))
    if (PermitDeref && areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
                                   InnerObj->IgnoreParenImpCasts()))
      return true;

  return false;
}

/// Returns true when Opcall is a call a one-parameter dereference of
/// IndexVar.
///
/// For example, if the index variable is `index`, returns true for
///   *index
/// but not
///   index
///   *notIndex
static bool isDereferenceOfOpCall(const CXXOperatorCallExpr *OpCall,
                                  const VarDecl *IndexVar) {
  return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 &&
         exprReferencesVariable(IndexVar, OpCall->getArg(0));
}

/// Returns true when Uop is a dereference of IndexVar.
///
/// For example, if the index variable is `index`, returns true for
///   *index
/// but not
///   index
///   *notIndex
static bool isDereferenceOfUop(const UnaryOperator *Uop,
                               const VarDecl *IndexVar) {
  return Uop->getOpcode() == UO_Deref &&
         exprReferencesVariable(IndexVar, Uop->getSubExpr());
}

/// Determines whether the given Decl defines a variable initialized to
/// the loop object.
///
/// This is intended to find cases such as
/// \code
///   for (int i = 0; i < arraySize(arr); ++i) {
///     T t = arr[i];
///     // use t, do not use i
///   }
/// \endcode
/// and
/// \code
///   for (iterator i = container.begin(), e = container.end(); i != e; ++i) {
///     T t = *i;
///     // use t, do not use i
///   }
/// \endcode
static bool isAliasDecl(ASTContext *Context, const Decl *TheDecl,
                        const VarDecl *IndexVar) {
  const auto *VDecl = dyn_cast<VarDecl>(TheDecl);
  if (!VDecl)
    return false;
  if (!VDecl->hasInit())
    return false;

  bool OnlyCasts = true;
  const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts();
  if (isa_and_nonnull<CXXConstructExpr>(Init)) {
    Init = digThroughConstructorsConversions(Init);
    OnlyCasts = false;
  }
  if (!Init)
    return false;

  // Check that the declared type is the same as (or a reference to) the
  // container type.
  if (!OnlyCasts) {
    QualType InitType = Init->getType();
    QualType DeclarationType = VDecl->getType();
    if (!DeclarationType.isNull() && DeclarationType->isReferenceType())
      DeclarationType = DeclarationType.getNonReferenceType();

    if (InitType.isNull() || DeclarationType.isNull() ||
        !ASTContext::hasSameUnqualifiedType(DeclarationType, InitType))
      return false;
  }

  switch (Init->getStmtClass()) {
  case Stmt::ArraySubscriptExprClass: {
    const auto *E = cast<ArraySubscriptExpr>(Init);
    // We don't really care which array is used here. We check to make sure
    // it was the correct one later, since the AST will traverse it next.
    return isIndexInSubscriptExpr(E->getIdx(), IndexVar);
  }

  case Stmt::UnaryOperatorClass:
    return isDereferenceOfUop(cast<UnaryOperator>(Init), IndexVar);

  case Stmt::CXXOperatorCallExprClass: {
    const auto *OpCall = cast<CXXOperatorCallExpr>(Init);
    if (OpCall->getOperator() == OO_Star)
      return isDereferenceOfOpCall(OpCall, IndexVar);
    if (OpCall->getOperator() == OO_Subscript) {
      return OpCall->getNumArgs() == 2 &&
             isIndexInSubscriptExpr(OpCall->getArg(1), IndexVar);
    }
    break;
  }

  case Stmt::CXXMemberCallExprClass: {
    const auto *MemCall = cast<CXXMemberCallExpr>(Init);
    // This check is needed because getMethodDecl can return nullptr if the
    // callee is a member function pointer.
    const auto *MDecl = MemCall->getMethodDecl();
    if (MDecl && !isa<CXXConversionDecl>(MDecl) &&
        MDecl->getNameAsString() == "at" && MemCall->getNumArgs() == 1) {
      return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar);
    }
    return false;
  }

  default:
    break;
  }
  return false;
}

/// Determines whether the bound of a for loop condition expression is
/// the same as the statically computable size of ArrayType.
///
/// Given
/// \code
///   const int N = 5;
///   int arr[N];
/// \endcode
/// This is intended to permit
/// \code
///   for (int i = 0; i < N; ++i) {  /* use arr[i] */ }
///   for (int i = 0; i < arraysize(arr); ++i) { /* use arr[i] */ }
/// \endcode
static bool arrayMatchesBoundExpr(ASTContext *Context,
                                  const QualType &ArrayType,
                                  const Expr *ConditionExpr) {
  if (!ConditionExpr || ConditionExpr->isValueDependent())
    return false;
  const ConstantArrayType *ConstType =
      Context->getAsConstantArrayType(ArrayType);
  if (!ConstType)
    return false;
  std::optional<llvm::APSInt> ConditionSize =
      ConditionExpr->getIntegerConstantExpr(*Context);
  if (!ConditionSize)
    return false;
  llvm::APSInt ArraySize(ConstType->getSize());
  return llvm::APSInt::isSameValue(*ConditionSize, ArraySize);
}

ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context,
                                               const VarDecl *IndexVar,
                                               const VarDecl *EndVar,
                                               const Expr *ContainerExpr,
                                               const Expr *ArrayBoundExpr,
                                               bool ContainerNeedsDereference)
    : Context(Context), IndexVar(IndexVar), EndVar(EndVar),
      ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
      ContainerNeedsDereference(ContainerNeedsDereference),

      ConfidenceLevel(Confidence::CL_Safe) {
  if (ContainerExpr)
    addComponent(ContainerExpr);
}

bool ForLoopIndexUseVisitor::findAndVerifyUsages(const Stmt *Body) {
  TraverseStmt(const_cast<Stmt *>(Body));
  return OnlyUsedAsIndex && ContainerExpr;
}

void ForLoopIndexUseVisitor::addComponents(const ComponentVector &Components) {
  // FIXME: add sort(on ID)+unique to avoid extra work.
  for (const auto &I : Components)
    addComponent(I);
}

void ForLoopIndexUseVisitor::addComponent(const Expr *E) {
  llvm::FoldingSetNodeID ID;
  const Expr *Node = E->IgnoreParenImpCasts();
  Node->Profile(ID, *Context, true);
  DependentExprs.push_back(std::make_pair(Node, ID));
}

void ForLoopIndexUseVisitor::addUsage(const Usage &U) {
  SourceLocation Begin = U.Range.getBegin();
  if (Begin.isMacroID())
    Begin = Context->getSourceManager().getSpellingLoc(Begin);

  if (UsageLocations.insert(Begin).second)
    Usages.push_back(U);
}

/// If the unary operator is a dereference of IndexVar, include it
/// as a valid usage and prune the traversal.
///
/// For example, if container.begin() and container.end() both return pointers
/// to int, this makes sure that the initialization for `k` is not counted as an
/// unconvertible use of the iterator `i`.
/// \code
///   for (int *i = container.begin(), *e = container.end(); i != e; ++i) {
///     int k = *i + 2;
///   }
/// \endcode
bool ForLoopIndexUseVisitor::TraverseUnaryOperator(UnaryOperator *Uop) {
  // If we dereference an iterator that's actually a pointer, count the
  // occurrence.
  if (isDereferenceOfUop(Uop, IndexVar)) {
    addUsage(Usage(Uop));
    return true;
  }

  return VisitorBase::TraverseUnaryOperator(Uop);
}

/// If the member expression is operator-> (overloaded or not) on
/// IndexVar, include it as a valid usage and prune the traversal.
///
/// For example, given
/// \code
///   struct Foo { int bar(); int x; };
///   vector<Foo> v;
/// \endcode
/// the following uses will be considered convertible:
/// \code
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int b = i->bar();
///     int k = i->x + 1;
///   }
/// \endcode
/// though
/// \code
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int k = i.insert(1);
///   }
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int b = e->bar();
///   }
/// \endcode
/// will not.
bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
  const Expr *Base = Member->getBase();
  const DeclRefExpr *Obj = getDeclRef(Base);
  const Expr *ResultExpr = Member;
  QualType ExprType;
  if (const auto *Call =
          dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
    // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then
    // the MemberExpr does not have the expression we want. We therefore catch
    // that instance here.
    // For example, if vector<Foo>::iterator defines operator->(), then the
    // example `i->bar()` at the top of this function is a CXXMemberCallExpr
    // referring to `i->` as the member function called. We want just `i`, so
    // we take the argument to operator->() as the base object.
    if (Call->getOperator() == OO_Arrow) {
      assert(Call->getNumArgs() == 1 &&
             "Operator-> takes more than one argument");
      Obj = getDeclRef(Call->getArg(0));
      ResultExpr = Obj;
      ExprType = Call->getCallReturnType(*Context);
    }
  }

  if (Obj && exprReferencesVariable(IndexVar, Obj)) {
    // Member calls on the iterator with '.' are not allowed.
    if (!Member->isArrow()) {
      OnlyUsedAsIndex = false;
      return true;
    }

    if (ExprType.isNull())
      ExprType = Obj->getType();

    if (!ExprType->isPointerType())
      return false;

    // FIXME: This works around not having the location of the arrow operator.
    // Consider adding OperatorLoc to MemberExpr?
    SourceLocation ArrowLoc = Lexer::getLocForEndOfToken(
        Base->getExprLoc(), 0, Context->getSourceManager(),
        Context->getLangOpts());
    // If something complicated is happening (i.e. the next token isn't an
    // arrow), give up on making this work.
    if (ArrowLoc.isValid()) {
      addUsage(Usage(ResultExpr, Usage::UK_MemberThroughArrow,
                     SourceRange(Base->getExprLoc(), ArrowLoc)));
      return true;
    }
  }
  return VisitorBase::TraverseMemberExpr(Member);
}

/// If a member function call is the at() accessor on the container with
/// IndexVar as the single argument, include it as a valid usage and prune
/// the traversal.
///
/// Member calls on other objects will not be permitted.
/// Calls on the iterator object are not permitted, unless done through
/// operator->(). The one exception is allowing vector::at() for pseudoarrays.
bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr(
    CXXMemberCallExpr *MemberCall) {
  auto *Member =
      dyn_cast<MemberExpr>(MemberCall->getCallee()->IgnoreParenImpCasts());
  if (!Member)
    return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);

  // We specifically allow an accessor named "at" to let STL in, though
  // this is restricted to pseudo-arrays by requiring a single, integer
  // argument.
  const IdentifierInfo *Ident = Member->getMemberDecl()->getIdentifier();
  if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1) {
    if (isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar,
                               Member->getBase(), ContainerExpr,
                               ContainerNeedsDereference)) {
      addUsage(Usage(MemberCall));
      return true;
    }
  }

  if (containsExpr(Context, &DependentExprs, Member->getBase()))
    ConfidenceLevel.lowerTo(Confidence::CL_Risky);

  return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);
}

/// If an overloaded operator call is a dereference of IndexVar or
/// a subscript of the container with IndexVar as the single argument,
/// include it as a valid usage and prune the traversal.
///
/// For example, given
/// \code
///   struct Foo { int bar(); int x; };
///   vector<Foo> v;
///   void f(Foo);
/// \endcode
/// the following uses will be considered convertible:
/// \code
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     f(*i);
///   }
///   for (int i = 0; i < v.size(); ++i) {
///      int i = v[i] + 1;
///   }
/// \endcode
bool ForLoopIndexUseVisitor::TraverseCXXOperatorCallExpr(
    CXXOperatorCallExpr *OpCall) {
  switch (OpCall->getOperator()) {
  case OO_Star:
    if (isDereferenceOfOpCall(OpCall, IndexVar)) {
      addUsage(Usage(OpCall));
      return true;
    }
    break;

  case OO_Subscript:
    if (OpCall->getNumArgs() != 2)
      break;
    if (isIndexInSubscriptExpr(Context, OpCall->getArg(1), IndexVar,
                               OpCall->getArg(0), ContainerExpr,
                               ContainerNeedsDereference)) {
      addUsage(Usage(OpCall));
      return true;
    }
    break;

  default:
    break;
  }
  return VisitorBase::TraverseCXXOperatorCallExpr(OpCall);
}

/// If we encounter an array with IndexVar as the index of an
/// ArraySubscriptExpression, note it as a consistent usage and prune the
/// AST traversal.
///
/// For example, given
/// \code
///   const int N = 5;
///   int arr[N];
/// \endcode
/// This is intended to permit
/// \code
///   for (int i = 0; i < N; ++i) {  /* use arr[i] */ }
/// \endcode
/// but not
/// \code
///   for (int i = 0; i < N; ++i) {  /* use notArr[i] */ }
/// \endcode
/// and further checking needs to be done later to ensure that exactly one array
/// is referenced.
bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
  Expr *Arr = E->getBase();
  if (!isIndexInSubscriptExpr(E->getIdx(), IndexVar))
    return VisitorBase::TraverseArraySubscriptExpr(E);

  if ((ContainerExpr && !areSameExpr(Context, Arr->IgnoreParenImpCasts(),
                                     ContainerExpr->IgnoreParenImpCasts())) ||
      !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(),
                             ArrayBoundExpr)) {
    // If we have already discovered the array being indexed and this isn't it
    // or this array doesn't match, mark this loop as unconvertible.
    OnlyUsedAsIndex = false;
    return VisitorBase::TraverseArraySubscriptExpr(E);
  }

  if (!ContainerExpr)
    ContainerExpr = Arr;

  addUsage(Usage(E));
  return true;
}

/// If we encounter a reference to IndexVar in an unpruned branch of the
/// traversal, mark this loop as unconvertible.
///
/// This determines the set of convertible loops: any usages of IndexVar
/// not explicitly considered convertible by this traversal will be caught by
/// this function.
///
/// Additionally, if the container expression is more complex than just a
/// DeclRefExpr, and some part of it is appears elsewhere in the loop, lower
/// our confidence in the transformation.
///
/// For example, these are not permitted:
/// \code
///   for (int i = 0; i < N; ++i) {  printf("arr[%d] = %d", i, arr[i]); }
///   for (vector<int>::iterator i = container.begin(), e = container.end();
///        i != e; ++i)
///     i.insert(0);
///   for (vector<int>::iterator i = container.begin(), e = container.end();
///        i != e; ++i)
///     if (i + 1 != e)
///       printf("%d", *i);
/// \endcode
///
/// And these will raise the risk level:
/// \code
///    int arr[10][20];
///    int l = 5;
///    for (int j = 0; j < 20; ++j)
///      int k = arr[l][j] + l; // using l outside arr[l] is considered risky
///    for (int i = 0; i < obj.getVector().size(); ++i)
///      obj.foo(10); // using `obj` is considered risky
/// \endcode
bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
  const ValueDecl *TheDecl = E->getDecl();
  if (areSameVariable(IndexVar, TheDecl) ||
      exprReferencesVariable(IndexVar, E) || areSameVariable(EndVar, TheDecl) ||
      exprReferencesVariable(EndVar, E))
    OnlyUsedAsIndex = false;
  if (containsExpr(Context, &DependentExprs, E))
    ConfidenceLevel.lowerTo(Confidence::CL_Risky);
  return true;
}

/// If the loop index is captured by a lambda, replace this capture
/// by the range-for loop variable.
///
/// For example:
/// \code
///   for (int i = 0; i < N; ++i) {
///     auto f = [v, i](int k) {
///       printf("%d\n", v[i] + k);
///     };
///     f(v[i]);
///   }
/// \endcode
///
/// Will be replaced by:
/// \code
///   for (auto & elem : v) {
///     auto f = [v, elem](int k) {
///       printf("%d\n", elem + k);
///     };
///     f(elem);
///   }
/// \endcode
bool ForLoopIndexUseVisitor::TraverseLambdaCapture(LambdaExpr *LE,
                                                   const LambdaCapture *C,
                                                   Expr *Init) {
  if (C->capturesVariable()) {
    ValueDecl *VDecl = C->getCapturedVar();
    if (areSameVariable(IndexVar, VDecl)) {
      // FIXME: if the index is captured, it will count as an usage and the
      // alias (if any) won't work, because it is only used in case of having
      // exactly one usage.
      addUsage(Usage(nullptr,
                     C->getCaptureKind() == LCK_ByCopy ? Usage::UK_CaptureByCopy
                                                       : Usage::UK_CaptureByRef,
                     C->getLocation()));
    }
    if (VDecl->isInitCapture())
      traverseStmtImpl(cast<VarDecl>(VDecl)->getInit());
  }
  return VisitorBase::TraverseLambdaCapture(LE, C, Init);
}

/// If we find that another variable is created just to refer to the loop
/// element, note it for reuse as the loop variable.
///
/// See the comments for isAliasDecl.
bool ForLoopIndexUseVisitor::VisitDeclStmt(DeclStmt *S) {
  if (!AliasDecl && S->isSingleDecl() &&
      isAliasDecl(Context, S->getSingleDecl(), IndexVar)) {
    AliasDecl = S;
    if (CurrStmtParent) {
      if (isa<IfStmt>(CurrStmtParent) || isa<WhileStmt>(CurrStmtParent) ||
          isa<SwitchStmt>(CurrStmtParent))
        ReplaceWithAliasUse = true;
      else if (isa<ForStmt>(CurrStmtParent)) {
        if (cast<ForStmt>(CurrStmtParent)->getConditionVariableDeclStmt() == S)
          ReplaceWithAliasUse = true;
        else
          // It's assumed S came the for loop's init clause.
          AliasFromForInit = true;
      }
    }
  }

  return true;
}

bool ForLoopIndexUseVisitor::traverseStmtImpl(Stmt *S) {
  // All this pointer swapping is a mechanism for tracking immediate parentage
  // of Stmts.
  const Stmt *OldNextParent = NextStmtParent;
  CurrStmtParent = NextStmtParent;
  NextStmtParent = S;
  bool Result = VisitorBase::TraverseStmt(S);
  NextStmtParent = OldNextParent;
  return Result;
}

bool ForLoopIndexUseVisitor::TraverseStmt(Stmt *S) {
  // If this is an initialization expression for a lambda capture, prune the
  // traversal so that we don't end up diagnosing the contained DeclRefExpr as
  // inconsistent usage. No need to record the usage here -- this is done in
  // TraverseLambdaCapture().
  if (const auto *LE = dyn_cast_or_null<LambdaExpr>(NextStmtParent)) {
    // Any child of a LambdaExpr that isn't the body is an initialization
    // expression.
    if (S != LE->getBody()) {
      return true;
    }
  }
  return traverseStmtImpl(S);
}

std::string VariableNamer::createIndexName() {
  // FIXME: Add in naming conventions to handle:
  //  - How to handle conflicts.
  //  - An interactive process for naming.
  std::string IteratorName;
  StringRef ContainerName;
  if (TheContainer)
    ContainerName = TheContainer->getName();

  size_t Len = ContainerName.size();
  if (Len > 1 && ContainerName.ends_with(Style == NS_UpperCase ? "S" : "s")) {
    IteratorName = std::string(ContainerName.substr(0, Len - 1));
    // E.g.: (auto thing : things)
    if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName())
      return IteratorName;
  }

  if (Len > 2 && ContainerName.ends_with(Style == NS_UpperCase ? "S_" : "s_")) {
    IteratorName = std::string(ContainerName.substr(0, Len - 2));
    // E.g.: (auto thing : things_)
    if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName())
      return IteratorName;
  }

  return std::string(OldIndex->getName());
}

/// Determines whether or not the name \a Symbol conflicts with
/// language keywords or defined macros. Also checks if the name exists in
/// LoopContext, any of its parent contexts, or any of its child statements.
///
/// We also check to see if the same identifier was generated by this loop
/// converter in a loop nested within SourceStmt.
bool VariableNamer::declarationExists(StringRef Symbol) {
  assert(Context != nullptr && "Expected an ASTContext");
  IdentifierInfo &Ident = Context->Idents.get(Symbol);

  // Check if the symbol is not an identifier (ie. is a keyword or alias).
  if (!isAnyIdentifier(Ident.getTokenID()))
    return true;

  // Check for conflicting macro definitions.
  if (Ident.hasMacroDefinition())
    return true;

  // Determine if the symbol was generated in a parent context.
  for (const Stmt *S = SourceStmt; S != nullptr; S = ReverseAST->lookup(S)) {
    StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(S);
    if (I != GeneratedDecls->end() && I->second == Symbol)
      return true;
  }

  // FIXME: Rather than detecting conflicts at their usages, we should check the
  // parent context.
  // For some reason, lookup() always returns the pair (NULL, NULL) because its
  // StoredDeclsMap is not initialized (i.e. LookupPtr.getInt() is false inside
  // of DeclContext::lookup()). Why is this?

  // Finally, determine if the symbol was used in the loop or a child context.
  DeclFinderASTVisitor DeclFinder(std::string(Symbol), GeneratedDecls);
  return DeclFinder.findUsages(SourceStmt);
}

} // namespace clang::tidy::modernize
