Author Topic: SE not determining type of auto loop variable in C++  (Read 1005 times)

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
SE not determining type of auto loop variable in C++
« on: January 16, 2022, 09:44:40 pm »
Look for loopautoissue.tar.gz on support.

See the README file.

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
Re: SE not determining type of auto loop variable in C++
« Reply #1 on: January 20, 2022, 06:17:51 pm »
Were you able to reproduce this? I'm seeing similar issues in multiple places in my code base.

Dennis

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 3606
  • Hero Points: 480
Re: SE not determining type of auto loop variable in C++
« Reply #2 on: January 20, 2022, 09:42:24 pm »
I do have this one on my list.  My list is frequently more of a stack than a queue, so it got bumped behind some other issues.

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
Re: SE not determining type of auto loop variable in C++
« Reply #3 on: January 20, 2022, 09:53:11 pm »
I think SE doesn't support range based for loop when the .begin() function returns the template type.

Refer to my actual example but I think it is doing this:

Code: [Select]
class Element
{
};

template <class T>
class List<T>
{
  T begin();
};

void func()
{
  List<Element> someList;
  ...
  for (auto &element : someList)
  {
    // SE can't determine that 'element' has type Element
    // which is the return type of List<>.begin()
    // Put cursor on 'element' below in Preview window to see the issue
   element
  }
}

Dennis

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 3606
  • Hero Points: 480
Re: SE not determining type of auto loop variable in C++
« Reply #4 on: January 21, 2022, 01:42:20 pm »
I can reproduce the problem with that example, however, there are a few problems with that example. 
  • begin() is private
  • List and Element are going to conflict with other classes
  • List is defined as a template specialization of the template parameter, this wouldn't compile.
  • Normally, begin() returns an instance of an iterator class, or at least a type which has operator *() and operator++() defined.

It works with your example after these corrections.  I'll have to look at your full example.

Code: [Select]
class rdElement
{
public:
  int a,b,c;
};

template <class T>
class rdList
{
public:
  T *begin();
  T *end();
};

void func()
{
  rdList<rdElement> someList;
  //...
  for (auto &element : someList)
  {
    // SE can't determine that 'element' has type Element
    // which is the return type of List<>.begin()
    // Put cursor on 'element' below in Preview window to see the issue
   element.
  }
}
« Last Edit: January 21, 2022, 01:44:59 pm by Dennis »

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
Re: SE not determining type of auto loop variable in C++
« Reply #5 on: January 21, 2022, 02:24:14 pm »
Please look at the full example. The full example was done with copy/paste from compilable code.

What I placed in my last post was my high level mental model. The mental model likely left out some important detail from the full example. I didn't try compiling the mental model example from my post or testing it in SE, I only have limited time to dedicate to test cases, and I thought that putting something in the post may be easier for you than finding the full example, while at the same time it minimized my time to develop a small test case that I can post in a public forum.

I'm sure the full example has some important detail I left out. In fact I see the full example does have begin() return an iterator with those operators overloaded. I guess I'm not an expert in range based for loops for creating a mental model, but my full example has real compilable code that meets the rules you specified.

Please take the small amount of time necessary to retrieve it from support and check it out. I think I'm seeing this happening over and over again in my code base and it is hard to code browse now. I don't want to keep making new, similar test cases before you look at the first one.
« Last Edit: January 21, 2022, 02:48:42 pm by rowbearto »

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
Re: SE not determining type of auto loop variable in C++
« Reply #6 on: January 21, 2022, 08:40:07 pm »
Here's the full example in a format that I can post on a public forum. My upload to support has other stuff like my user.cfg.xml.

I verified that the clangd language server protocol is able to determine the type of the auto while SE cannot with this example. The clangd server does something close to compilation and is not showing any errors.

This has the .begin() method return an iterator with the required operators.

Search for the "REPRODUCE" in the code sample.

Code: [Select]
#include <memory>
namespace SomeOtherNamespace {
struct Struct33
{
};
template <class R>
class SomeReaderInterface {
 public:
  virtual void WaitFunc();
};
template <class R>
class SomeReader : public SomeReaderInterface<R> {
};
//
}

namespace some_namespace {
class SomeListType
{
};

}

namespace NameSpace7 {
class Class55;
template <typename Response>
class StreamReader {
  friend Class55;

  std::unique_ptr<SomeOtherNamespace::Struct33> context;
  std::unique_ptr<SomeOtherNamespace::SomeReader<Response>> reader;

 public:
  Response result;

  StreamReader() : context(new SomeOtherNamespace::Struct33) {}

  bool Read() {
    return false;
  }

  /**
   * Iterator for response stream.
   */
  class Iterator {
    friend StreamReader;

    StreamReader<Response> *reader;

    explicit Iterator(StreamReader<Response> *reader) : reader(reader) {}

   public:
    Iterator() : reader(nullptr) {}

    Response &operator*() {
      return reader->result;
    }

    Response *operator->() {
      return &reader->result;
    }

    Iterator &operator++() {
      if (!reader->Read()) reader = nullptr;
      return *this;
    }

    bool operator!=(const Iterator &other) {
      return reader != other.reader;
    }
  };

  /**
   * Returns an iterator for the response stream.
   */
  Iterator begin() {
    if (Read())
      return Iterator(this);
    else
      return Iterator();
  }

  /**
   * Returns an invalid iterator to mark the end of the response stream.
   */
  Iterator end() {
    return Iterator();
  }
};

}

namespace namespace99 {
class ClassName3
{
};

}


namespace application_common
{

  class NamespaceIntf
  {
    public:
      static NameSpace7::StreamReader<some_namespace::SomeListType>  GetFunction(namespace99::ClassName3& model);

  };

void myfunc()
{
  auto model_p = std::make_unique<namespace99::ClassName3>();
    auto reader = NamespaceIntf::GetFunction(*model_p);
    for (auto const &result : reader) {
      // REPRODUCE: Do a "Preview" window on 'result' below, it says that the type
      // of result is:
      //    const&:reader
      // however the type of 'result' should be:
      //    const some_namespace::SomeListType &
      // The clangd language server is able to correctly determine the type
      // but SlickEdit is not able to get the correct type.
      // clangd language server: https://clangd.llvm.org/
      result
    }
}

} // namespace application_common

Dennis

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 3606
  • Hero Points: 480
Re: SE not determining type of auto loop variable in C++
« Reply #7 on: January 21, 2022, 09:02:06 pm »
Thanks, I will also look at the example you uploaded, but the reduced example saves me a lot of time.  I appreciate that you spent the time to put it together.

rowbearto

  • Senior Community Member
  • Posts: 2162
  • Hero Points: 132
Re: SE not determining type of auto loop variable in C++
« Reply #8 on: January 21, 2022, 09:37:54 pm »
It is very time consuming for me to create reduced examples. For example for this one I have to learn the internals of range-based for loops which I didn't know before. I tried simplifying by posting my "mental model" and failed. What I put in the last post is identical to what I uploaded originally to support, I just changed some names.

Dennis

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 3606
  • Hero Points: 480
Re: SE not determining type of auto loop variable in C++
« Reply #9 on: March 08, 2022, 05:03:52 pm »
The problem traced down to a C/C++ parsing issue.  This will be fixed for 26.0.2.