base: Make Genode::List clang friendly.

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
This commit is contained in:
Piotr Tworek 2021-01-13 00:12:49 +01:00 committed by Norman Feske
parent 9d239957bc
commit 80e8cf99e2

View File

@ -76,11 +76,11 @@ class Genode::List
{
/* insert at beginning of the list */
if (at == 0) {
le->List::Element::_next = _first;
le->List<LT>::Element::_next = _first;
_first = const_cast<LT *>(le);
} else {
le->List::Element::_next = at->List::Element::_next;
at->List::Element::_next = const_cast<LT *>(le);
le->List<LT>::Element::_next = at->List<LT>::Element::_next;
at->List<LT>::Element::_next = const_cast<LT *>(le);
}
}
@ -93,7 +93,7 @@ class Genode::List
/* if specified element is the first of the list */
if (le == _first) {
_first = le->List::Element::_next;
_first = le->List<LT>::Element::_next;
} else {
@ -106,10 +106,10 @@ class Genode::List
if (!e->_next) return;
/* e->_next is the element to remove, skip it in list */
e->List::Element::_next = e->List::Element::_next->List::Element::_next;
e->List<LT>::Element::_next = e->List<LT>::Element::_next->List<LT>::Element::_next;
}
le->List::Element::_next = 0;
le->List<LT>::Element::_next = 0;
}
};