mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 20:42:56 +01:00
Clang is generally fine with Genode::List and compiles code using it
without emitting any warnings. There is however one exception. Clang
fails hard when building base-hw/src/core/kernel/object.cc.
This is due to a call to Genode::List::remove made from
Object_identity::invalidate function. The error message clang
produces is:
list.h:96:33: error: 'Genode::List<Kernel::Object_identity_reference>::Element::_next'
is not a member of class 'const Kernel::Object_identity'
_first = le->List::Element::_next;
~~~~~~~~~~~~~~~^
When we look at the declaration of the Kernel::Object class on which
the remove method is called. as expected it does inherit Genode::List:
using Object_identity_list
= Genode::List<Kernel::Object_identity>;
class Kernel::Object : private Object_identity_list
{
...
}
Given the error message we see that List::Element should be resolved to
Genode::List<Kernel::Object_identity>::Element, and not
Genode::List<Kernel::Object_identity_reference>::Element. But how does
clang manage to figure out we're talking about Object_identity_refecence
list here? Well, I admit I don't know the exact steps it takes to arrive
at this conclusion, but it is not entirely wrong. If we take a look at
what Kernel::Object_identity is we'll see:
class Kernel::Object_identity
: public Object_identity_list::Element,
public Kernel::Object_identity_reference_list
{
...
}
Where as one can guess Object_identity_reference_list is defined as:
using Object_identity_reference_list
= Genode::List<Object_identity_reference>;
Long story short Kernel::Object has Genode::List of both Kernel::Object_identity
and Kernel::Object_identity_reference in its inheritance chain and clang
is not really sure to which of those the code refers to in
Genode::List::remove method by using List::Element::.
The fix for this is relatively simple, explicitly state the full type of
the base class the code intends to refer to. Replacing List::Element,
with List<LT>::Element makes the code buildable with both clang and GCC.
Fixes #3990
141 lines
2.8 KiB
C++
141 lines
2.8 KiB
C++
/*
|
|
* \brief Single connected list
|
|
* \author Norman Feske
|
|
* \date 2006-08-02
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__UTIL__LIST_H_
|
|
#define _INCLUDE__UTIL__LIST_H_
|
|
|
|
namespace Genode {
|
|
|
|
template <typename> class List;
|
|
template <typename> class List_element;
|
|
}
|
|
|
|
|
|
/**
|
|
* Single-connected list
|
|
*
|
|
* \param LT list element type
|
|
*/
|
|
template <typename LT>
|
|
class Genode::List
|
|
{
|
|
private:
|
|
|
|
LT *_first;
|
|
|
|
public:
|
|
|
|
class Element
|
|
{
|
|
protected:
|
|
|
|
friend class List;
|
|
|
|
LT mutable *_next;
|
|
|
|
public:
|
|
|
|
Element(): _next(0) { }
|
|
|
|
/**
|
|
* Return next element in list
|
|
*/
|
|
LT *next() const { return _next; }
|
|
};
|
|
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
List() : _first(0) { }
|
|
|
|
/**
|
|
* Return first list element
|
|
*/
|
|
LT *first() { return _first; }
|
|
LT const *first() const { return _first; }
|
|
|
|
/**
|
|
* Insert element after specified element into list
|
|
*
|
|
* \param le list element to insert
|
|
* \param at target position (preceding list element)
|
|
*/
|
|
void insert(LT const *le, LT const *at = 0)
|
|
{
|
|
/* insert at beginning of the list */
|
|
if (at == 0) {
|
|
le->List<LT>::Element::_next = _first;
|
|
_first = const_cast<LT *>(le);
|
|
} else {
|
|
le->List<LT>::Element::_next = at->List<LT>::Element::_next;
|
|
at->List<LT>::Element::_next = const_cast<LT *>(le);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove element from list
|
|
*/
|
|
void remove(LT const *le)
|
|
{
|
|
if (!_first) return;
|
|
|
|
/* if specified element is the first of the list */
|
|
if (le == _first) {
|
|
_first = le->List<LT>::Element::_next;
|
|
|
|
} else {
|
|
|
|
/* search specified element in the list */
|
|
Element *e = _first;
|
|
while (e->_next && (e->_next != le))
|
|
e = e->_next;
|
|
|
|
/* element is not member of the list */
|
|
if (!e->_next) return;
|
|
|
|
/* e->_next is the element to remove, skip it in list */
|
|
e->List<LT>::Element::_next = e->List<LT>::Element::_next->List<LT>::Element::_next;
|
|
}
|
|
|
|
le->List<LT>::Element::_next = 0;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Helper for using member variables as list elements
|
|
*
|
|
* \param T type of compound object to be organized in a list
|
|
*
|
|
* This helper allow the creation of lists that use member variables to
|
|
* connect their elements. This way, the organized type does not need to
|
|
* publicly inherit 'List<LT>::Element'. Furthermore objects can easily
|
|
* be organized in multiple lists by embedding multiple 'List_element'
|
|
* member variables.
|
|
*/
|
|
template <typename T>
|
|
class Genode::List_element : public List<List_element<T> >::Element
|
|
{
|
|
T *_object;
|
|
|
|
public:
|
|
|
|
List_element(T *object) : _object(object) { }
|
|
|
|
T *object() const { return _object; }
|
|
};
|
|
|
|
#endif /* _INCLUDE__UTIL__LIST_H_ */
|