MPS issue job003619

TitlePageOfTract macro doesn't compile in Clang 3.0
Assigned userGareth Rees
DescriptionIf I try to compile the MPS on Ubuntu with Clang/LLVM 3.0 (the standard Clang that you get via the Ubuntu Software Centre), I get the following detailed error message:

    In file included from mps.c:42:
    ./reserv.c:277:3: error: using extended field designator is an extension
      TRACT_FOR(tract, addr, arena, base, limit) {
    ./tract.h:273:3: note: expanded from:
      TRACT_TRACT_FOR(tract, addr, arena, TractOfBaseAddr(arena, base), limit)
    ./tract.h:262:28: note: expanded from:
            (tract = PageTract(PageOfTract(tract) + 1)) : \
    ./tract.h:114:28: note: expanded from:
    #define PageOfTract(tract) PARENT(PageStruct, the.tractStruct, (tract))
    ./misc.h:162:35: note: expanded from:
      ((type *)(void *)((char *)(p) - offsetof(type, field)))
    /usr/include/clang/3.0/include/stddef.h:52:24: note: expanded from:
    #define offsetof(t, d) __builtin_offsetof(t, d)
    ./tract.h:110:29: note: expanded from:
    #define PageTract(page) (&((page)->the.tractStruct))
AnalysisThe problem is the definition of the PageOfTract() macro. PageOfTract(tract) expands to

    PARENT(PageStruct, the.tractStruct, (tract))

which expands to

    ((PageStruct *)(void *)((char *)(tract) - offsetof(PageStruct, the.tractStruct)))

and the offsetof() call here is not standard C, at least as far as Clang/LLVM -pedantic is concerned: only a bare field name is allowed here, not an "extended field designator" like "the.tractStruct".

In Clang/LLVM 4.0 there's an option -Wno-extended-offsetof that suppresses this error, but that's doesn't have any effect in Clang/LLVM 3.0.

I can think of three possible approaches:

1. Declare Clang/LLVM 3.0 unsupported and insist on customers upgrading to 4.0. (But then it will be difficult to develop the MPS on Ubuntu with Clang, because you won't be able to use Ubuntu Software Centre to install it.)

2. Redefine the PageOfTract() macro as follows:

    PARENT(PageStruct, the, (tract))

Or maybe this (to make the intention clearer):

    PARENT(PageStruct, the/*.tractStruct*/, (tract))

This works because "the" is a union and so "the" and "the.tractStruct" have the same address. But is that required by the standard or does it just happen to be true in most implementations?

3. Give the nameless union a name (for example, PageStructUnion), and then redefine PageOfTract() like this:

    PARENT(PageStruct, the, PARENT(union PageStructUnion, traceStruct, (tract)))

There are similar problems with the linkOfMessage and linkOfRing macros, which can be fixed similarly.

In segsmess.c the Pool2AMST macro can be changed from

    PARENT(AMSTStruct, amsStruct.poolStruct, (pool))


    PARENT(AMSTStruct, amsStruct, PARENT(AMSStruct, poolStruct, (pool)))

and another instance of offsetof:

    offsetof(AMSTStruct, amsStruct.poolStruct)

can be changed to

    offsetof(AMSTStruct, amsStruct) + offsetof(AMSStruct, poolStruct);
How foundmanual_test
EvidenceNone as yet.
Observed in1.111.0
Created byGareth Rees
Created on2013-09-11 09:41:44
Last modified byGareth Rees
Last modified on2013-09-11 10:48:22
History2013-09-11 GDR Created.


Change Effect Date User Description
183413 closed 2013-09-11 10:21:12 Gareth Rees Make the MPS compilable under Clang/LLVM 3.0 with the -ansi -pedantic options:
Avoid if with empty body by adding NOOP.
Avoid extended offsetof in expansion of PageOfTract, linkOfMessage, linkOfRing, and Pool2AMST macros.