Message ID | 1374770523-6570-2-git-send-email-peter.maydell@linaro.org |
---|---|
State | New |
Headers | show |
On Thu, Jul 25, 2013 at 05:42:02PM +0100, Peter Maydell wrote: > Provide infrastructure for marking private QOM struct fields, > so that a compiler warning is generated when a user of the QOM > object attempts to access them directly. > > This is implemented using GCC's 'deprecated' attribute; preprocessor > macros arrange that when compiling the class implementation, > no attribute is applied to the fields; when compiling a user > of the class the fields are marked deprecated. > > This allows us to have a single simple C struct defining the > object, and for users of the QOM object to be able to embed > instances of it into other structs, but still to have a guard > against users accidentally touching parts of the structure > they should not be accessing. Very cool =) Maybe there is a way to decrease the plain text impl footprint by using header files? #define im_the_implementation #include xxx #undef im_the_implementation or something better... Cheers, Edgar > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > include/qemu/compiler.h | 10 ++++++++++ > include/qom/object.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 57 insertions(+) > > diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h > index 155b358..d7cc153 100644 > --- a/include/qemu/compiler.h > +++ b/include/qemu/compiler.h > @@ -52,4 +52,14 @@ > #define GCC_FMT_ATTR(n, m) > #endif > > +/* An attribute usable to mark structure fields as private to the > + * implementation; since this is only a diagnostic to catch programming > + * errors, it's OK if it expands to nothing on non-gcc compilers. > + */ > +#if defined __GNUC__ > +# define QEMU_PRIVATE_ATTR __attribute__((deprecated("this field is private"))) > +#else > +# define QEMU_PRIVATE_ATTR > +#endif > + > #endif /* COMPILER_H */ > diff --git a/include/qom/object.h b/include/qom/object.h > index 23fc048..7f02f80 100644 > --- a/include/qom/object.h > +++ b/include/qom/object.h > @@ -284,6 +284,53 @@ typedef struct InterfaceInfo InterfaceInfo; > * > * The first example of such a QOM method was #CPUClass.reset, > * another example is #DeviceClass.realize. > + * > + * = Marking fields as private to the class implementation = > + * > + * The expected code structure for QOM objects is that they should > + * have a header file in include/ which defines the class and object > + * structures and the typecasting macros. This header can then be > + * included by both the source file which implements the QOM object > + * and also by other source files which merely wish to use the object. > + * Users of your object need the class and object structures so that > + * they can embed instances of the object in their own structures; > + * however they do not need to be able to access individual fields in > + * these structures. To enforce this you should use the QEMU_PRIVATE_ATTR > + * macro in a pattern like this: > + * > + * <example> > + * <title>Marking fields as private</title> > + * <programlisting> > + * #ifdef IMPLEMENTING_MY_DEVICE > + * # define __private > + * #else > + * # define __private QEMU_PRIVATE_ATTR > + * #endif > + * > + * typedef struct MyDevice > + * { > + * __private DeviceState parent; > + * > + * __private int reg0, reg1, reg2; > + * } MyDevice; > + * > + * typedef struct MyDeviceClass > + * { > + * __private DeviceClass parent; > + * > + * void (*frobnicate) (MyDevice *obj); > + * } MyDeviceClass; > + * > + * #undef __private > + * </programlisting> > + * </example> > + * > + * The source files which provide the implementation of your > + * class (or of subclasses to it) should then have > + * "#define IMPLEMENTING_MY_DEVICE" before they include any > + * headers. Since users of the class will not define this > + * macro, they will get a compilation warning if they access > + * any of the private fields by mistake. > */ > > > -- > 1.7.9.5 > >
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 155b358..d7cc153 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -52,4 +52,14 @@ #define GCC_FMT_ATTR(n, m) #endif +/* An attribute usable to mark structure fields as private to the + * implementation; since this is only a diagnostic to catch programming + * errors, it's OK if it expands to nothing on non-gcc compilers. + */ +#if defined __GNUC__ +# define QEMU_PRIVATE_ATTR __attribute__((deprecated("this field is private"))) +#else +# define QEMU_PRIVATE_ATTR +#endif + #endif /* COMPILER_H */ diff --git a/include/qom/object.h b/include/qom/object.h index 23fc048..7f02f80 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -284,6 +284,53 @@ typedef struct InterfaceInfo InterfaceInfo; * * The first example of such a QOM method was #CPUClass.reset, * another example is #DeviceClass.realize. + * + * = Marking fields as private to the class implementation = + * + * The expected code structure for QOM objects is that they should + * have a header file in include/ which defines the class and object + * structures and the typecasting macros. This header can then be + * included by both the source file which implements the QOM object + * and also by other source files which merely wish to use the object. + * Users of your object need the class and object structures so that + * they can embed instances of the object in their own structures; + * however they do not need to be able to access individual fields in + * these structures. To enforce this you should use the QEMU_PRIVATE_ATTR + * macro in a pattern like this: + * + * <example> + * <title>Marking fields as private</title> + * <programlisting> + * #ifdef IMPLEMENTING_MY_DEVICE + * # define __private + * #else + * # define __private QEMU_PRIVATE_ATTR + * #endif + * + * typedef struct MyDevice + * { + * __private DeviceState parent; + * + * __private int reg0, reg1, reg2; + * } MyDevice; + * + * typedef struct MyDeviceClass + * { + * __private DeviceClass parent; + * + * void (*frobnicate) (MyDevice *obj); + * } MyDeviceClass; + * + * #undef __private + * </programlisting> + * </example> + * + * The source files which provide the implementation of your + * class (or of subclasses to it) should then have + * "#define IMPLEMENTING_MY_DEVICE" before they include any + * headers. Since users of the class will not define this + * macro, they will get a compilation warning if they access + * any of the private fields by mistake. */
Provide infrastructure for marking private QOM struct fields, so that a compiler warning is generated when a user of the QOM object attempts to access them directly. This is implemented using GCC's 'deprecated' attribute; preprocessor macros arrange that when compiling the class implementation, no attribute is applied to the fields; when compiling a user of the class the fields are marked deprecated. This allows us to have a single simple C struct defining the object, and for users of the QOM object to be able to embed instances of it into other structs, but still to have a guard against users accidentally touching parts of the structure they should not be accessing. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/qemu/compiler.h | 10 ++++++++++ include/qom/object.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)