Whole Tomato Software Forums
Whole Tomato Software Forums
Main Site | Profile | Register | Active Topics | Members | Search | FAQ
User name:
Password:
Save Password
Forgot your password?

 All Forums
 Visual Assist
 Technical Support
 C++20 Lambda return class reference not renamed
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Kram
Junior Member

Germany
16 Posts

Posted - Oct 05 2021 :  07:40:33 AM  Show Profile  Reply with Quote
I renamed the class PacketInStream.

All other instances of the class were renamed, but not the PacketInStream& Lambda return type.

inline Manip2P<uint8_t, bool> PacketTerminator(
        _In_ const uint8_t value = PacketStream::_PACKET_TERMINATOR,
        _In_ const bool isfinal = true)
    {
        return(Manip2P<uint8_t, bool>(
            [](_In_ PacketInStream& os, 
               _In_ const uint8_t value, 
               _In_ const bool isfinal) -> PacketInStream&
            {
                os.DecodeConst(value, isfinal);
                return os;
            },
            value, isfinal));
    }


It's not a serious problem, but I thought I would let you know.

B00ting, please wait...

Edited by - Kram on Oct 05 2021 07:43:49 AM

feline
Whole Tomato Software

United Kingdom
18750 Posts

Posted - Oct 05 2021 :  12:47:57 PM  Show Profile  Reply with Quote
Can you please try the following code block, which I have put together based on your example:

enum PacketStreamFeline { _PACKET_TERMINATOR };
class PacketInStreamFeline
{
public:
    void DecodeConst(const uint8_t value, const bool isfinal) {}
};

void felineVATestFuncHoldingLambda()
{
    std::map<uint8_t, bool> PacketTerminator(
        _In_ const uint8_t value = PacketStreamFeline::_PACKET_TERMINATOR,
        _In_ const bool isfinal = true)
    {
        return(std::map<uint8_t, bool>(
            [](_In_ PacketInStreamFeline& os,
                _In_ const uint8_t value,
                _In_ const bool isfinal) -> PacketInStreamFeline&
            {
                os.DecodeConst(value, isfinal);
                return os;
            },
            value, isfinal));
    }
}

I have renamed symbols to make sure that you should have no problems in your solution. When I rename the class "PacketInStreamFeline" all references are being renamed for me.

However I have obviously done something wrong, since the code does not compile, but I am not quite sure what. Still, it should be a reasonable test case to start with. It's possible the problem you are seeing is being triggered by something further up the file, so it will be interesting to see what results you get.

zen is the art of being at one with the two'ness
Go to Top of Page

Kram
Junior Member

Germany
16 Posts

Posted - Oct 05 2021 :  2:52:18 PM  Show Profile  Reply with Quote
There has been some refactoring since the first code snippet, so I've put together a stand alone compiling example (VS2019 16.11.3) that demonstrates the issues (there are two that I have seen now):

1. Renaming class PacketTestStream does not rename the Labmda return.
2. Renaming template parameter TP1 from any of the templates wants to rename the TP1 parameter of all templates in the whole solution.

#pragma once

#include <cstdio>

namespace Packet
{
    class PacketStream
    {
    public:
        PacketStream(_In_ const size_t size) noexcept :
            _width(0),
            _remaining(size),
            _streamOkay(true),
            _size(0)
        {
        }

        // Get the current status of the packet

        operator bool() const
        {
            return _streamOkay;
        }

        // Return the current size of the data, or 0 if there are any errors

        inline size_t Size() const
        {
            return operator bool() ? _size : 0;
        }

        // Set the maximum width of the next string

        inline void SetW(_In_ const size_t width)
        {
            _width = width;
        }

        // ASCII string terminator character

        static constexpr uint8_t _ASCII_STRING_TERMINATOR = 0x00;

        // Packet terminator character

        static constexpr uint8_t _PACKET_TERMINATOR = 0x10;

        // Manipulator template for one parameter

        template <class TStream, typename TP1>
        class Manip1
        {
        public:

            // Function prototype for the manipulator worker.

            using Function = TStream & (*) (TStream&, TP1);

            // Construct a new manipulator object.

            Manip1(Function function, TP1 value) :
                _function(function),
                _value1(value)
            {
            }

            // Execute the manipulator.

            TStream& Go(TStream& os) const
            {
                _function(os, _value1);
            }

        private:

            // The value to apply to the manipulator call.

            TP1 _value1;

            // The manipulator function to call.

            Function _function;
        };

        // Manipulator template for two parameters

        template <class TStream, typename TP1, typename TP2>
        class Manip2
        {
        public:

            // Function prototype for the manipulator worker.

            using Function = TStream & (*) (_Inout_ TStream&, _In_ const TP1, _In_ const TP2);

            // Construct a new manipulator object.

            Manip2(_In_ const Function function, _In_ const TP1 value1, _In_ const TP2 value2) :
                _function(function),
                _value1(value1),
                _value2(value2)
            {
            }

            // Execute the manipulator.

            TStream& Go(_Inout_ TStream& os) const
            {
                _function(os, _value1, _value2);

                return os;
            }

        private:

            // The value to apply to the manipulator call.

            TP1 _value1;

            // The value to apply to the manipulator call.

            TP2 _value2;

            // The manipulator function to call.

            Function _function;
        };

    protected:

        // Width of the the next string operation

        size_t _width;

