Author Topic: Erroneous code generation with __declspec Macros  (Read 2066 times)

sl@sh

  • EA User
  • **
  • Posts: 85
  • Karma: +0/-0
    • View Profile
Erroneous code generation with __declspec Macros
« on: May 02, 2007, 10:53:01 pm »
As pointed out in this thread:
http://www.sparxsystems.com.au/cgi-bin/yabb/YaBB.pl?board=general;action=display;num=1168551310
EA does not produce the correct code in some cases when using Macros for the __declspec qualifiers (C++).

This problem refers to cases where #define Macros are being used for alternate __declspec declarations within library headers that are meant for both import and export of interfaces.

Consider a Macro defined like this:
Code: [Select]
#ifdef MY_FOO_LIB
 #define MY_FOO_API __declspec(dllexport)
#else
 #define MY_FOO_API __declspec(dllimport)
#endif

Then consider a class defined like that:
Code: [Select]
class cMyFoo : public cSomeExternalClass {
public:
 MY_FOO_API cMyFoo();
 virtual MY_FOO_API ~cMyFoo();
 void* MY_FOO_API bar();
 MY_FOO_API class cMyBar {/* ... */} m_bar;
};


If this gets imported to EA, all the methods get tagged values 'DeclMacro1' with the value 'MY_FOO_API'. With one exception: the constructor doesn't get this tagged value! (1). Also the attribute m_bar doesn not get the tagged value. (3)

When I then regenerate the code, I get this (comments added):
Code: [Select]
class cMyFoo : public cSomeExternalClass {
public:
 cMyFoo(); // (1) error: MY_FOO_API missing
 virtual MY_FOO_API ~cMyFoo(); // correct - but only works because declared as virtual!
 void MY_FOO_API *bar(); // (2) error: the location of MY_FOO_API is wrong (between 'void' and the '*') - because of this it is being ignored!
 class cMyBar {/* ... */} m_bar; // (3) error: MY_FOO_API missing
};


Problems (1) and (3) appear to be caused by the fact 'MY_FOO_API' happens to be the first symbol on the line. Adding those tagged values manually does fix the code generation for the constructor, but not for the attribute (see (2)!)

Problem (2) appear to be caused by EA's ignorance of placement rules for __declspec macros: the type definition has to appear either in front or behind '__declspec'. This is, including the '*' or '&', if present. So, MY_FOO_API void* bar(); would also work.

EA appears to assume that any use of __declspec macros require a type (or at least some kind of symbol) in front of the macro. This is wrong. Both constructors and attribute declarations might require the Macro to be the very first symbol - and possibly destructors too, unless they are virtual. As a matter of fact, the __declspec macro can always be used as the first symbol in line - however, in that case it gets completely ignored by EA import!

There are two things that need to be fixed:

1. Code import should recognize Macros even if they're the first symbol of the declaration.

2. Code export should place those macros either at the start of the declaration, or it should remember it's placement from import and use that information. Since it is possible different compilers treat __declspec slightly different, the latter approach would be preferrable.

The second point is the more important one since it is not possible to automatically generate correct code until this is fixed. The first one can be fixed manually, but I consider it severe since it causes hard to discover problems for those who are not aware of the bug -  I know it took me the better part of a day to analyse it.

P.S.:
1. I just reported this as a bug, referring to this topic.
2. If anyone knows a good solution to problem (2), please let me know. (And no, I don't consider using typedefs a good solution, as a matter of fact I stumbled over this problem exactly because I wanted to reduce the number of typedefs being used within the project ... )
« Last Edit: May 02, 2007, 11:14:09 pm by sl@sh »

«Midnight»

  • EA Guru
  • *****
  • Posts: 5651
  • Karma: +0/-0
  • That nice Mister Grey
    • View Profile
Re: Erroneous code generation with __declspec Macr
« Reply #1 on: May 03, 2007, 02:17:14 am »
Thanks for reporting this - and using the link. I believe this one has gotten away from the community.

On point 2, you are certainly correct. There's been a fair amount of discussion about EA support for typedefs. Simply put, the support is quite 'basic.' It will work for simple declarations, but anything even a bit exotic is likely (certain?) to run into problems. In your situation this could chew up significant time before you were forced to abandon the idea.

Not only that, but you'd be twisting your entire code base around to accomplish something. If you came back to it later you'd be hard pressed to explain what it was for, and why you did it that way.

Sorry, I don't have the solution at all. This is not my development paradigm any more.

Hopefully you'll get some traction, and let us know how the solution comes about.

David
No, you can't have it!