[m-dev.] for review: MR_TypeInfo cleanup, part 1

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Mar 24 19:36:05 AEDT 2000


On 24-Mar-2000, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
> On 24-Mar-2000, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > Hmm... here you just return the number directly, but 
> > the MR_TYPECTOR_DESC_IS_HIGHER_ORDER() macro calls
> > MR_TYPECTOR_DESC_UNSIGNED(), which assumes that its argument
> > will be a pointer to a struct containing the number as its first field.
> > 
> > So `MR_TYPECTOR_DESC_IS_HIGHER_ORDER(MR_TYPECTOR_DESC_MAKE_PRED(0))'
> > would lead to a seg fault.  That sure looks to me like a bug.
> 
> No, this is not a bug. MR_TYPECTOR_DESC_UNSIGNED() *does not* assume that
> its argument will be a pointer to a struct containing the number as its
> first field; it assumes that its argument is a value of type MR_TypeCtorDesc
> (i.e. a pointer) which it then simply casts to Unsigned. The
> MR_TYPECTOR_DESC_UNSIGNED macro does not do any dereferencing;
> it returns the *address* of the dummy field, not its contents.

Ah, I see now. You're absolutely correct.

This scheme is a quite nifty trick for getting type safety when using macros.

> I will document this scheme better before I commit.

That would be great, thanks.

It's a pity that for portability reasons we can't use more
straight-forward techniques to get type safety, such as using
inline functions, or perhaps using GNU C's `({ ... })' extension.

One small drawback with this technique is that it depends for its correctness
on the named field (e.g. `arity' or `type_ctor_desc_dummy_field') being the
*first* field in the type.  Another minor drawback is that it only guarantees
that the type is a type with the given field name, not that it is the correct
type.

An alternative technique which avoids these drawbacks would be to use
the following macro:

	/*
	** MR_CHECK_EXPR_TYPE(expr, type):
	** This macro checks that the given expression has a type
	** which is compatible with (assignable to) the specified type,
	** forcing a compile error if it does not.
	** It does not evaluate the expression.
	** Note that the specified type must be a complete type,
	** i.e. it must not be a pointer to a struct which has
	** not been defined.
	**
	** The implementation of this macro looks like it dereferences
	** a null pointer, but because that code is inside sizeof(), it will
	** not get executed; the compiler will instead just check that it is
	** type-correct.
	*/
	#define MR_CHECK_EXPR_TYPE(expr, type) \
		((void) sizeof(*(type *)NULL = (expr)))

With this macro, you can define macros like MR_TYPECTOR_DESC_UNSIGNED()
in a fairly straight-forward manner:

	#define MR_TYPECTOR_DESC_UNSIGNED(typector_desc) \
		( MR_CHECK_EXPR_TYPE(typector_desc, MR_TypeCtorDesc), \
		  (Unsigned) (typector_desc) )

But this is a relatively minor improvement; if you want to commit the
code as is, I'm happy to do the above change myself, as a separate change.

Cheers,
	Fergus.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list