This is an archive of the discontinued LLVM Phabricator instance.

[Clang-tidy] readability check to convert numerical constants to std::numeric_limits
Needs ReviewPublic

Authored by IdrissRio on Oct 4 2018, 9:44 AM.

Details

Summary

Hello, i want to propose this check suggested by @EugeneZelenko.
I have found it in the beginner tag of llvm-bugzilla repository.

This check looks for numerical unsigned constants that are equal to -1 or ~0
and substitutes them with std::numeric_limits<type>::max().

It includes the library <limits> if is not found.

Example:

unsigned const int x = -1;

becomes

unsigned const int x = std::numeric_limits<unsigned int>::max();

If the library <limits> is not include in the TU the check will add it with this criteria:

  • If a #include is found it will add #include <limits> before this include.
  • if no #include directive is found it will add it at the begin of the TU.

Event Timeline

IdrissRio created this revision.Oct 4 2018, 9:44 AM

The check itself isn't in the diff.

IdrissRio updated this revision to Diff 168321.Oct 4 2018, 9:48 AM

Sorry i have forgot to add the source code.

IdrissRio edited the summary of this revision. (Show Details)Oct 4 2018, 9:50 AM

Hi IdrissRio,

thanks for working on this! I have one question: Why are variables _not_ considered in the check but only constants? IMHO it would make sense to transform these as well.

I dont have time for long review today anymore, I will continue tomorrow.

clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
22

Unfortunatly this is duplicated effort.
Please take a look at cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp and
utils/IncludeInserter.{h,cpp} to add new includes from clang-tidy

90

Is failure here expected? The matcher should match both nodes simultanously, if so please use an assert instead to detect unexpected failures

docs/clang-tidy/checks/readability-numerical-costants-to-max-int.rst
16

please indent that code, otherwise its is rendered incorrect

Eugene.Zelenko retitled this revision from [Clang-tidy: readability] readability check to convert numerical constants to std::numeric_limits to [Clang-tidy] readability check to convert numerical constants to std::numeric_limits.Oct 4 2018, 10:23 AM
Eugene.Zelenko edited reviewers, added: hokein; removed: Eugene.Zelenko.
Eugene.Zelenko added a project: Restricted Project.

I think modernize is better module for this check.

clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
58

Semicolon at end is not necessary. Please also run Clang-format.

87

Unnecessary empty line.

docs/ReleaseNotes.rst
60

Please use alphabetical order for new checks.

63

Please enclose -1 and ~0 in `.

64

Please enclose std::numeric_limits<type>::max() in ``.

docs/clang-tidy/checks/readability-numerical-costants-to-max-int.rst
7

Please synchronize with Release Notes.

It'll be good idea to handle climits constants too.

jfb added a comment.Oct 4 2018, 10:56 AM

Can you also catch casts such as (unsigned)-1 ?

Eugene.Zelenko added inline comments.Oct 4 2018, 1:17 PM
clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
44

Unnecessary empty line.

@aaron.ballman I have a question for an expert: How would bitfields relate to this check? Can there be a similar pattern for them and do they need to be handled here?

clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
62

you dont need this-> and please use the same return early pattern as in the other registering call

64

its uncommong to specify the global namespace (first ::), you can remove these

77

Please use the full name for the bind, Literal or IntLiteral (please consistent with VarDecl, so CamelCase). I feel that this is more readable (no strong opinion though if you want to leave it as is)

93

Please declar this variable later, directly before usage (locality), and add const SourceManager* SM as you don't seem to manipulate SM

95

You can use llvm::Twine here which is very efficient for concatenation.

std::string Replacement = (Twine("std::numeric_limits<") + Decl->getType().getAtomicUnqualifiedType().getAsString() + ">::max()").str();
107

I think its better to create the source-range before to deal with exceptional cases (invalid ranges, macros)

docs/clang-tidy/checks/list.rst
12

spurious change, does it still happen on master? i thought this was ordered at some point already

219

this does not follow the naming convention (hyphens and not CamelCase)

docs/clang-tidy/checks/readability-numerical-costants-to-max-int.rst
4

please make === full length.

10

This line is slightly inaccurate. The library is the standard library, s/library/header-file

37

Please remove the empty lines at the end

test/clang-tidy/readability-numerical-costants-to-max-int.cpp
9

Please add testcases for macros (literal in macro, variable declaration in macro, other possibilities you might find) and for templates.

template <typename Foo>
void f() {
    Foo f = -1;
}

template <int NonType>
void f2() {
    decltype(NonType) new_var = -1;
}

and variations. Please try to cover as many possible constructs as you can.

Another interesting case are enums, example:

enum FooEnum : unsigned {
   bar = 0,
   foobar = 1,
   maximum = -1
}

You don't need to handle this case yet, but please add a testcase to demonstrate the behaviour of the check for it. Adding a TODO: would be perfect to signal future extendability.

Eugene.Zelenko added inline comments.Oct 5 2018, 10:11 AM
clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
62

By the word, see PR32774 for such check suggestion.

IdrissRio updated this revision to Diff 168662.Oct 8 2018, 7:36 AM
IdrissRio marked 22 inline comments as done.
IdrissRio edited the summary of this revision. (Show Details)

Update with the suggestion proposed by @Eugene.Zelenko and @JonasToth

lebedev.ri added inline comments.Oct 8 2018, 8:55 AM
clang-tidy/readability/NumericalCostantsToMaxIntCheck.h
26

I feel like the name is overly vague.
This *only* handles the cases of -1 and ~0.
It does not handle cases like 255 -> std::numeric_limits<uint_8>::max().
(It might be nice to do that, but it is more complex i suspect.)

Eugene.Zelenko added inline comments.Oct 8 2018, 10:01 AM
docs/ReleaseNotes.rst
118

Wrong kind of quotes were used. Should be . std::numeric_limits<type>::max() Should be enclosed in `.

docs/clang-tidy/checks/readability-numerical-costants-to-max-int.rst
8

Please re-synchronize.

JonasToth added inline comments.Oct 9 2018, 2:42 AM
clang-tidy/readability/NumericalCostantsToMaxIntCheck.cpp
64

please assert Lit as well and add an error message in the assert, like assert(Decl && Lit && "Expect both matchers to match");

docs/clang-tidy/checks/readability-numerical-costants-to-max-int.rst
37

Please remove the empty line at the end

test/clang-tidy/readability-numerical-costants-to-max-int.cpp
73

Please add tests that use typedefs (and using = ...) to mask the underlying type. If they dont work, use hasCanonicalType in the matcher, as the canonical type looks through the typedefs.

Common typedefs are uint32_t and the like to control the bitwidth of the integer.

I like the thrust of this check, but we already have the readability-magic-numbers check and I think that this functionality would fit naturally there. That check finds numerical constants and recommends turning them into named constants, but for special values it seems reasonable to recommend using numeric_limits instead. What do others think of that, from an organizational perspective?

I like the thrust of this check, but we already have the readability-magic-numbers check and I think that this functionality would fit naturally there. That check finds numerical constants and recommends turning them into named constants, but for special values it seems reasonable to recommend using numeric_limits instead. What do others think of that, from an organizational perspective?

+1, totally forgot that one. I feel that the bugprone is more strict though, so adding an readability-mode for it that only warns for the numeric_limits constants seems desirable.