From: jonpryor AT vt DOT edu (Jonathan Pryor) Subject: B20: egcs: Questions (Structures, inline assembly, comments, unnamed unions) 2 Dec 1998 10:28:12 -0800 Message-ID: <000201be1d73$64e6bb80$246a52c6.cygnus.gnu-win32@balthasar.campus.vt.edu> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit To: "gnu-win32 Mailing List (E-mail)" I'm trying to get the latest Microsoft Platform SDK headers to compile under egcs-2.91.57, and I came across volumes of code that seem to generate errors... :-) Most of the errors seem to fall into two categories (so far...), but there are a couple of other areas that need help... First are structures that contain arrays of unspecified size, e.g.: #include typedef struct _TEST { short Pad; unsigned char Format[]; } TEST; int main (int, char **) { return 0; } I've looked in Stroustrup (3rd edition) to see if the above syntax is legal, but found nothing. Thus, some questions: * _Is_ it legal? * If not, why not? (It seems reasonable to me; sure, a pointer would make more sense, but we allow function declarations such as void some_funct ( char some_text[] ); so why not allow it in structures? BTW, the RPC headers and seem to make extensive use of this type of construct.) * Is there any type of workaround that *doesn't* require changing the code? (I couldn't think of any, but that doesn't mean such techniques don't exist...) ---- Second is the issue of code containing inline assembler. In Microsoft's great genious, they decided to insert inline assembler into their headers (yech!), such as this (from ): __inline ULONGLONG NTAPI Int64ShllMod32 ( ULONGLONG Value, DWORD ShiftCount ) { __asm { mov ecx, ShiftCount mov eax, dword ptr [Value] mov edx, dword ptr [Value+4] shld edx, eax, cl shl eax, cl } } (This is supposed to shift a 64-bit value by a 32-bit value). While I don't know assembler, the above makes sense -- presumably, the code in the __asm { ... } braces will be inserted directly into the machine-level source before the program is compiled into machine code. Not exactly portable, but it looks better than needing to code an entire routine in assembler and manually linking it in later (though that's probably more portable across compilers). Plus, you get the compiler to take care of the stack cleanup for you. Sounds great to me. I looked up the g++ `asm' documentation in the man pages, and was rather confused... For example, to use the 68881's `fsinx' assembler instruction, the following would be needed (from gcc.info-11): asm ("fsinx %1,%0" : "=f" (result) : "f" (angle)); This, frankly, looks uglier to me than the inline assembler seen above, but opinions aren't under consideration here... What is under consideration (for me, anyway) is how to get this __asm block through g++ *without* modifying the file. Thus, some questions: * why does g++ uses the syntax it currently uses (though this is mostly out of curiosity). * is there any way (without modifying the files) to get around this inline assembler? (Actually, there is a way -- set the _M_ALPHA pre-processor macro, which causes to think it's running on an Alpha, thus it simply uses macro's for the functions, as Alpha has native support of 64-bit types... But this still leaves the first question about the structures.) * how 'bout adding inline assembly braces for g++... :-) (Well...maybe not....) ---- The final issue preventing successful compilation of the Microsoft Windows headers regards comments. In the days of yore, they created variables of type VARIANT_BOOL named `bool', which of course collides with the C++ type `bool'. This, of course, wouldn't compile under a C++ compiler, so some changes were necessary... The "fix" was to "duplicate" all locations that used VARIANT_BOOL with a "dummy" _VARIANT_BOOL; the "new" _VARIANT_BOOL declared variables with the old name (`bool'), while the VARIANT_BOOL declared a variable with a non-colliding name. Thus, older code wouldn't need to change (unless it was re-compiled with an updated compiler), e.g. typedef union _VARIANT { // ... VARIANT_BOOL boolVal; _VARIANT_BOOL bool; // satisfies legacy code // ... } VARIANT; So, how to keep the _VARIANT_BOOL line from giving errors? By doing this: #define _VARIANT_BOOL /##/ Which would have the effect of "commenting out" all lines that made use of `bool', allowing the VARIANT definition to work reliably on C++. Therein lies the problem; when g++ comes across the above definition of VARIANT (including the `//' to "remove" the line), it gives an error: C:\\usr\\include\\ms\\oaidl.h:421: parse error before `/' After dumping the pre-processed source to a text file, the error is on this line: // bool; Which suggests to me that the g++ compiler doesn't like to deal with comments, instead expecting the pre-processor to remove them. Could this be considered a bug? :-) (Probably not; such usage -- expecting the pre-processor to remove comments -- makes sense, as I'd think it would simplify the logic needed to compile the source -- parsing of comments wouldn't be needed. Unfortunately it breaks seemingly valid code like this. I'd submit that if we tried to use an "older" pre-processor that didn't handle single line comments, it would "break" g++...not exactly a good thing.) ---- Aside from the above three issues, there are some things that just cause warnings to appear during compilation, which I'm curious about... Just out of curiosity, why does g++ give a warning on unnamed unions? It's only a warning (and thus can be ignored), but it's still annoying seeing dozens of such warnings... Another warning deals with stack cleanup declarations in function prototypes; from IViewObject : public IUnknown { //... virtual /* [local] */ HRESULT STDMETHODCALLTYPE Draw ( // lots of parameters skipped... BOOL ( STDMETHODCALLTYPE *pfnContinue )( DWORD dwContinue ), // ... ) = 0; // ... }; STDMETHODCALLTYPE is an alias for __attribute__((stdcall)), and g++ doesn't seem to like specifying a pointer to a `stdcall' function in a function prototype (the definition of `pfnContinue' gets a warning: "`__stdcall__' attribute ignored.". Very odd...but it's still only a warning. ---- For the record, if I do modify the headers to get around these problems (which amounts to using the preprocessor to #define __int64 as "long long", #define-ing _M_ALPHA, and #define-ing __unaligned (which only occurs in the Alpha path), and modifying the files , , , and ), I can compile the program fine (discounting dozens of warnings, but it compiles...), and it runs successfully. For those wondering why I don't use the Windows headers included with the CygWin32 utils, I have a couple reasons... * The included headers don't include all the API's I need (such as the COM API functions. This is rather interesting because the DLL link libraries (libole32.a) include them, but the function prototypes aren't in any of the headers. e.g. CoInitialize(), CoCreateInstanceEx(), etc...) * As Windows changes, it would be nice to have updated headers. The "closer" to the "source", the faster the updates (I can use the original headers instead of needing to wait for someone to re-write the headers into a form I can use); In the same beat, if the standard headers can be used, then people are free to write other things, instead of needing to try to keep up-to-date headers. Finally, I have been to the site with "fuller" Windows headers that compile under g++ (at http://www.acc.umu.se/~anorland/gnu-win32/) and am using them, in fact (thanks to Anders Norlander); however, these are completely new and will still need to be maintained; using the Microsoft headers would mean that we wouldn't need to keep maintaining our own duplicate set. Thank you for your time - Jon - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".