Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Compiler/Delphi/Header Generation    [ Add a report in this area ]  
Report #:  72890   Status: Closed
Nested type aliases in generic classes result in an invalid header
Project:  C++Builder Build #:  12.0.3210.17555
Version:    12.1 Submitted By:   Moritz Beutel
Report Type:  Basic functionality failure Date Reported:  4/10/2009 6:43:43 AM
Severity:    Commonly encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All versions Internal Tracking #:   268965
Resolution: Fixed (Resolution Comments) Resolved in Build: : 14.0.3446.21875
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
To work around the fact that C++ does not yet support template typedefs, DCC currently emits a helper macro for type aliases with type parameters. I.e.,
// -----
type
  Bar <T> = procedure;
// -----
becomes
// -----
#define _decl_Bar__1(T, _DECLNAME) void __fastcall (*_DECLNAME)(void)
// typedef template<typename T> void __fastcall (*Bar__1)(void);
// -----
in the header file.
(IMHO, a wrapper structure like
// -----
template <typename T> struct Bar__1
{ typedef void __fastcall (*type) (void); }
// -----
should have been used instead, but that's not the point here.)

Apparently, this workaround has unneccessarily been applied to nested type definitions of generic classes. The following code
// -----
type
  Foo <T> = class
    type
      Bar = procedure;
      Baz <T2> = procedure;
    var
      FBar: Bar;
      FBaz: Baz <Integer>;
  end;
// -----
emits this declarations to the header:
// -----
template<typename T> class PASCALIMPLEMENTATION Foo__1 : public System::TObject
{

...


#define _decl_Foo__1_Bar(, _DECLNAME) void __fastcall (*Bar)(void)

// typedef void __fastcall (*Bar)(void);




#define _decl_Foo__1_Baz__1(T2, _DECLNAME) void __fastcall (*Baz__1)(void)

// typedef template<typename T2> void __fastcall (*Baz__1)(void);


_decl_Foo__1_Bar(FBar);

// Bar FBar;

_decl_Foo__1_Baz__1(int, FBaz);

// Baz__1<int>  FBaz;
// -----
Obviously, the first #define is syntactically wrong - and it would not be required at all since Foo<T>.Bar is not a generic type itself.

The correct header output would be:
// -----
template<typename T> class PASCALIMPLEMENTATION Foo__1 : public System::TObject
{

...


typedef void __fastcall (*Bar)(void);




#define _decl_Foo__1_Baz__1(T2, _DECLNAME) void __fastcall (*Baz__1)(void)

// typedef template<typename T2> void __fastcall (*Baz__1)(void);


Bar FBar;

_decl_Foo__1_Baz__1(int, FBaz);

// Baz__1<int>  FBaz;
// -----
Steps to Reproduce:
- Compile the following code (dcc32 -JPHN qc72890.pas):
// -----
unit qc72890;

interface

type
  Bar <T> = procedure;

type
  Foo <T> = class
    type
      Bar = procedure;
      Baz <T2> = procedure;
    var
      FBar: Bar;
      FBaz: Baz <Integer>;
  end;

implementation

end.
// -----
- Now compile the generated header file with BCC (bcc32 -P -c qc72890.hpp).

Exp.: compiles
Act.: Error E2221 qc72890.hpp 37: Error in macro argument syntax
Workarounds
None
Attachment
qc72890.zip
Comments

None

Server Response from: ETNACODE01