
On Mon, Apr 16, 2018 at 06:27:45PM +0200, Michal Privoznik wrote:
On 04/16/2018 02:30 PM, Erik Skultety wrote:
On Fri, Apr 13, 2018 at 04:47:15PM +0200, Michal Privoznik wrote:
Our virObject code relies heavily on the fact that the first member of the class struct is type of virObject (or some derivation of if). Let's check for that.
If a class is missing 'parent' memeber, it's a bug in the definition of the struct/class, therefore there should be a static assertion rather than a runtime check.
If a class is missing parent then you'd hit compile time error because offsetof() is trying to get offset of a non-existent member.
Sigh, poor choice of words, you're right, I meant the scenario where you put it somewhere else...
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/util/virobject.c | 31 +++++++++++++++++++++---------- src/util/virobject.h | 5 ++++- 2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/src/util/virobject.c b/src/util/virobject.c index c5a98d21cc..e184f5349e 100644 --- a/src/util/virobject.c +++ b/src/util/virobject.c @@ -77,6 +77,7 @@ virObjectOnceInit(void) { if (!(virObjectClass = virClassNew(NULL, "virObject", + 0, sizeof(virObject), NULL)))
Also, I don't like this extra parameter, which really shouldn't be needed; you created a macro which hides this parameter, but that doesn't mean that design-wise it makes sense to have it there, think of it as a constructor, you don't pass a constructor an offset of the class' member, because it shouldn't have need for it, but you do, solely for the purpose of checking whether we have a particular member in place. So, to start a discussion about this (I also think Dan posted something related to this recently, but I don't seem to be able to find it in the archives - do I even archive?!!!), I came up with my first compile-time hack ever, it seems to work like expected, but I'd like to hear your opinions both the macro itself and the approach we're going to take, so here's my replacement patch:
diff --git a/src/util/virobject.h b/src/util/virobject.h index 92dd51239..2a973d401 100644 --- a/src/util/virobject.h +++ b/src/util/virobject.h @@ -75,8 +75,12 @@ virClassPtr virClassForObjectRWLockable(void); # define VIR_PARENT_REQUIRED ATTRIBUTE_NONNULL(1) # endif
+# define VIR_CLASS_HAS_PARENT(name) \ + !sizeof(char[0-offsetof(name, parent)])
I don't quite understand why this is so obfuscated. Anyway, since VIR_CLASS_NEW() is going to be a stand alone macro (like VIR_ENUM_DECL for instance) we can do plain:
Well, this was to accommodate the macro to the original form of having it behave function-like. But as I said, if we adjust 7/9, we have other options as well and frankly, I like the usage of verify below, which I didn't know gnulib had.
#define VIR_CLASS_NEW(prt, name) \ verify(offsetof(name, parent) == 0); \ if (!(name##Class = virClassNew(prt, #name, sizeof(name), name##Dispose))) \ return -1;
(written from the top of my head, not tested, not compiled, don't take it too much literally)
I did and it works. With the above change: Reviewed-by: Erik Skultety <eskultet@redhat.com>