aaron.ballman added a comment.

In https://reviews.llvm.org/D49114#1179652, @0x8000-0000 wrote:

> Top 40 magic numbers in https://github.com/qt/qtbase
>
>   4859 2
>   2901 3
>   1855 4
>    985 5
>    968 8
>    605 6
>    600 7
>    439 16
>    432 10
>    363 
>    356 32
>    241 1.0f
>    217 12
>    209 255
>    207 100
>    205 9
>    205 20
>    204 50
>    177 0.5
>    174 15
>    162 0x2
>    144 24
>    140 0x80
>    135 11
>    127 256
>    113 14
>    110 0xff
>    101 1.0
>     99 64
>     99 200
>     96 13
>     86 30
>     84 1000
>     68 18
>     66 150
>     62 127
>     62 0xFF
>     58 19
>     58 0.05f
>     57 128
>   
>
> Top 40 floating point magic numbers in https://github.com/qt/qtbase
>
>   241 1.0f
>   177 0.5
>   101 1.0
>    58 0.05f
>    44 2.0
>    42 0.5f
>    31 10.0
>    28 30.0
>    24 20.0
>    22 60.0
>    20 100.0
>    19 0.8
>    19 0.25
>    17 0.2
>    16 1000.0
>    14 1.224744871
>    14 100.
>    13 25.0
>    13 0.1
>    12 90.0
>    12 40.0
>    12 0.707106781
>    12 0.30
>    12 0.20
>    11 80.0
>    11 6.0
>    11 50.0
>    11 2.0f
>    11 0.75
>    11 0.66f
>    11 0.1f
>    10 6.28
>    10 5.0
>    10 4.0
>    10 1.414213562
>     9 360.0
>     9 25.4
>     9 2.54
>     8 70.0
>     8 55.0
>   
>
> Top 40 magic numbers in https://github.com/facebook/rocksdb
>
>   2131 2
>    896 3
>    859 4
>    858 10
>    685 100
>    678 1024
>    600 8
>    445 5
>    323 1000
>    244 20
>    231 301
>    227 200
>    223 6
>    209 16
>    189 7
>    154 10000
>    131 1000000
>    119 100000
>    111 30
>    105 256
>    104 32
>    103 5U
>    103 50
>     94 128
>     91 64
>     89 60
>     88 3U
>     85 2U
>     84 500
>     72 4U
>     67 9
>     65 300
>     63 13
>     59 0xff
>     57 6U
>     52 4096
>     52 24
>     52 12
>     51 600
>     50 10U
>   
>
> Top 40 floating point numbers in rocksdb:
>
>   37 100.0
>   30 1.0
>   27 0.5
>   24 0.001
>   12 1048576.0
>   12 0.25
>   11 1.1
>    8 50.0
>    8 1.5
>    8 10000.0
>    5 .3
>    5 .1
>    5 0.8
>    4 99.99
>    4 99.9
>    4 20000.0
>    4 1.048576
>    4 100.0f
>    4 0.9
>    4 0.75
>    4 0.69
>    4 0.02
>    4 0.00001
>    3 1000000.0
>    3 0.4
>    3 0.1
>    2 0.7
>    2 0.6
>    2 0.45
>    1 8.0
>    1 5.6
>    1 40.00002
>    1 40.00001
>    1 3.25
>    1 2.0
>    1 2.
>    1 116.00002
>    1 116.00001
>    1 110.5e-4
>    1 1024.0
>   


Awesome, thank you for this! Based on this, I think the integer list should 
also include 2, 3, and 4 as defaults -- those show up a lot more than I'd have 
expected. As for floating-point values, 1.0 certainly jumps out at me, but none 
of the rest seem particularly common. What do you think?



