117 lines · c
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H11 12#include "../ClangTidyCheck.h"13#include "clang/Lex/Lexer.h"14#include <llvm/ADT/APFloat.h>15#include <llvm/ADT/SmallVector.h>16 17namespace 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/// https://clang.llvm.org/extra/clang-tidy/checks/readability/magic-numbers.html23class MagicNumbersCheck : public ClangTidyCheck {24public: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 30private: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 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 44 bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &,45 const FloatingLiteral &) const {46 return false;47 }48 49 bool50 isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result,51 const IntegerLiteral &Literal) const;52 53 bool isUserDefinedLiteral(54 const clang::ast_matchers::MatchFinder::MatchResult &Result,55 const clang::Expr &Literal) const;56 57 template <typename L>58 void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,59 const char *BoundName) {60 const L *MatchedLiteral = Result.Nodes.getNodeAs<L>(BoundName);61 if (!MatchedLiteral)62 return;63 64 if (Result.SourceManager->isMacroBodyExpansion(65 MatchedLiteral->getLocation()))66 return;67 68 if (isIgnoredValue(MatchedLiteral))69 return;70 71 if (isConstant(Result, *MatchedLiteral))72 return;73 74 if (isSyntheticValue(Result.SourceManager, MatchedLiteral))75 return;76 77 if (isBitFieldWidth(Result, *MatchedLiteral))78 return;79 80 if (IgnoreUserDefinedLiterals &&81 isUserDefinedLiteral(Result, *MatchedLiteral))82 return;83 84 const StringRef LiteralSourceText = Lexer::getSourceText(85 CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),86 *Result.SourceManager, getLangOpts());87 88 diag(MatchedLiteral->getLocation(),89 "%0 is a magic number; consider replacing it with a named constant")90 << LiteralSourceText;91 }92 93 const bool IgnoreAllFloatingPointValues;94 const bool IgnoreBitFieldsWidths;95 const bool IgnorePowersOf2IntegerValues;96 const bool IgnoreTypeAliases;97 const bool IgnoreUserDefinedLiterals;98 const StringRef RawIgnoredIntegerValues;99 const StringRef RawIgnoredFloatingPointValues;100 101 constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16;102 103 constexpr static llvm::APFloat::roundingMode DefaultRoundingMode =104 llvm::APFloat::rmNearestTiesToEven;105 106 llvm::SmallVector<int64_t, SensibleNumberOfMagicValueExceptions>107 IgnoredIntegerValues;108 llvm::SmallVector<float, SensibleNumberOfMagicValueExceptions>109 IgnoredFloatingPointValues;110 llvm::SmallVector<double, SensibleNumberOfMagicValueExceptions>111 IgnoredDoublePointValues;112};113 114} // namespace clang::tidy::readability115 116#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H117