blob: db4cc886553b67722ce09a538a317d3c2bdcaca8 [file] [log] [blame]
Aaron Ballmanbc8f5ac2018-08-12 14:35:13 +00001//===--- MagicNumbersCheck.h - clang-tidy-----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
12
13#include "../ClangTidy.h"
14#include <llvm/ADT/APFloat.h>
15#include <llvm/ADT/SmallVector.h>
16#include <vector>
17
18namespace clang {
19namespace tidy {
20namespace readability {
21
22/// Detects magic numbers, integer and floating point literals embedded in code.
23///
24/// For the user-facing documentation see:
25/// http://clang.llvm.org/extra/clang-tidy/checks/readability-magic-numbers.html
26class MagicNumbersCheck : public ClangTidyCheck {
27public:
28 MagicNumbersCheck(StringRef Name, ClangTidyContext *Context);
29 void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
30 void registerMatchers(ast_matchers::MatchFinder *Finder) override;
31 void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
32
33private:
34 bool isConstant(const clang::ast_matchers::MatchFinder::MatchResult &Result,
35 const clang::Expr &ExprResult) const;
36
37 bool isIgnoredValue(const IntegerLiteral *Literal) const;
38 bool isIgnoredValue(const FloatingLiteral *Literal) const;
39
40 bool isSyntheticValue(const clang::SourceManager *,
41 const FloatingLiteral *) const {
42 return false;
43 }
44
45 bool isSyntheticValue(const clang::SourceManager *SourceManager,
46 const IntegerLiteral *Literal) const;
47
48 template <typename L>
49 void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,
50 const char *BoundName) {
51 const L *MatchedLiteral = Result.Nodes.getNodeAs<L>(BoundName);
52 if (!MatchedLiteral)
53 return;
54
55 if (Result.SourceManager->isMacroBodyExpansion(
56 MatchedLiteral->getLocation()))
57 return;
58
59 if (isIgnoredValue(MatchedLiteral))
60 return;
61
62 if (isConstant(Result, *MatchedLiteral))
63 return;
64
65 if (isSyntheticValue(Result.SourceManager, MatchedLiteral))
66 return;
67
68 const StringRef LiteralSourceText = Lexer::getSourceText(
69 CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),
70 *Result.SourceManager, getLangOpts());
71
72 diag(MatchedLiteral->getLocation(),
73 "%0 is a magic number; consider replacing it with a named constant")
74 << LiteralSourceText;
75 }
76
77 const bool IgnoreAllFloatingPointValues;
78 const bool IgnorePowersOf2IntegerValues;
79
80 constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16;
81
82 constexpr static llvm::APFloat::roundingMode DefaultRoundingMode =
83 llvm::APFloat::rmNearestTiesToEven;
84
85 llvm::SmallVector<int64_t, SensibleNumberOfMagicValueExceptions>
86 IgnoredIntegerValues;
87 llvm::SmallVector<float, SensibleNumberOfMagicValueExceptions>
88 IgnoredFloatingPointValues;
89 llvm::SmallVector<double, SensibleNumberOfMagicValueExceptions>
90 IgnoredDoublePointValues;
91};
92
93} // namespace readability
94} // namespace tidy
95} // namespace clang
96
97#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H