        // Remaining unused / unprocessed bytes in the packet data

        size_t _remaining;

        // The number of read or written bytes in the stream

        size_t _size;

        // Current status of the packet processing

        bool _streamOkay;
    };


    // Stream operator template 1 parameter manipulators

    template <class TOStream, typename TP1>
    inline TOStream& operator<<(_Inout_ TOStream& os, _In_ const PacketStream::Manip1<TOStream, TP1>& manip)
    {
        return manip.Go(os);
    }

    // Stream operator template 1 parameter manipulators

    template <class TIStream, typename TP1>
    inline TIStream& operator>>(_Inout_ TIStream& is, _In_ const PacketStream::Manip1<TIStream, TP1>& manip)
    {
        return manip.Go(is);
    }

    // Stream operator template 2 parameter manipulators

    template <typename TIStream, typename TP1, typename TP2>
    inline TIStream& operator>>(_Inout_ TIStream& is, _In_ const PacketStream::Manip2<TIStream, TP1, TP2>& manip)
    {
        return manip.Go(is);
    }

#include <stdexcept>

    class PacketTestStream : public PacketStream
    {
    public:
        // Default constructor

        PacketTestStream(_In_ const uint8_t* const data, _In_ size_t size) noexcept :
            PacketStream(size)
        {
            std::ignore = data;
        }

        // Decode a terminator byte

        inline void DecodeConst(_In_ const uint8_t value, _In_ const bool isfinal)
        {
            std::ignore = value;
            std::ignore = isfinal;
            throw std::logic_error("TODO");
        }

        template <typename T>
        PacketTestStream& operator>>(_Out_ T& value)
        {
            std::ignore = value;
            throw std::logic_error("TODO");
        }

    private:

        // Decode a uint8

        inline void Decode(_Out_ uint8_t& value)
        {
            std::ignore = value;
            throw std::logic_error("TODO");
        }

    public:

        // Instantiate the set width manipulator.

        static inline Manip1<PacketTestStream, size_t> SetW(_In_ const size_t width)
        {
            return(Manip1<PacketTestStream, size_t>(
                [](_Inout_ PacketTestStream& os, _In_ const size_t width) -> PacketTestStream& {
                    os.SetW(width);
                    return os;
                },
                width));
        }

        // Instantiate the packet terminator manipulator.

        static inline Manip2<PacketTestStream, uint8_t, bool> PacketTerminator(
            _In_ const uint8_t value = PacketStream::_PACKET_TERMINATOR,
            _In_ const bool isfinal = true)
        {
            return(Manip2<PacketTestStream, uint8_t, bool>(
                [](_In_ PacketTestStream& is, _In_ const uint8_t value, _In_ const bool isfinal) -> PacketTestStream& {
                    is.DecodeConst(value, isfinal);
                    return is;
                },
                value, isfinal));
        }

    };

}

B00ting, please wait...

Edited by - Kram on Oct 06 2021 10:32:39 AM
Go to Top of Page

feline
Whole Tomato Software

United Kingdom
18750 Posts

Posted - Oct 06 2021 :  10:13:30 AM  Show Profile  Reply with Quote
I have this compiling here, many thanks for the sample code, I will take this apart and work out why this code has the problem and my simple test case doesn't.

Starting with "PacketTestStream", if you do a Find References instead of a Rename, and right click in the Find References Results window you should have the option to show or hide:

Display unknown/guess hits (G)

the lambda return is showing up as a guess result. Assuming you have these results turned On in Find References Results then you should see the guess results in the Rename dialog, but they won't be checked by default. Now to work out why VA is not sure what is going on here.

zen is the art of being at one with the two'ness
Go to Top of Page

feline
Whole Tomato Software

United Kingdom
18750 Posts

Posted - Oct 06 2021 :  11:32:37 AM  Show Profile  Reply with Quote
Thinking about this, I have just put in a feature request to let you turn on showing the unknown/guess hits in the Rename dialog directly, for odd rename problems, this one included.

case=146287

zen is the art of being at one with the two'ness
Go to Top of Page

feline
Whole Tomato Software

United Kingdom
18750 Posts

Posted - Oct 06 2021 :  1:26:08 PM  Show Profile  Reply with Quote
I have a very simple test case for the lambda return type only being picked up as a guess by VA. The trigger in the simple test case is the namespace. Remove the namespace and VA understands the return type correctly. Not really a good work around for you, and quite unexpected, but at least its a clear pattern.

case=146288

For now I would recommend keeping "Display unknown/guess hits" turned On in Find References Results, so you can be aware when VA isn't sure about something.

zen is the art of being at one with the two'ness
Go to Top of Page

Kram
Junior Member

Germany
16 Posts

Posted - Oct 06 2021 :  1:36:21 PM  Show Profile  Reply with Quote
I'm happy that you are making progress.

B00ting, please wait...
Go to Top of Page

feline
Whole Tomato Software

United Kingdom
18750 Posts

Posted - Oct 07 2021 :  06:51:59 AM  Show Profile  Reply with Quote
I am seeing the same problem for the template parameter TP1, it turns out this is a known bug, VA does not yet limit the scope of Find References or Rename to the single template, instead scanning all of them:

case=16397

I have added this example to the bug report, which will help with testing when we get this fixed.

zen is the art of being at one with the two'ness
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
© 2023 Whole Tomato Software, LLC Go To Top Of Page
Snitz Forums 2000