https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80521

            Bug ID: 80521
           Summary: Wrong line reported in error for missing template
                    argument in friend class declaration.
           Product: gcc
           Version: 7.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: carlo at gcc dot gnu.org
  Target Milestone: ---

Although similar to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=8570 from
2002, I guess I'll report it again now, for version 7.0.1.

When compiling the following snippet:

-------------------------------
template<typename T>
struct RingBuffer {
 private:
  unsigned long m_capacity;    // Number of objects of type T in the buffer.
  union {
    T* m_start;         // Start of buffer.
    char* m_storage;
  };
  T* m_head;       // Next write position.
  T* m_tail;       // Next read position.

 protected:
  friend class ProducerAccess;

  friend class ConsumerAccess;

 public:
  RingBuffer() : m_storage(nullptr), m_head(nullptr), m_tail(nullptr) { }
  RingBuffer(int objects) : m_storage(nullptr), m_head(nullptr),
m_tail(nullptr) { allocate_(objects); }
  ~RingBuffer() { delete [] m_storage; }

 private:
  void allocate_(int objects)
  {
    m_capacity = objects * sizeof(T);
    // Allocate storage aligned to at least 32 bytes.
    //m_storage = new decltype(*m_storage) [m_capacity];
    m_tail = m_head = m_start;
  }

 public:
  void reallocate(int objects)
  {
    if (m_storage) delete [] m_storage;
    allocate_(objects);
  }
};

template<typename T>
struct ProducerAccess {
 private:
  RingBuffer<T>& m_buffer;
 public:
  ProducerAccess(RingBuffer<T>& buffer) : m_buffer(buffer) { }
  ~ProducerAccess() { }
};

template<typename T>
struct ConsumerAccess {
 private:
  RingBuffer<T>& m_buffer;
 public:
  ConsumerAccess(RingBuffer<T>& buffer) : m_buffer(buffer) { }
  ~ConsumerAccess() { }
};

int main()
{
  // Construct an empty buffer.
  RingBuffer<long> fifo_buffer;
  // Allocate 100 std::function<void()> objects in it.
  fifo_buffer.reallocate(100);

  ProducerAccess<long> pa(fifo_buffer);
  ConsumerAccess<long> ca(fifo_buffer);
}
------------------------------------------

You get an almost random location for where the problem is:

>g++-svn-7 -c bug.cxx
bug.cxx: In instantiation of ‘struct RingBuffer<long int>’:
bug.cxx:60:20:   required from here
bug.cxx:10:6: error: template argument required for ‘class ProducerAccess’
   T* m_tail;       // Next read position.
      ^~~~~~
bug.cxx:10:6: error: template argument required for ‘class ConsumerAccess’


The real problem is here:

  friend class ProducerAccess;

  friend class ConsumerAccess;


Sorry for not minimizing the snippet further,
Carlo

Reply via email to