xref: /llvm-project/clang-tools-extra/clang-tidy/utils/UseRangesCheck.h (revision 0762db6533eda3453158c7b9b0631542c47093a8)
1 //===--- UseRangesCheck.h - clang-tidy --------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_USERANGESCHECK_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_USERANGESCHECK_H
11 
12 #include "../ClangTidyCheck.h"
13 #include "IncludeInserter.h"
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/Expr.h"
16 #include "clang/Basic/Diagnostic.h"
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringRef.h"
20 #include <optional>
21 
22 namespace clang::tidy::utils {
23 
24 /// Base class for handling converting std iterator algorithms to a range
25 /// equivalent.
26 class UseRangesCheck : public ClangTidyCheck {
27 public:
28   struct Indexes {
29     enum Replace { First, Second };
30     unsigned BeginArg;
31     unsigned EndArg = BeginArg + 1;
32     Replace ReplaceArg = First;
33   };
34 
35   using Signature = SmallVector<Indexes, 2>;
36 
37   struct ReverseIteratorDescriptor {
38     StringRef ReverseAdaptorName;
39     std::optional<StringRef> ReverseHeader;
40     ArrayRef<std::pair<StringRef, StringRef>> FreeReverseNames;
41     bool IsPipeSyntax = false;
42   };
43 
44   class Replacer : public llvm::RefCountedBase<Replacer> {
45   public:
46     /// Gets the name to replace a function with, return std::nullopt for a
47     /// replacement where we just call a different overload.
48     virtual std::optional<std::string>
49     getReplaceName(const NamedDecl &OriginalName) const = 0;
50 
51     /// Gets the header needed to access the replaced function
52     /// Return std::nullopt if no new header is needed.
53     virtual std::optional<std::string>
54     getHeaderInclusion(const NamedDecl &OriginalName) const;
55 
56     /// Gets an array of all the possible overloads for a function with indexes
57     /// where begin and end arguments are.
58     virtual ArrayRef<Signature> getReplacementSignatures() const = 0;
59     virtual ~Replacer() = default;
60   };
61 
62   using ReplacerMap = llvm::StringMap<llvm::IntrusiveRefCntPtr<Replacer>>;
63 
64   UseRangesCheck(StringRef Name, ClangTidyContext *Context);
65   /// Gets a map of function to replace and methods to create the replacements
66   virtual ReplacerMap getReplacerMap() const = 0;
67   /// Create a diagnostic for the CallExpr
68   /// Override this to support custom diagnostic messages
69   virtual DiagnosticBuilder createDiag(const CallExpr &Call);
70 
71   virtual std::optional<ReverseIteratorDescriptor> getReverseDescriptor() const;
72 
73   /// Gets the fully qualified names of begin and end functions.
74   /// The functions must take the container as their one and only argument
75   /// `::std::begin` and `::std::end` are a common example
76   virtual ArrayRef<std::pair<StringRef, StringRef>>
77   getFreeBeginEndMethods() const;
78 
79   void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
80                            Preprocessor *ModuleExpanderPP) final;
81   void registerMatchers(ast_matchers::MatchFinder *Finder) final;
82   void check(const ast_matchers::MatchFinder::MatchResult &Result) final;
83   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
84   void storeOptions(ClangTidyOptions::OptionMap &Options) override;
85   std::optional<TraversalKind> getCheckTraversalKind() const override;
86 
87 private:
88   std::vector<llvm::IntrusiveRefCntPtr<Replacer>> Replacers;
89   std::optional<ReverseIteratorDescriptor> ReverseDescriptor;
90   IncludeInserter Inserter;
91 };
92 
93 } // namespace clang::tidy::utils
94 
95 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_USERANGESCHECK_H
96