0x8000-0000 marked an inline comment as done.
0x8000-0000 added inline comments.


================
Comment at: 
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-const-correctness-values.cpp:608
+}
+
+template <typename L, typename R>
----------------
JonasToth wrote:
> JonasToth wrote:
> > 0x8000-0000 wrote:
> > > JonasToth wrote:
> > > > 0x8000-0000 wrote:
> > > > > 0x8000-0000 wrote:
> > > > > > JonasToth wrote:
> > > > > > > JonasToth wrote:
> > > > > > > > 0x8000-0000 wrote:
> > > > > > > > > Please insert the this test code here:
> > > > > > > > > 
> > > > > > > > > ```
> > > > > > > > > struct IntWrapper {
> > > > > > > > > 
> > > > > > > > >    unsigned low;
> > > > > > > > >    unsigned high;
> > > > > > > > > 
> > > > > > > > >    IntWrapper& operator=(unsigned value) {
> > > > > > > > >       low = value & 0xffff;
> > > > > > > > >       high = (value >> 16) & 0xffff;
> > > > > > > > >    }
> > > > > > > > > 
> > > > > > > > >    template<typename Istream>
> > > > > > > > >    friend Istream& operator>>(Istream& is, IntWrapper& rhs) {
> > > > > > > > >       unsigned someValue = 0;       // false positive now
> > > > > > > > >       if (is >> someValue) {
> > > > > > > > >          rhs = someValue;
> > > > > > > > >       }
> > > > > > > > >       return is;
> > > > > > > > >    }
> > > > > > > > > };
> > > > > > > > > 
> > > > > > > > > unsigned TestHiddenFriend(IntMaker& im) {
> > > > > > > > >    IntWrapper iw;
> > > > > > > > > 
> > > > > > > > >    im >> iw;
> > > > > > > > > 
> > > > > > > > >    return iw.low;
> > > > > > > > > }
> > > > > > > > > ```
> > > > > > > > clang gives me no error when I add the const there. sure it 
> > > > > > > > does reproduce properly?
> > > > > > > Here for reference: https://godbolt.org/z/DXKMYh
> > > > > > Probably I wasn't clear - I suggested adding my test code at line 
> > > > > > 608, because it needs the "IntMaker" definition at line 594.
> > > > > > 
> > > > > > The false positive from this const check is reported on the 
> > > > > > "unsigned someValue = 0;" line inside the template extraction 
> > > > > > operator.
> > > > > Oh, I got it - don't think "shift" think "overloaded extraction 
> > > > > operator".
> > > > > 
> > > > > In my code above, you don't know what ">>" does, and it clearly takes 
> > > > > a mutable reference as the right side.
> > > > > 
> > > > > ```
> > > > > const int foo;
> > > > > std::cin >> foo;
> > > > > ```
> > > > > 
> > > > > should not compile, either :)
> > > > no. something else is going on.
> > > > https://godbolt.org/z/xm8eVC
> > > > ```
> > > > | |   |-CXXOperatorCallExpr <line:21:5, col:11> '<dependent type>'
> > > > | |   | |-UnresolvedLookupExpr <col:8> '<overloaded function type>' 
> > > > lvalue (ADL) = 'operator>>' 0x55a26b885938 0x55a26b857238
> > > > | |   | |-DeclRefExpr <col:5> 'Istream' lvalue ParmVar 0x55a26b885748 
> > > > 'is' 'Istream &'
> > > > | |   | `-DeclRefExpr <col:11> 'const unsigned int' lvalue Var 
> > > > 0x55a26b885a38 'someValue' 'const unsigned int'
> > > > ```
> > > > This code is only a false positive in the sense, that the "we can not 
> > > > know if something bad happens" is not detected. The operator>> is not 
> > > > resolved. That is because the template is not instantiated and the 
> > > > expressions can therefore not be resolved yet.
> > > > There seems to be no instantiation of this template function.
> > > > 
> > > > Somehow the `im >> iw;` does not instantiate the `friend operator<<`. I 
> > > > reduced it to something i think is minimal and that shows the same 
> > > > behaviour. (https://godbolt.org/z/MMG_4q)
> > > https://godbolt.org/z/7QEdHJ
> > > 
> > > ```
> > > struct IntMaker {
> > >   operator bool() const;
> > > 
> > >   friend IntMaker &operator>>(IntMaker &, unsigned &);
> > >   //friend IntMaker &operator>>(IntMaker &, const unsigned &) = delete;
> > > };
> > > ```
> > > 
> > > If you uncomment the deleted overload then
> > > 
> > > ```
> > > template <typename Istream>
> > > Istream& operator>>(Istream& is, IntWrapper& rhs)  {
> > >     unsigned const someValue = 0;
> > >     if (is >> someValue) {
> > >         rhs = someValue;
> > >     }
> > >     return is;
> > > }
> > > ```
> > > 
> > > Fails to compile.
> > > 
> > > Depending on what else is around, it seems that somehow the compiler 
> > > would try to use the (bool) conversion to obtain an integral then use it 
> > > as an argument to the built-in integral left shift.
> > > 
> > > https://godbolt.org/z/-JFL5o - this does not compile, as expected:
> > > 
> > > ```
> > > #include <iostream>
> > > 
> > > int readInt() {
> > >     const int foo = 0;
> > >     std::cin >> foo;
> > >     return foo;
> > > }
> > > ```
> > > 
> > > so this check should not recommend making foo constant.
> > I see. Implicit conversions are great... :)
> > 
> > I will recheck that. And the `std::cin` example is analyzed correctly. I 
> > added a test for that, too.
> > Thank you for researching the issue!
> https://godbolt.org/z/VerWce
> Minimal example that shows the issue.
As much as I would have liked to contribute a good test to your new checker, 
I'm happier that I have found something strange with my original code from 
which I was trying to distill the minimal case.

For what it's worth, dumping the AST on my original code, shows this
```
|     | |       |-IfStmt 0x7fdafcfb3a60 <line:60:9, line:63:9>
|     | |       | |-BinaryOperator 0x7fdafcfb32b0 <line:60:13, col:19> 
'<dependent type>' '>>'
|     | |       | | |-DeclRefExpr 0x7fdafcfb3270 <col:13> 'Istream' lvalue 
ParmVar 0x7fdafcfb1448 'is' 'Istream &'
|     | |       | | `-DeclRefExpr 0x7fdafcfb3290 <col:19> 'uint32_t':'unsigned 
int' lvalue Var 0x7fdafcfb31b8 'someValue' 'uint32_t':'unsigned int'
```

Instead of the expected:
```
2220 | |   |   |-IfStmt 0x5971b00 <line:624:7, line:626:7>                      
                                                                             
2221 | |   |   | |-CXXOperatorCallExpr 0x596f040 <line:624:11, col:17> 
'<dependent type>'
2222 | |   |   | | |-UnresolvedLookupExpr 0x596efe8 <col:14> '<overloaded 
function type>' lvalue (ADL) = 'operator>>' 0x596b8a8 0x596b668 0x596ab38       
   
2223 | |   |   | | |-DeclRefExpr 0x596efa8 <col:11> 'Istream' lvalue ParmVar 
0x596e968 'is' 'Istream &'                                                      
2224 | |   |   | | `-DeclRefExpr 0x596efc8 <col:17> 'unsigned int' lvalue Var 
0x596eef0 'someValue' 'unsigned int'
```

I need to investigate if I need to shuffle some includes around to get clang to 
treat it as an overloaded method instead of shift. At any rate, the new 
const-checker has proved its worth by pointing me to a bug!

Thank you, Jonas!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54943/new/

https://reviews.llvm.org/D54943



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

Reply via email to