1 //===--- MagicNumbersCheck.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_READABILITY_MAGICNUMBERSCHECK_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
11 
12 #include "../ClangTidyCheck.h"
13 #include "clang/Lex/Lexer.h"
14 #include <llvm/ADT/APFloat.h>
15 #include <llvm/ADT/SmallVector.h>
16 
17 namespace clang::tidy::readability {
18 
19 /// Detects magic numbers, integer and floating point literals embedded in code.
20 ///
21 /// For the user-facing documentation see:
22 /// http://clang.llvm.org/extra/clang-tidy/checks/readability/magic-numbers.html
23 class MagicNumbersCheck : public ClangTidyCheck {
24 public:
25   MagicNumbersCheck(StringRef Name, ClangTidyContext *Context);
26   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
27   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
28   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
29 
30 private:
31   bool isConstant(const clang::ast_matchers::MatchFinder::MatchResult &Result,
32                   const clang::Expr &ExprResult) const;
33 
34   bool isIgnoredValue(const IntegerLiteral *Literal) const;
35   bool isIgnoredValue(const FloatingLiteral *Literal) const;
36 
isSyntheticValue(const clang::SourceManager *,const FloatingLiteral *)37   bool isSyntheticValue(const clang::SourceManager *,
38                         const FloatingLiteral *) const {
39     return false;
40   }
41   bool isSyntheticValue(const clang::SourceManager *SourceManager,
42                         const IntegerLiteral *Literal) const;
43 
isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &,const FloatingLiteral &)44   bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &,
45                        const FloatingLiteral &) const {
46      return false;
47   }
48 
49   bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result,
50                        const IntegerLiteral &Literal) const;
51 
52   bool isUserDefinedLiteral(
53       const clang::ast_matchers::MatchFinder::MatchResult &Result,
54       const clang::Expr &Literal) const;
55 
56   template <typename L>
checkBoundMatch(const ast_matchers::MatchFinder::MatchResult & Result,const char * BoundName)57   void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,
58                        const char *BoundName) {
59     const L *MatchedLiteral = Result.Nodes.getNodeAs<L>(BoundName);
60     if (!MatchedLiteral)
61       return;
62 
63     if (Result.SourceManager->isMacroBodyExpansion(
64             MatchedLiteral->getLocation()))
65       return;
66 
67     if (isIgnoredValue(MatchedLiteral))
68       return;
69 
70     if (isConstant(Result, *MatchedLiteral))
71       return;
72 
73     if (isSyntheticValue(Result.SourceManager, MatchedLiteral))
74       return;
75 
76     if (isBitFieldWidth(Result, *MatchedLiteral))
77       return;
78 
79     if (IgnoreUserDefinedLiterals &&
80         isUserDefinedLiteral(Result, *MatchedLiteral))
81       return;
82 
83     const StringRef LiteralSourceText = Lexer::getSourceText(
84         CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),
85         *Result.SourceManager, getLangOpts());
86 
87     diag(MatchedLiteral->getLocation(),
88          "%0 is a magic number; consider replacing it with a named constant")
89         << LiteralSourceText;
90   }
91 
92   const bool IgnoreAllFloatingPointValues;
93   const bool IgnoreBitFieldsWidths;
94   const bool IgnorePowersOf2IntegerValues;
95   const bool IgnoreTypeAliases;
96   const bool IgnoreUserDefinedLiterals;
97   const StringRef RawIgnoredIntegerValues;
98   const StringRef RawIgnoredFloatingPointValues;
99 
100   constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16;
101 
102   constexpr static llvm::APFloat::roundingMode DefaultRoundingMode =
103       llvm::APFloat::rmNearestTiesToEven;
104 
105   llvm::SmallVector<int64_t, SensibleNumberOfMagicValueExceptions>
106       IgnoredIntegerValues;
107   llvm::SmallVector<float, SensibleNumberOfMagicValueExceptions>
108       IgnoredFloatingPointValues;
109   llvm::SmallVector<double, SensibleNumberOfMagicValueExceptions>
110       IgnoredDoublePointValues;
111 };
112 
113 } // namespace clang::tidy::readability
114 
115 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
116