[clang-tools-extra] r339516 - Add a new check to the readability module that flags uses of "magic numbers" (both floating-point and integral).
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 12 07:35:13 PDT 2018
Author: aaronballman
Date: Sun Aug 12 07:35:13 2018
New Revision: 339516
URL: http://llvm.org/viewvc/llvm-project?rev=339516&view=rev
Log:
Add a new check to the readability module that flags uses of "magic numbers" (both floating-point and integral).
Patch by Florin Iucha <florin at signbit.net>
Added:
clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.cpp
clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-avoid-magic-numbers.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/readability-magic-numbers.rst
clang-tools-extra/trunk/test/clang-tidy/readability-magic-numbers.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=339516&r1=339515&r2=339516&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp Sun Aug 12 07:35:13 2018
@@ -11,6 +11,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../misc/UnconventionalAssignOperatorCheck.h"
+#include "../readability/MagicNumbersCheck.h"
#include "AvoidGotoCheck.h"
#include "InterfacesGlobalInitCheck.h"
#include "NarrowingConversionsCheck.h"
@@ -41,6 +42,8 @@ public:
"cppcoreguidelines-avoid-goto");
CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
"cppcoreguidelines-interfaces-global-init");
+ CheckFactories.registerCheck<readability::MagicNumbersCheck>(
+ "cppcoreguidelines-avoid-magic-numbers");
CheckFactories.registerCheck<NarrowingConversionsCheck>(
"cppcoreguidelines-narrowing-conversions");
CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc");
Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=339516&r1=339515&r2=339516&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Sun Aug 12 07:35:13 2018
@@ -11,6 +11,7 @@ add_clang_library(clangTidyReadabilityMo
IdentifierNamingCheck.cpp
ImplicitBoolConversionCheck.cpp
InconsistentDeclarationParameterNameCheck.cpp
+ MagicNumbersCheck.cpp
MisleadingIndentationCheck.cpp
MisplacedArrayIndexCheck.cpp
NamedParameterCheck.cpp
Added: clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.cpp?rev=339516&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.cpp Sun Aug 12 07:35:13 2018
@@ -0,0 +1,171 @@
+//===--- MagicNumbersCheck.cpp - clang-tidy-------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A checker for magic numbers: integer or floating point literals embedded
+// in the code, outside the definition of a constant or an enumeration.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MagicNumbersCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+
+using namespace clang::ast_matchers;
+using namespace clang::ast_type_traits;
+
+namespace {
+
+bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result,
+ const DynTypedNode &Node) {
+
+ const auto *AsDecl = Node.get<clang::DeclaratorDecl>();
+ if (AsDecl) {
+ if (AsDecl->getType().isConstQualified())
+ return true;
+
+ return AsDecl->isImplicit();
+ }
+
+ if (Node.get<clang::EnumConstantDecl>() != nullptr)
+ return true;
+
+ return llvm::any_of(Result.Context->getParents(Node),
+ [&Result](const DynTypedNode &Parent) {
+ return isUsedToInitializeAConstant(Result, Parent);
+ });
+}
+
+} // namespace
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+const char DefaultIgnoredIntegerValues[] = "1;2;3;4;";
+const char DefaultIgnoredFloatingPointValues[] = "1.0;100.0;";
+
+MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IgnoreAllFloatingPointValues(
+ Options.get("IgnoreAllFloatingPointValues", false)),
+ IgnorePowersOf2IntegerValues(
+ Options.get("IgnorePowersOf2IntegerValues", false)) {
+ // Process the set of ignored integer values.
+ const std::vector<std::string> IgnoredIntegerValuesInput =
+ utils::options::parseStringList(
+ Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues));
+ IgnoredIntegerValues.resize(IgnoredIntegerValuesInput.size());
+ llvm::transform(IgnoredIntegerValuesInput, IgnoredIntegerValues.begin(),
+ [](const std::string &Value) { return std::stoll(Value); });
+ llvm::sort(IgnoredIntegerValues.begin(), IgnoredIntegerValues.end());
+
+ if (!IgnoreAllFloatingPointValues) {
+ // Process the set of ignored floating point values.
+ const std::vector<std::string> IgnoredFloatingPointValuesInput =
+ utils::options::parseStringList(Options.get(
+ "IgnoredFloatingPointValues", DefaultIgnoredFloatingPointValues));
+ IgnoredFloatingPointValues.reserve(IgnoredFloatingPointValuesInput.size());
+ IgnoredDoublePointValues.reserve(IgnoredFloatingPointValuesInput.size());
+ for (const auto &InputValue : IgnoredFloatingPointValuesInput) {
+ llvm::APFloat FloatValue(llvm::APFloat::IEEEsingle());
+ FloatValue.convertFromString(InputValue, DefaultRoundingMode);
+ IgnoredFloatingPointValues.push_back(FloatValue.convertToFloat());
+
+ llvm::APFloat DoubleValue(llvm::APFloat::IEEEdouble());
+ DoubleValue.convertFromString(InputValue, DefaultRoundingMode);
+ IgnoredDoublePointValues.push_back(DoubleValue.convertToDouble());
+ }
+ llvm::sort(IgnoredFloatingPointValues.begin(),
+ IgnoredFloatingPointValues.end());
+ llvm::sort(IgnoredDoublePointValues.begin(),
+ IgnoredDoublePointValues.end());
+ }
+}
+
+void MagicNumbersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IgnoredIntegerValues", DefaultIgnoredIntegerValues);
+ Options.store(Opts, "IgnoredFloatingPointValues",
+ DefaultIgnoredFloatingPointValues);
+}
+
+void MagicNumbersCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(integerLiteral().bind("integer"), this);
+ if (!IgnoreAllFloatingPointValues)
+ Finder->addMatcher(floatLiteral().bind("float"), this);
+}
+
+void MagicNumbersCheck::check(const MatchFinder::MatchResult &Result) {
+ checkBoundMatch<IntegerLiteral>(Result, "integer");
+ checkBoundMatch<FloatingLiteral>(Result, "float");
+}
+
+bool MagicNumbersCheck::isConstant(const MatchFinder::MatchResult &Result,
+ const Expr &ExprResult) const {
+ return llvm::any_of(
+ Result.Context->getParents(ExprResult),
+ [&Result](const DynTypedNode &Parent) {
+ return isUsedToInitializeAConstant(Result, Parent) ||
+ // Ignore this instance, because this match reports the location
+ // where the template is defined, not where it is instantiated.
+ Parent.get<SubstNonTypeTemplateParmExpr>();
+ });
+}
+
+bool MagicNumbersCheck::isIgnoredValue(const IntegerLiteral *Literal) const {
+ const llvm::APInt IntValue = Literal->getValue();
+ const int64_t Value = IntValue.getZExtValue();
+ if (Value == 0)
+ return true;
+
+ if (IgnorePowersOf2IntegerValues && IntValue.isPowerOf2())
+ return true;
+
+ return std::binary_search(IgnoredIntegerValues.begin(),
+ IgnoredIntegerValues.end(), Value);
+}
+
+bool MagicNumbersCheck::isIgnoredValue(const FloatingLiteral *Literal) const {
+ const llvm::APFloat FloatValue = Literal->getValue();
+ if (FloatValue.isZero())
+ return true;
+
+ if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEsingle()) {
+ const float Value = FloatValue.convertToFloat();
+ return std::binary_search(IgnoredFloatingPointValues.begin(),
+ IgnoredFloatingPointValues.end(), Value);
+ }
+
+ if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEdouble()) {
+ const double Value = FloatValue.convertToDouble();
+ return std::binary_search(IgnoredDoublePointValues.begin(),
+ IgnoredDoublePointValues.end(), Value);
+ }
+
+ return false;
+}
+
+bool MagicNumbersCheck::isSyntheticValue(const SourceManager *SourceManager,
+ const IntegerLiteral *Literal) const {
+ const std::pair<FileID, unsigned> FileOffset =
+ SourceManager->getDecomposedLoc(Literal->getLocation());
+ if (FileOffset.first.isInvalid())
+ return false;
+
+ const StringRef BufferIdentifier =
+ SourceManager->getBuffer(FileOffset.first)->getBufferIdentifier();
+
+ return BufferIdentifier.empty();
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.h?rev=339516&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/MagicNumbersCheck.h Sun Aug 12 07:35:13 2018
@@ -0,0 +1,97 @@
+//===--- MagicNumbersCheck.h - clang-tidy-----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
+
+#include "../ClangTidy.h"
+#include <llvm/ADT/APFloat.h>
+#include <llvm/ADT/SmallVector.h>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Detects magic numbers, integer and floating point literals embedded in code.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-magic-numbers.html
+class MagicNumbersCheck : public ClangTidyCheck {
+public:
+ MagicNumbersCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ bool isConstant(const clang::ast_matchers::MatchFinder::MatchResult &Result,
+ const clang::Expr &ExprResult) const;
+
+ bool isIgnoredValue(const IntegerLiteral *Literal) const;
+ bool isIgnoredValue(const FloatingLiteral *Literal) const;
+
+ bool isSyntheticValue(const clang::SourceManager *,
+ const FloatingLiteral *) const {
+ return false;
+ }
+
+ bool isSyntheticValue(const clang::SourceManager *SourceManager,
+ const IntegerLiteral *Literal) const;
+
+ template <typename L>
+ void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,
+ const char *BoundName) {
+ const L *MatchedLiteral = Result.Nodes.getNodeAs<L>(BoundName);
+ if (!MatchedLiteral)
+ return;
+
+ if (Result.SourceManager->isMacroBodyExpansion(
+ MatchedLiteral->getLocation()))
+ return;
+
+ if (isIgnoredValue(MatchedLiteral))
+ return;
+
+ if (isConstant(Result, *MatchedLiteral))
+ return;
+
+ if (isSyntheticValue(Result.SourceManager, MatchedLiteral))
+ return;
+
+ const StringRef LiteralSourceText = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),
+ *Result.SourceManager, getLangOpts());
+
+ diag(MatchedLiteral->getLocation(),
+ "%0 is a magic number; consider replacing it with a named constant")
+ << LiteralSourceText;
+ }
+
+ const bool IgnoreAllFloatingPointValues;
+ const bool IgnorePowersOf2IntegerValues;
+
+ constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16;
+
+ constexpr static llvm::APFloat::roundingMode DefaultRoundingMode =
+ llvm::APFloat::rmNearestTiesToEven;
+
+ llvm::SmallVector<int64_t, SensibleNumberOfMagicValueExceptions>
+ IgnoredIntegerValues;
+ llvm::SmallVector<float, SensibleNumberOfMagicValueExceptions>
+ IgnoredFloatingPointValues;
+ llvm::SmallVector<double, SensibleNumberOfMagicValueExceptions>
+ IgnoredDoublePointValues;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MAGICNUMBERSCHECK_H
Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=339516&r1=339515&r2=339516&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Sun Aug 12 07:35:13 2018
@@ -20,6 +20,7 @@
#include "IdentifierNamingCheck.h"
#include "ImplicitBoolConversionCheck.h"
#include "InconsistentDeclarationParameterNameCheck.h"
+#include "MagicNumbersCheck.h"
#include "MisleadingIndentationCheck.h"
#include "MisplacedArrayIndexCheck.h"
#include "NamedParameterCheck.h"
@@ -65,6 +66,8 @@ public:
"readability-implicit-bool-conversion");
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
"readability-inconsistent-declaration-parameter-name");
+ CheckFactories.registerCheck<MagicNumbersCheck>(
+ "readability-magic-numbers");
CheckFactories.registerCheck<MisleadingIndentationCheck>(
"readability-misleading-indentation");
CheckFactories.registerCheck<MisplacedArrayIndexCheck>(
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=339516&r1=339515&r2=339516&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Sun Aug 12 07:35:13 2018
@@ -59,6 +59,12 @@ Improvements to clang-tidy
The improvements are...
+- New :doc:`readability-magic-numbers
+ <clang-tidy/checks/readability-magic-numbers>` check.
+
+ Detect usage of magic numbers, numbers that are used as literals instead of
+ introduced via constants or symbols.
+
Improvements to include-fixer
-----------------------------
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-avoid-magic-numbers.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-avoid-magic-numbers.rst?rev=339516&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-avoid-magic-numbers.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-avoid-magic-numbers.rst Sun Aug 12 07:35:13 2018
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cppcoreguidelines-avoid-magic-numbers
+.. meta::
+ :http-equiv=refresh: 5;URL=readability-magic-numbers.html
+
+cppcoreguidelines-avoid-magic-numbers
+=====================================
+
+The cppcoreguidelines-avoid-magic-numbers check is an alias, please see
+`readability-magic-numbers <readability-magic-numbers.html>`_
+for more information.
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=339516&r1=339515&r2=339516&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Sun Aug 12 07:35:13 2018
@@ -79,6 +79,7 @@ Clang-Tidy Checks
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
cppcoreguidelines-avoid-goto
+ cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) <cppcoreguidelines-avoid-magic-numbers>
cppcoreguidelines-c-copy-assignment-signature (redirects to misc-unconventional-assign-operator) <cppcoreguidelines-c-copy-assignment-signature>
cppcoreguidelines-interfaces-global-init
cppcoreguidelines-narrowing-conversions
@@ -218,6 +219,7 @@ Clang-Tidy Checks
readability-identifier-naming
readability-implicit-bool-conversion
readability-inconsistent-declaration-parameter-name
+ readability-magic-numbers
readability-misleading-indentation
readability-misplaced-array-index
readability-named-parameter
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-magic-numbers.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-magic-numbers.rst?rev=339516&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-magic-numbers.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-magic-numbers.rst Sun Aug 12 07:35:13 2018
@@ -0,0 +1,113 @@
+.. title:: clang-tidy - readability-magic-numbers
+
+readability-magic-numbers
+=========================
+
+Detects magic numbers, integer or floating point literals that are embedded in
+code and not introduced via constants or symbols.
+
+Many coding guidelines advise replacing the magic values with symbolic
+constants to improve readability. Here are a few references:
+
+ * `Rule ES.45: Avoid âmagic constantsâ; use symbolic constants in C++ Core Guidelines <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-magic>`_
+ * `Rule 5.1.1 Use symbolic names instead of literal values in code in High Integrity C++ <http://www.codingstandard.com/rule/5-1-1-use-symbolic-names-instead-of-literal-values-in-code/>`_
+ * Item 17 in "C++ Coding Standards: 101 Rules, Guidelines and Best
+ Practices" by Herb Sutter and Andrei Alexandrescu
+ * Chapter 17 in "Clean Code - A handbook of agile software craftsmanship."
+ by Robert C. Martin
+ * Rule 20701 in "TRAIN REAL TIME DATA PROTOCOL Coding Rules" by Armin-Hagen
+ Weiss, Bombardier
+ * http://wiki.c2.com/?MagicNumber
+
+
+Examples of magic values:
+
+.. code-block:: c++
+
+ double circleArea = 3.1415926535 * radius * radius;
+
+ double totalCharge = 1.08 * itemPrice;
+
+ int getAnswer() {
+ return -3; // FILENOTFOUND
+ }
+
+ for (int mm = 1; mm <= 12; ++mm) {
+ std::cout << month[mm] << '\n';
+ }
+
+Example with magic values refactored:
+
+.. code-block:: c++
+
+ double circleArea = M_PI * radius * radius;
+
+ const double TAX_RATE = 0.08; // or make it variable and read from a file
+
+ double totalCharge = (1.0 + TAX_RATE) * itemPrice;
+
+ int getAnswer() {
+ return E_FILE_NOT_FOUND;
+ }
+
+ for (int mm = 1; mm <= MONTHS_IN_A_YEAR; ++mm) {
+ std::cout << month[mm] << '\n';
+ }
+
+For integral literals by default only `0` and `1` (and `-1`) integer values
+are accepted without a warning. This can be overridden with the
+:option:`IgnoredIntegerValues` option. Negative values are accepted if their
+absolute value is present in the :option:`IgnoredIntegerValues` list.
+
+As a special case for integral values, all powers of two can be accepted
+without warning by enabling the :option:`IgnorePowersOf2IntegerValues` option.
+
+For floating point literals by default the `0.0` floating point value is
+accepted without a warning. The set of ignored floating point literals can
+be configured using the :option:`IgnoredFloatingPointValues` option.
+For each value in that set, the given string value is converted to a
+floating-point value representation used by the target architecture. If a
+floating-point literal value compares equal to one of the converted values,
+then that literal is not diagnosed by this check. Because floating-point
+equality is used to determine whether to diagnose or not, the user needs to
+be aware of the details of floating-point representations for any values that
+cannot be precisely represented for their target architecture.
+
+For each value in the :option:`IgnoredFloatingPointValues` set, both the
+single-precision form and double-precision form are accepted (for example, if
+3.14 is in the set, neither 3.14f nor 3.14 will produce a warning).
+
+Scientific notation is supported for both source code input and option.
+Alternatively, the check for the floating point numbers can be disabled for
+all floating point values by enabling the
+:option:`IgnoreAllFloatingPointValues` option.
+
+Since values `0` and `0.0` are so common as the base counter of loops,
+or initialization values for sums, they are always accepted without warning,
+even if not present in the respective ignored values list.
+
+Options
+-------
+
+.. option:: IgnoredIntegerValues
+
+ Semicolon-separated list of magic positive integers that will be accepted
+ without a warning. Default values are `{1, 2, 3, 4}`, and `0` is accepted
+ unconditionally.
+
+.. option:: IgnorePowersOf2IntegerValues
+
+ Boolean value indicating whether to accept all powers-of-two integer values
+ without warning. Default value is `false`.
+
+.. option:: IgnoredFloatingPointValues
+
+ Semicolon-separated list of magic positive floating point values that will
+ be accepted without a warning. Default values are `{1.0, 100.0}` and `0.0`
+ is accepted unconditionally.
+
+.. option:: IgnoreAllFloatingPointValues
+
+ Boolean value indicating whether to accept all floating point values without
+ warning. Default value is `false`.
+
Added: clang-tools-extra/trunk/test/clang-tidy/readability-magic-numbers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-magic-numbers.cpp?rev=339516&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-magic-numbers.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-magic-numbers.cpp Sun Aug 12 07:35:13 2018
@@ -0,0 +1,199 @@
+// RUN: %check_clang_tidy %s readability-magic-numbers %t \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: readability-magic-numbers.IgnoredIntegerValues, value: "0;1;2;10;100;"}, \
+// RUN: {key: readability-magic-numbers.IgnoredFloatingPointValues, value: "3.14;2.71828;9.81;10000.0;101.0;0x1.2p3"}, \
+// RUN: {key: readability-magic-numbers.IgnorePowersOf2IntegerValues, value: 1}]}' \
+// RUN: --
+
+template <typename T, int V>
+struct ValueBucket {
+ T value[V];
+};
+
+int BadGlobalInt = 5;
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+int IntSquarer(int param) {
+ return param * param;
+}
+
+void BuggyFunction() {
+ int BadLocalInt = 6;
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+ (void)IntSquarer(7);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+ int LocalArray[15];
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 15 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+ for (int ii = 0; ii < 22; ++ii)
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 22 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+ {
+ LocalArray[ii] = 3 * ii;
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+ }
+
+ ValueBucket<int, 66> Bucket;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 66 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+}
+
+class TwoIntContainer {
+public:
+ TwoIntContainer(int val) : anotherMember(val * val), yetAnotherMember(6), anotherConstant(val + val) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:73: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+ int getValue() const;
+
+private:
+ int oneMember = 9;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 9 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+ int anotherMember;
+
+ int yetAnotherMember;
+
+ const int oneConstant = 2;
+
+ const int anotherConstant;
+};
+
+int ValueArray[] = {3, 5};
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+// CHECK-MESSAGES: :[[@LINE-2]]:24: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+float FloatPiVariable = 3.1415926535f;
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 3.1415926535f is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+double DoublePiVariable = 6.283185307;
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 6.283185307 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+float SomeFloats[] = {0.5, 0x1.2p4};
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 0.5 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+// CHECK-MESSAGES: :[[@LINE-2]]:28: warning: 0x1.2p4 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+
+int getAnswer() {
+ if (ValueArray[0] < ValueArray[1])
+ return ValueArray[1];
+
+ return -3; // FILENOTFOUND
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+}
+
+/*
+ * Clean code
+ */
+
+#define INT_MACRO 5
+
+const int GoodGlobalIntConstant = 42;
+
+constexpr int AlsoGoodGlobalIntConstant = 42;
+
+int InitializedByMacro = INT_MACRO;
+
+void SolidFunction() {
+ const int GoodLocalIntConstant = 43;
+
+ (void)IntSquarer(GoodLocalIntConstant);
+
+ int LocalArray[INT_MACRO];
+
+ ValueBucket<int, INT_MACRO> Bucket;
+}
+
+const int ConstValueArray[] = {7, 9};
+
+const int ConstValueArray2D[2][2] = {{7, 9}, {13, 15}};
+
+/*
+ * no warnings for ignored values (specified in the configuration above)
+ */
+int GrandfatheredIntegerValues[] = {0, 1, 2, 10, 100, -1, -10, -100, 65536};
+
+float GrandfatheredFloatValues[] = {3.14f, 3.14, 2.71828, 2.71828f, -1.01E2, 1E4, 0x1.2p3};
+
+/*
+ * no warnings for enums
+ */
+enum Smorgasbord {
+ STARTER,
+ ALPHA = 3,
+ BETA = 1 << 5,
+};
+
+const float FloatPiConstant = 3.1415926535f;
+const double DoublePiConstant = 6.283185307;
+
+const float Angles[] = {45.0f, 90.0f, 135.0f};
+
+double DoubleZeroIsAccepted = 0.0;
+float FloatZeroIsAccepted = 0.0f;
+
+namespace geometry {
+
+template <typename T>
+struct Point {
+ T x;
+ T y;
+
+ explicit Point(T xval, T yval) noexcept : x{xval}, y{yval} {
+ }
+};
+
+template <typename T>
+struct Dimension {
+ T x;
+ T y;
+
+ explicit Dimension(T xval, T yval) noexcept : x{xval}, y{yval} {
+ }
+};
+
+template <typename T>
+struct Rectangle {
+ Point<T> origin;
+ Dimension<T> size;
+ T rotation; // angle of rotation around origin
+
+ Rectangle(Point<T> origin_, Dimension<T> size_, T rotation_ = 0) noexcept : origin{origin_}, size{size_}, rotation{rotation_} {
+ }
+
+ bool contains(Point<T> point) const;
+};
+
+} // namespace geometry
+
+const geometry::Rectangle<double> mandelbrotCanvas{geometry::Point<double>{-2.5, -1}, geometry::Dimension<double>{3.5, 2}};
+
+// Simulate the macro magic in Google Test internal headers
+class AssertionHelper {
+public:
+ AssertionHelper(const char *Message, int LineNumber) : Message(Message), LineNumber(LineNumber) {}
+
+private:
+ const char *Message;
+ int LineNumber;
+};
+
+#define ASSERTION_HELPER_AT(M, L) AssertionHelper(M, L)
+
+#define ASSERTION_HELPER(M) ASSERTION_HELPER_AT(M, __LINE__)
+
+void FunctionWithCompilerDefinedSymbol(void) {
+ ASSERTION_HELPER("here and now");
+}
+
+// prove that integer literals introduced by the compiler are accepted silently
+extern int ConsumeString(const char *Input);
+
+const char *SomeStrings[] = {"alpha", "beta", "gamma"};
+
+int TestCheckerOverreach() {
+ int Total = 0;
+
+ for (const auto *Str : SomeStrings) {
+ Total += ConsumeString(Str);
+ }
+
+ return Total;
+}
More information about the cfe-commits
mailing list