================
Comment at: clang-tidy/readability/MagicNumbersCheck.cpp:76-86
+  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());
+
----------------
0x8000-0000 wrote:
> 0x8000-0000 wrote:
> > 0x8000-0000 wrote:
> > > aaron.ballman wrote:
> > > > aaron.ballman wrote:
> > > > > 0x8000-0000 wrote:
> > > > > > 0x8000-0000 wrote:
> > > > > > > 0x8000-0000 wrote:
> > > > > > > > 0x8000-0000 wrote:
> > > > > > > > > 0x8000-0000 wrote:
> > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > 0x8000-0000 wrote:
> > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > 0x8000-0000 wrote:
> > > > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > > > This is where I would construct an `APFloat` 
> > > > > > > > > > > > > > > object from the string given. As for the 
> > > > > > > > > > > > > > > semantics to be used, I would recommend getting 
> > > > > > > > > > > > > > > it from `TargetInfo::getDoubleFormat()` on the 
> > > > > > > > > > > > > > > belief that we aren't going to care about 
> > > > > > > > > > > > > > > precision (explained in the documentation).
> > > > > > > > > > > > > > Here is the problem I tried to explain last night 
> > > > > > > > > > > > > > but perhaps I wasn't clear enough.
> > > > > > > > > > > > > > 
> > > > > > > > > > > > > > When we parse the input list from strings, we have 
> > > > > > > > > > > > > > to commit to one floating point value "semantic" - 
> > > > > > > > > > > > > > in our case single or double precision.
> > > > > > > > > > > > > > 
> > > > > > > > > > > > > > When we encounter the value in the source code and 
> > > > > > > > > > > > > > it is captured by a matcher, it comes as either one 
> > > > > > > > > > > > > > of those values.
> > > > > > > > > > > > > > 
> > > > > > > > > > > > > > Floats with different semantics can't be directly 
> > > > > > > > > > > > > > compared - so we have to maintain two distinct 
> > > > > > > > > > > > > > arrays.
> > > > > > > > > > > > > > 
> > > > > > > > > > > > > > If we do that, rather than store APFloats and 
> > > > > > > > > > > > > > sort/compare them with awkward lambdas, we might as 
> > > > > > > > > > > > > > well just use the native float/double and be done 
> > > > > > > > > > > > > > with it more cleanly.
> > > > > > > > > > > > > >When we encounter the value in the source code and 
> > > > > > > > > > > > > >it is captured by a matcher, it comes as either one 
> > > > > > > > > > > > > >of those values.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > It may also come in as long double or __float128, for 
> > > > > > > > > > > > > instance, because there are type suffixes for that.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > > Floats with different semantics can't be directly 
> > > > > > > > > > > > > > compared - so we have to maintain two distinct 
> > > > > > > > > > > > > > arrays.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > Yes, floats with different semantics cannot be 
> > > > > > > > > > > > > directly compared. That's why I said below that we 
> > > > > > > > > > > > > should coerce the literal values.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > > If we do that, rather than store APFloats and 
> > > > > > > > > > > > > > sort/compare them with awkward lambdas, we might as 
> > > > > > > > > > > > > > well just use the native float/double and be done 
> > > > > > > > > > > > > > with it more cleanly.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > There are too many different floating-point semantics 
> > > > > > > > > > > > > for this to be viable, hence why coercion is a 
> > > > > > > > > > > > > reasonable behavior.
> > > > > > > > > > > > Let me see if I understood it - your proposal is: store 
> > > > > > > > > > > > only doubles, and when a floating-point literal is 
> > > > > > > > > > > > encountered in code, do not use the FloatingLiteral 
> > > > > > > > > > > > instance, but parse it again into a double and compare 
> > > > > > > > > > > > exactly. If the comparison matches - ignore it.
> > > > > > > > > > > > 
> > > > > > > > > > > > In that case what is the value of storing APFloats with 
> > > > > > > > > > > > double semantics in the IgnoredValues array, instead of 
> > > > > > > > > > > > doubles?
> > > > > > > > > > > > Let me see if I understood it - your proposal is: store 
> > > > > > > > > > > > only doubles, and when a floating-point literal is 
> > > > > > > > > > > > encountered in code, do not use the FloatingLiteral 
> > > > > > > > > > > > instance, but parse it again into a double and compare 
> > > > > > > > > > > > exactly. If the comparison matches - ignore it.
> > > > > > > > > > > 
> > > > > > > > > > > My proposal is to use `APFloat` as the storage and 
> > > > > > > > > > > comparison medium. Read in strings from the configuration 
> > > > > > > > > > > and convert them to an `APFloat` that has double 
> > > > > > > > > > > semantics. Read in literals and call 
> > > > > > > > > > > `FloatLiteral::getValue()` to get the `APFloat` from it, 
> > > > > > > > > > > convert it to one that has double semantics as needed, 
> > > > > > > > > > > then perform the comparison between those two `APFloat` 
> > > > > > > > > > > objects.
> > > > > > > > > > > 
> > > > > > > > > > > > In that case what is the value of storing APFloats with 
> > > > > > > > > > > > double semantics in the IgnoredValues array, instead of 
> > > > > > > > > > > > doubles?
> > > > > > > > > > > 
> > > > > > > > > > > Mostly that it allows us to modify or extend the check 
> > > > > > > > > > > for more complicated semantics in the future. Also, it's 
> > > > > > > > > > > good practice to use something with consistent semantic 
> > > > > > > > > > > behavior across hosts and targets (comparisons between 
> > > > > > > > > > > numbers that cannot be precisely represented will at 
> > > > > > > > > > > least be consistently compared across hosts when 
> > > > > > > > > > > compiling for the same target).
> > > > > > > > > > > 
> > > > > > > > > > ok - coming right up!
> > > > > > > > > > My proposal is to use APFloat as the storage and comparison 
> > > > > > > > > > medium. Read in strings from the configuration and convert 
> > > > > > > > > > them to an APFloat that has double semantics.
> > > > > > > > > 
> > > > > > > > > This is easy.
> > > > > > > > > 
> > > > > > > > > > Read in literals and call FloatLiteral::getValue() to get 
> > > > > > > > > > the APFloat from it, 
> > > > > > > > > 
> > > > > > > > > this is easy as well,
> > > > > > > > > 
> > > > > > > > > > convert it to one that has double semantics as needed, then 
> > > > > > > > > > perform the comparison between those two APFloat objects.
> > > > > > > > > 
> > > > > > > > > The conversion methods in `APFloat` only produce 
> > > > > > > > > plain-old-data-types: 
> > > > > > > > > ```
> > > > > > > > >   double convertToDouble() const;                             
> > > > > > > > >                                                               
> > > > > > > > >                                                               
> > > > > > > > >      
> > > > > > > > >   float convertToFloat() const;     
> > > > > > > > > ```
> > > > > > > > > 
> > > > > > > > > There is no
> > > > > > > > > ```
> > > > > > > > >    APFloat convertToOtherSemantics(const fltSemantics &) 
> > > > > > > > > const;
> > > > > > > > > ```
> > > > > > > > > method.
> > > > > > > > > 
> > > > > > > > > What I can do is
> > > > > > > > > 1. convert the APFloat to float or double, depending on what 
> > > > > > > > > the semantics is; cast to double then load into an APFloat 
> > > > > > > > > with double semantics and then search into the set
> > > > > > > > > 2. parse the textual representation of the FloatingLiteral 
> > > > > > > > > directly into an APFloat with double semantics.
> > > > > > > > `TargetInfo::getDoubleFormat()` is not accessible directly from 
> > > > > > > > `ClangTidyContext` or from `MatchFinder`
> > > > > > > 2. doesn't quite work;  `APFloat.convertFromString` chokes on 
> > > > > > > `3.14f` ;(
> > > > > > Option 1 doesn't work, either:
> > > > > > ```
> > > > > >      llvm::APFloat DoubleFloatValue(llvm::APFloat::IEEEdouble());   
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >      if (&FloatValue.getSemantics() == 
> > > > > > &llvm::APFloat::IEEEdouble())                                       
> > > > > >                                                                     
> > > > > >                
> > > > > >        DoubleFloatValue = FloatValue;                               
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >      else if (&FloatValue.getSemantics() == 
> > > > > > &llvm::APFloat::IEEEsingle()) {                                     
> > > > > >                                                                     
> > > > > >           
> > > > > >        const float Value = FloatValue.convertToFloat();             
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >        DoubleFloatValue = 
> > > > > > llvm::APFloat(static_cast<double>(Value));                          
> > > > > >                                                                     
> > > > > >                             
> > > > > >      }                                                              
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >                                                                     
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >       return std::binary_search(IgnoredFloatingPointValues.begin(), 
> > > > > >                                                                     
> > > > > >                                                        
> > > > > >                                IgnoredFloatingPointValues.end(),    
> > > > > >                                                                     
> > > > > >                                                       
> > > > > >                                DoubleFloatValue, compareAPFloats);
> > > > > > ```
> > > > > > has problems with floating point values that are not integers.
> > > > > > 
> > > > > > Unless somebody knows how to convert APFloats with any semantics 
> > > > > > into APFloats with double semantics, I'm stuck ;(
> > > > > > There is no
> > > > > > `APFloat convertToOtherSemantics(const fltSemantics &) const;`
> > > > > > method.
> > > > > ```
> > > > >   opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
> > > > >                    bool *losesInfo);
> > > > > ```
> > > > > This function does exactly that?
> > > > > `TargetInfo::getDoubleFormat()` is not accessible directly from 
> > > > > `ClangTidyContext` or from `MatchFinder`
> > > > 
> > > > `MatchFinder` has an `ASTContext` object on which you can call 
> > > > `ASTContext::getTargetInfo()`, I believe.
> > > Yes, it does! Thank you!
> > Looking at the code, it declares a structure for MatchResult which indeed 
> > contains an ASTContext. But MatchFinder does not hold a reference to it, it 
> > is passed into it from a MatchVisitor.
> > 
> > What we would need is to parse the configuration before we start matching 
> > (either in the constructor or in `::registerMatchers` - and there is no 
> > visitor available then.
> So functionally it works, but it suffers from the same problem as doing the 
> conversion by hand using the 
> ```static_cast<double>(FloatValue.convertToFloat())```; the resulting value 
> for 3.14f does not match the existing value for 3.14 present in the 
> IgnoredFloatingPointValues array.
Hmm, that's certainly annoying.

@alexfh -- I think we should have access to the ASTContext object from within 
the ClangTidyContext passed in when registering the checks. We already have 
`ClangTidyContext::setASTContext()` that gets called before `createChecks()` in 
`ClangTidyASTConsumerFactory::CreateASTConsumer()`; can you think of a reason 
we should not persist that value in the `ClangTidyContext`? If there is a good 
reason to not persist it, perhaps it would be a reasonable argument to be 
passed to each check's constructor (by threading it through `createChecks()`?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D49114



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to