I'm not sure if this is a flaw in the compiler or if I'm violating
the standard. Compile the following with version 6.2.3, "cc21k -c -21065L foo.c": #define MAC(a,b,c) { a,b,c } #define MULTPARM 1,2 struct X { int a, b, c; } x = MAC(MULTPARM, 3); The result is: "foo4.c", line 3: cc0054-D: error: too few arguments in macro invocation struct X { int a, b, c; } x = MAC(MULTPARM, 3); It looks like there's a sensitivity to the order of macro expansion, and I'm not sure if this is defined by the standard. In my actual application, for different target architectures, the structure has a different number of components (there's an extra for SHARC's), the MAC macro has a different number of parameters, hence the MULTPARM macro has a different number of values. For now I'm wrapping the whole structure initialization in an #ifdef, but I'd like to do something like this if it's legal: #ifdef __ADSP21065L__ #define MULTPARM 1,2 #else #define MULTPARM 1 #endif |
|
Macro expansion order
Started by ●July 9, 2003
Reply by ●July 9, 20032003-07-09
On Wed, 9 Jul 2003, Kenneth Porter wrote: > I'm not sure if this is a flaw in the compiler or if I'm violating the > standard. Compile the following with version 6.2.3, "cc21k -c -21065L foo.c": > > #define MAC(a,b,c) { a,b,c } > #define MULTPARM 1,2 > struct X { int a, b, c; } x = MAC(MULTPARM, 3); > > The result is: > > "foo4.c", line 3: cc0054-D: error: too few arguments in macro invocation > struct X { int a, b, c; } x = MAC(MULTPARM, 3); > > It looks like there's a sensitivity to the order of macro expansion, and I'm > not sure if this is defined by the standard. It's working from the outside in. I'm not familiar with the ccp macro expansion method, but it may be a multiple pass operation which works on one level at a time and just keeps going till there are no more levels to do. Some won't let you go more than 8 levels. You can have 2 macros that are similar and get around this: #define MULTPART 1,2 #define MAC(a, b, c) {a, b, c} #define MACm( c) { MULTPART, c} So places where you have 3 arguments you include all 3, and places where you need expansion you have only 1. > In my actual application, for different target architectures, the structure > has a different number of components (there's an extra for SHARC's), the MAC > macro has a different number of parameters, hence the MULTPARM macro has a > different number of values. then ifdef does seem to be a good solution. > For now I'm wrapping the whole structure initialization in an #ifdef, but I'd > like to do something like this if it's legal: > > #ifdef __ADSP21065L__ > #define MULTPARM 1,2 > #else > #define MULTPARM 1 > #endif But then you should define MAC as MACm above, and it'll work in both cases automaticly. Patience, persistence, truth, Dr. mike |
|
Reply by ●July 10, 20032003-07-10
Here's the reply from ADI, quoting the relevant part of the
standard. ------------ Forwarded Message ------------ Subject: PR18068 A solution would be to use the macro MULTPARM in the MAC macro as shown below. #ifdef __ADSP21065L__ # define MULTPARM 1,2 #else # define MULTPARM 1 #endif #define MAC(c) { MULTPARM, c } #ifdef __ADSP21065L__ struct X { int a, b, c; } x = MAC(3); #else struct X { int a, b; } x = MAC(3); #endif This should produce the expected result cc21k example.c -E .. struct X { int a, b; } x = { 1, 3 }; cc21k example -E -21065L .. struct X { int a, b, c; } x = { 1,2, 3 }; The ANSI ISO IEC 14882 1998 Macro Replacement section 16.3 (page 305) paragraph 10 states: "The sequence of preprocessing tokens bounded by the out-side most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If (before argument substitution) any argument consists of no preprocessing tokens, the behaviour is undefined. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behaviour is undefined." The reply received from Dr Mike Rosing also looks like a good solution. ---------- End Forwarded Message ---------- |
|
Reply by ●July 10, 20032003-07-10
On Thu, 10 Jul 2003, Kenneth Porter wrote: > If there > are sequences of preprocessing tokens within the list of arguments > that would otherwise act as preprocessing directives, the behaviour is > undefined." That's the problem. So you have to make it obvious. > The reply received from Dr Mike Rosing also looks like a good solution. I like your #if sequence too. You might have to define the processor yourself, but at least all the code will be transportable. Thanks for posting ADI's response. Patience, persistence, truth, Dr. mike |
|
Reply by ●July 10, 20032003-07-10
--On Thursday, July 10, 2003 6:38 AM -0700 Mike Rosing <> wrote: > I like your #if sequence too. You might have to define the processor > yourself, but at least all the code will be transportable. Initially I coded something like: X x = MAC(xxx, #if defined(__ADSP21065L__) yyy,zzz, #else aaa, #endif bbb,ccc); The ADI compiler is fine with this, but the ancient Borland compiler I use for the 80186 version of my code choked. Hence I had to tinker around to come up with something that made both environments happy. I've got it ported to Blackfin as well, but it's more like the 80186 so that wasn't so much of a stretch. The biggest issue porting 80186 code to SHARC was the 32-bit char, and the assumption that casting to short or char caused masking to 16 or 8 bits. I grepped my code for such casts and switched those to a macro call (MASK_TO_8_BITS(x)) to make the intent clear. If anyone here is contemplating Blackfin as a target, be aware that VDSP lacks 64 bit doubles for that beast. I had a spot where I needed a 48-bit temporary and we had to code our own extended precision in assembly for it. |