carlosgalvezp created this revision.
Herald added subscribers: PiotrZSL, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
carlosgalvezp requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Some user-defined literals operate on implementation-defined types, like
"unsigned long long" and "long double", which are not well supported by
this check. Currently, the check gives warnings when using UDLs, without
giving possiblity to the user to whitelist common UDLs. A good compromise
until a proper fix is found (if any) is to allow the user to disable
warnings on UDLs.

Partially fixes #61656


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146913

Files:
  clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
  clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp
@@ -1,10 +1,18 @@
-// RUN: %check_clang_tidy -std=c++14-or-later %s readability-magic-numbers %t --
+// RUN: %check_clang_tidy -check-suffixes=UDL-ALLOWED -std=c++14-or-later %s readability-magic-numbers %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: readability-magic-numbers.IgnoreUserDefinedLiterals, value: false}]}' \
+// RUN: --
+// RUN: %check_clang_tidy -check-suffixes=UDL-IGNORED -std=c++14-or-later %s readability-magic-numbers %t \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: readability-magic-numbers.IgnoreUserDefinedLiterals, value: true}]}' \
+// RUN: --
 
 namespace std {
   class string {};
   using size_t = decltype(sizeof(int));
   string operator ""s(const char *, std::size_t);
   int operator "" s(unsigned long long);
+  float operator "" s(long double);
 }
 
 void UserDefinedLiteral() {
@@ -12,5 +20,9 @@
   "Hello World"s;
   const int i = 3600s;
   int j = 3600s;
-  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+  // CHECK-MESSAGES-UDL-ALLOWED: :[[@LINE-1]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+  // CHECK-MESSAGES-UDL-IGNORED-NOT: :[[@LINE-2]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+  float k = 3600.0s;
+  // CHECK-MESSAGES-UDL-ALLOWED: :[[@LINE-1]]:13: warning: 3600.0s is a magic number; consider replacing it with a named constant [readability-magic-numbers]
+  // CHECK-MESSAGES-UDL-IGNORED-NOT: :[[@LINE-1]]:13: warning: 3600.0s is a magic number; consider replacing it with a named constant [readability-magic-numbers]
 }
Index: clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst
@@ -57,7 +57,7 @@
 
    const size_t NUMBER_OF_ELEMENTS = 30;
    using containerType = CustomType<int, NUMBER_OF_ELEMENTS>;
-   
+
    struct OtherType {
       containerType container;
    }
@@ -144,3 +144,8 @@
 
    Boolean value indicating whether to accept magic numbers in ``typedef`` or
    ``using`` declarations. Default value is `false`.
+
+.. option:: IgnoreUserDefinedLiterals
+
+   Boolean value indicating whether to accept magic numbers in user-defined
+   literals. Default value is `false`.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -211,6 +211,9 @@
   behavior of using `i` as the prefix for enum tags, set the `EnumConstantPrefix`
   option to `i` instead of using `EnumConstantHungarianPrefix`.
 
+- Added support to optionally ignore user-defined literals in
+  :doc:`readability-magic-numbers<clang-tidy/checks/readability/magic-numbers>`.
+
 - Fixed a false positive in :doc:`readability-container-size-empty
   <clang-tidy/checks/readability/container-size-empty>` check when comparing
   ``std::array`` objects to default constructed ones. The behavior for this and
Index: clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
===================================================================
--- clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
+++ clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
@@ -49,6 +49,15 @@
   bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result,
                        const IntegerLiteral &Literal) const;
 
+  bool isUserDefinedLiteral(
+      const clang::ast_matchers::MatchFinder::MatchResult &Result,
+      const clang::Expr *Literal) const {
+     auto Parents = Result.Context->getParents(*Literal);
+     if (Parents.empty())
+       return false;
+     return Parents[0].get<UserDefinedLiteral>() != nullptr;
+  }
+
   template <typename L>
   void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,
                        const char *BoundName) {
@@ -72,6 +81,10 @@
     if (isBitFieldWidth(Result, *MatchedLiteral))
       return;
 
+    if (IgnoreUserDefinedLiterals &&
+        isUserDefinedLiteral(Result, MatchedLiteral))
+      return;
+
     const StringRef LiteralSourceText = Lexer::getSourceText(
         CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),
         *Result.SourceManager, getLangOpts());
@@ -85,6 +98,7 @@
   const bool IgnoreBitFieldsWidths;
   const bool IgnorePowersOf2IntegerValues;
   const bool IgnoreTypeAliases;
+  const bool IgnoreUserDefinedLiterals;
   const StringRef RawIgnoredIntegerValues;
   const StringRef RawIgnoredFloatingPointValues;
 
Index: clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -81,6 +81,8 @@
       IgnorePowersOf2IntegerValues(
           Options.get("IgnorePowersOf2IntegerValues", false)),
       IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)),
+      IgnoreUserDefinedLiterals(
+          Options.get("IgnoreUserDefinedLiterals", false)),
       RawIgnoredIntegerValues(
           Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues)),
       RawIgnoredFloatingPointValues(Options.get(
@@ -130,6 +132,7 @@
   Options.store(Opts, "IgnorePowersOf2IntegerValues",
                 IgnorePowersOf2IntegerValues);
   Options.store(Opts, "IgnoreTypeAliases", IgnoreTypeAliases);
+  Options.store(Opts, "IgnoreUserDefinedLiterals", IgnoreUserDefinedLiterals);
   Options.store(Opts, "IgnoredIntegerValues", RawIgnoredIntegerValues);
   Options.store(Opts, "IgnoredFloatingPointValues",
                 RawIgnoredFloatingPointValues);
@@ -202,6 +205,7 @@
 
 bool MagicNumbersCheck::isIgnoredValue(const FloatingLiteral *Literal) const {
   const llvm::APFloat FloatValue = Literal->getValue();
+
   if (FloatValue.isZero())
     return true;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to