Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:22

0001 //===--- RenamerClangTidyCheck.h - clang-tidy -------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
0010 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
0011 
0012 #include "../ClangTidyCheck.h"
0013 #include "llvm/ADT/DenseMap.h"
0014 #include "llvm/ADT/DenseSet.h"
0015 #include "llvm/ADT/FunctionExtras.h"
0016 #include <optional>
0017 #include <string>
0018 #include <utility>
0019 
0020 namespace clang {
0021 
0022 class MacroInfo;
0023 
0024 namespace tidy {
0025 
0026 /// Base class for clang-tidy checks that want to flag declarations and/or
0027 /// macros for renaming based on customizable criteria.
0028 class RenamerClangTidyCheck : public ClangTidyCheck {
0029 public:
0030   RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
0031   ~RenamerClangTidyCheck();
0032 
0033   /// Derived classes should not implement any matching logic themselves; this
0034   /// class will do the matching and call the derived class'
0035   /// getDeclFailureInfo() and getMacroFailureInfo() for determining whether a
0036   /// given identifier passes or fails the check.
0037   void registerMatchers(ast_matchers::MatchFinder *Finder) final;
0038   void check(const ast_matchers::MatchFinder::MatchResult &Result) final;
0039   void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
0040                            Preprocessor *ModuleExpanderPP) final;
0041   void onEndOfTranslationUnit() final;
0042 
0043   /// Derived classes that override this function should call this method from
0044   /// the overridden method.
0045   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
0046 
0047   /// This enum will be used in %select of the diagnostic message.
0048   /// Each value below IgnoreFailureThreshold should have an error message.
0049   enum class ShouldFixStatus {
0050     ShouldFix,
0051 
0052     /// The fixup will conflict with a language keyword,
0053     /// so we can't fix it automatically.
0054     ConflictsWithKeyword,
0055 
0056     /// The fixup will conflict with a macro
0057     /// definition, so we can't fix it
0058     /// automatically.
0059     ConflictsWithMacroDefinition,
0060 
0061     /// The fixup results in an identifier that is not a valid c/c++ identifier.
0062     FixInvalidIdentifier,
0063 
0064     /// Values pass this threshold will be ignored completely
0065     /// i.e no message, no fixup.
0066     IgnoreFailureThreshold,
0067 
0068     /// If the identifier was used or declared within a macro we
0069     /// won't offer a fixup for safety reasons.
0070     InsideMacro,
0071   };
0072 
0073   /// Information describing a failed check
0074   struct FailureInfo {
0075     std::string KindName; // Tag or misc info to be used as derived classes need
0076     std::string Fixup;    // The name that will be proposed as a fix-it hint
0077   };
0078 
0079   /// Holds an identifier name check failure, tracking the kind of the
0080   /// identifier, its possible fixup and the starting locations of all the
0081   /// identifier usages.
0082   struct NamingCheckFailure {
0083     FailureInfo Info;
0084 
0085     /// Whether the failure should be fixed or not.
0086     ///
0087     /// e.g.: if the identifier was used or declared within a macro we won't
0088     /// offer a fixup for safety reasons.
0089     bool shouldFix() const {
0090       return FixStatus == ShouldFixStatus::ShouldFix && !Info.Fixup.empty();
0091     }
0092 
0093     bool shouldNotify() const {
0094       return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;
0095     }
0096 
0097     ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;
0098 
0099     /// A set of all the identifier usages starting SourceLocation.
0100     llvm::DenseSet<SourceLocation> RawUsageLocs;
0101 
0102     NamingCheckFailure() = default;
0103   };
0104 
0105   using NamingCheckId = std::pair<SourceLocation, StringRef>;
0106 
0107   using NamingCheckFailureMap =
0108       llvm::DenseMap<NamingCheckId, NamingCheckFailure>;
0109 
0110   /// Check Macros for style violations.
0111   void checkMacro(const Token &MacroNameTok, const MacroInfo *MI,
0112                   const SourceManager &SourceMgr);
0113 
0114   /// Add a usage of a macro if it already has a violation.
0115   void expandMacro(const Token &MacroNameTok, const MacroInfo *MI,
0116                    const SourceManager &SourceMgr);
0117 
0118   void addUsage(const NamedDecl *Decl, SourceRange Range,
0119                 const SourceManager &SourceMgr);
0120 
0121 protected:
0122   /// Overridden by derived classes, returns information about if and how a Decl
0123   /// failed the check. A 'std::nullopt' result means the Decl did not fail the
0124   /// check.
0125   virtual std::optional<FailureInfo>
0126   getDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;
0127 
0128   /// Overridden by derived classes, returns information about if and how a
0129   /// macro failed the check. A 'std::nullopt' result means the macro did not
0130   /// fail the check.
0131   virtual std::optional<FailureInfo>
0132   getMacroFailureInfo(const Token &MacroNameTok,
0133                       const SourceManager &SM) const = 0;
0134 
0135   /// Represents customized diagnostic text and how arguments should be applied.
0136   /// Example usage:
0137   ///
0138   /// return DiagInfo{"my %1 very %2 special %3 text",
0139   ///                  [=](DiagnosticBuilder &diag) {
0140   ///                    diag << arg1 << arg2 << arg3;
0141   ///                  }};
0142   struct DiagInfo {
0143     std::string Text;
0144     llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;
0145   };
0146 
0147   /// Overridden by derived classes, returns a description of the diagnostic
0148   /// that should be emitted for the given failure. The base class will then
0149   /// further customize the diagnostic by adding info about whether the fix-it
0150   /// can be automatically applied or not.
0151   virtual DiagInfo getDiagInfo(const NamingCheckId &ID,
0152                                const NamingCheckFailure &Failure) const = 0;
0153 
0154 private:
0155   // Manage additions to the Failure/usage map
0156   //
0157   // return the result of NamingCheckFailures::try_emplace() if the usage was
0158   // accepted.
0159   std::pair<NamingCheckFailureMap::iterator, bool>
0160   addUsage(const RenamerClangTidyCheck::NamingCheckId &FailureId,
0161            SourceRange UsageRange, const SourceManager &SourceMgr);
0162 
0163   NamingCheckFailureMap NamingCheckFailures;
0164   const bool AggressiveDependentMemberLookup;
0165 };
0166 
0167 } // namespace tidy
0168 } // namespace clang
0169 
0170 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H