Title | PageOfTract macro doesn't compile in Clang 3.0 |
Status | closed |
Priority | optional |
Assigned user | Gareth Rees |
Organization | Ravenbrook |
Description | If 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 [-Werror,-pedantic] 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)) ^~~~ |
Analysis | The 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)) to 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 found | manual_test |
Evidence | None as yet. |
Observed in | 1.111.0 |
Created by | Gareth Rees |
Created on | 2013-09-11 09:41:44 |
Last modified by | Gareth Rees |
Last modified on | 2013-09-11 10:48:22 |
History | 2013-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. |