llvm/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp

//===--- LoopConvertCheck.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 "LoopConvertCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstring>
#include <optional>
#include <tuple>
#include <utility>

usingnamespaceclang::ast_matchers;
usingnamespacellvm;

namespace clang::tidy {

template <> struct OptionEnumMapping<modernize::Confidence::Level> {};

template <> struct OptionEnumMapping<modernize::VariableNamer::NamingStyle> {};

namespace modernize {

static const char LoopNameArray[] =;
static const char LoopNameIterator[] =;
static const char LoopNameReverseIterator[] =;
static const char LoopNamePseudoArray[] =;
static const char ConditionBoundName[] =;
static const char InitVarName[] =;
static const char BeginCallName[] =;
static const char EndCallName[] =;
static const char EndVarName[] =;
static const char DerefByValueResultName[] =;
static const char DerefByRefResultName[] =;
static const llvm::StringSet<> MemberNames{};
static const llvm::StringSet<> ADLNames{};
static const llvm::StringSet<> StdNames{};

static StatementMatcher integerComparisonMatcher() {}

static DeclarationMatcher initToZeroMatcher() {}

static StatementMatcher incrementVarMatcher() {}

static StatementMatcher
arrayConditionMatcher(internal::Matcher<Expr> LimitExpr) {}

/// The matcher for loops over arrays.
/// \code
///   for (int i = 0; i < 3 + 2; ++i) { ... }
/// \endcode
/// The following string identifiers are bound to these parts of the AST:
///   ConditionBoundName: '3 + 2' (as an Expr)
///   InitVarName: 'i' (as a VarDecl)
///   LoopName: The entire for loop (as a ForStmt)
///
/// Client code will need to make sure that:
///   - The index variable is only used as an array index.
///   - All arrays indexed by the loop are the same.
StatementMatcher makeArrayLoopMatcher() {}

/// The matcher used for iterator-based for loops.
///
/// This matcher is more flexible than array-based loops. It will match
/// catch loops of the following textual forms (regardless of whether the
/// iterator type is actually a pointer type or a class type):
///
/// \code
///   for (containerType::iterator it = container.begin(),
///        e = createIterator(); it != e; ++it) { ... }
///   for (containerType::iterator it = container.begin();
///        it != anotherContainer.end(); ++it) { ... }
///   for (containerType::iterator it = begin(container),
///        e = end(container); it != e; ++it) { ... }
///   for (containerType::iterator it = std::begin(container),
///        e = std::end(container); it != e; ++it) { ... }
/// \endcode
/// The following string identifiers are bound to the parts of the AST:
///   InitVarName: 'it' (as a VarDecl)
///   LoopName: The entire for loop (as a ForStmt)
///   In the first example only:
///     EndVarName: 'e' (as a VarDecl)
///   In the second example only:
///     EndCallName: 'container.end()' (as a CXXMemberCallExpr)
///   In the third/fourth examples:
///     'end(container)' or 'std::end(container)' (as a CallExpr)
///
/// Client code will need to make sure that:
///   - The two containers on which 'begin' and 'end' are called are the same.
StatementMatcher makeIteratorLoopMatcher(bool IsReverse) {}

/// The matcher used for array-like containers (pseudoarrays).
///
/// This matcher is more flexible than array-based loops. It will match
/// loops of the following textual forms (regardless of whether the
/// iterator type is actually a pointer type or a class type):
///
/// \code
///   for (int i = 0, j = container.size(); i < j; ++i) { ... }
///   for (int i = 0; i < container.size(); ++i) { ... }
///   for (int i = 0; i < size(container); ++i) { ... }
/// \endcode
/// The following string identifiers are bound to the parts of the AST:
///   InitVarName: 'i' (as a VarDecl)
///   LoopName: The entire for loop (as a ForStmt)
///   In the first example only:
///     EndVarName: 'j' (as a VarDecl)
///   In the second example only:
///     EndCallName: 'container.size()' (as a CXXMemberCallExpr) or
///     'size(container)' (as a CallExpr)
///
/// Client code will need to make sure that:
///   - The containers on which 'size()' is called is the container indexed.
///   - The index variable is only used in overloaded operator[] or
///     container.at().
///   - The container's iterators would not be invalidated during the loop.
StatementMatcher makePseudoArrayLoopMatcher() {}

enum class IteratorCallKind {};

struct ContainerCall {};

// Find the Expr likely initializing an iterator.
//
// Call is either a CXXMemberCallExpr ('c.begin()') or CallExpr of a free
// function with the first argument as a container ('begin(c)'), or nullptr.
// Returns at a 3-tuple with the container expr, function name (begin/end/etc),
// and whether the call is made through an arrow (->) for CXXMemberCallExprs.
// The returned Expr* is nullptr if any of the assumptions are not met.
// static std::tuple<const Expr *, StringRef, bool, IteratorCallKind>
static std::optional<ContainerCall> getContainerExpr(const Expr *Call) {}

/// Determine whether Init appears to be an initializing an iterator.
///
/// If it is, returns the object whose begin() or end() method is called, and
/// the output parameter isArrow is set to indicate whether the initialization
/// is called via . or ->.
static std::pair<const Expr *, IteratorCallKind>
getContainerFromBeginEndCall(const Expr *Init, bool IsBegin, bool *IsArrow,
                             bool IsReverse) {}

/// Determines the container whose begin() and end() functions are called
/// for an iterator-based loop.
///
/// BeginExpr must be a member call to a function named "begin()", and EndExpr
/// must be a member.
static const Expr *findContainer(ASTContext *Context, const Expr *BeginExpr,
                                 const Expr *EndExpr,
                                 bool *ContainerNeedsDereference,
                                 bool IsReverse) {}

/// Obtain the original source code text from a SourceRange.
static StringRef getStringFromRange(SourceManager &SourceMgr,
                                    const LangOptions &LangOpts,
                                    SourceRange Range) {}

/// If the given expression is actually a DeclRefExpr or a MemberExpr,
/// find and return the underlying ValueDecl; otherwise, return NULL.
static const ValueDecl *getReferencedVariable(const Expr *E) {}

/// Returns true when the given expression is a member expression
/// whose base is `this` (implicitly or not).
static bool isDirectMemberExpr(const Expr *E) {}

/// Given an expression that represents an usage of an element from the
/// container that we are iterating over, returns false when it can be
/// guaranteed this element cannot be modified as a result of this usage.
static bool canBeModified(ASTContext *Context, const Expr *E) {}

/// Returns true when it can be guaranteed that the elements of the
/// container are not being modified.
static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {}

/// Returns true if the elements of the container are never accessed
/// by reference.
static bool usagesReturnRValues(const UsageResult &Usages) {}

/// Returns true if the container is const-qualified.
static bool containerIsConst(const Expr *ContainerExpr, bool Dereference) {}

LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
    :{}

void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {}

void LoopConvertCheck::registerPPCallbacks(const SourceManager &SM,
                                           Preprocessor *PP,
                                           Preprocessor *ModuleExpanderPP) {}

void LoopConvertCheck::registerMatchers(MatchFinder *Finder) {}

/// Given the range of a single declaration, such as:
/// \code
///   unsigned &ThisIsADeclarationThatCanSpanSeveralLinesOfCode =
///       InitializationValues[I];
///   next_instruction;
/// \endcode
/// Finds the range that has to be erased to remove this declaration without
/// leaving empty lines, by extending the range until the beginning of the
/// next instruction.
///
/// We need to delete a potential newline after the deleted alias, as
/// clang-format will leave empty lines untouched. For all other formatting we
/// rely on clang-format to fix it.
void LoopConvertCheck::getAliasRange(SourceManager &SM, SourceRange &Range) {}

/// Computes the changes needed to convert a given for loop, and
/// applies them.
void LoopConvertCheck::doConversion(
    ASTContext *Context, const VarDecl *IndexVar,
    const ValueDecl *MaybeContainer, const UsageResult &Usages,
    const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit,
    const ForStmt *Loop, RangeDescriptor Descriptor) {}

/// Returns a string which refers to the container iterated over.
StringRef LoopConvertCheck::getContainerString(ASTContext *Context,
                                               const ForStmt *Loop,
                                               const Expr *ContainerExpr) {}

/// Determines what kind of 'auto' must be used after converting a for
/// loop that iterates over an array or pseudoarray.
void LoopConvertCheck::getArrayLoopQualifiers(ASTContext *Context,
                                              const BoundNodes &Nodes,
                                              const Expr *ContainerExpr,
                                              const UsageResult &Usages,
                                              RangeDescriptor &Descriptor) {}

/// Determines what kind of 'auto' must be used after converting an
/// iterator based for loop.
void LoopConvertCheck::getIteratorLoopQualifiers(ASTContext *Context,
                                                 const BoundNodes &Nodes,
                                                 RangeDescriptor &Descriptor) {}

/// Determines the parameters needed to build the range replacement.
void LoopConvertCheck::determineRangeDescriptor(
    ASTContext *Context, const BoundNodes &Nodes, const ForStmt *Loop,
    LoopFixerKind FixerKind, const Expr *ContainerExpr,
    const UsageResult &Usages, RangeDescriptor &Descriptor) {}

/// Check some of the conditions that must be met for the loop to be
/// convertible.
bool LoopConvertCheck::isConvertible(ASTContext *Context,
                                     const ast_matchers::BoundNodes &Nodes,
                                     const ForStmt *Loop,
                                     LoopFixerKind FixerKind) {}

void LoopConvertCheck::check(const MatchFinder::MatchResult &Result) {}

llvm::StringRef LoopConvertCheck::getReverseFunction() const {}

llvm::StringRef LoopConvertCheck::getReverseHeader() const {}

} // namespace modernize
} // namespace clang::tidy