As I wrote I updated may implementation of Delphi classes to gpc-20050331. Now, I have put a patch at:
http://www.math.uni.wroc.pl/~hebisch/gpc/delphi3.diff
With the patch, when one chooses Mac Pascal as a dialect, object model should be compatible with Mac Pascal: -- objects are pointers -- all methods are virtual (that was already implemented in gpc-20050331) -- overriding a method requires `override' keyword -- you can allocate memory for objects with `New' and deallocate it with `Dispose'
In default mode the `class' keyword is recognized and allows you to declare Delphi classes. ATM Delphi constructors works only in simplest case (you can not call a constructor inside a (different) constructor). Destructors do not deallocate memory (but `Dispose' applied to a Delphi class will deallocate memory). Also, Delphi builtin `TObject' is unimplemented.
This is experimatal (and incomplete) implementation. I would like to get some feedback about missing features. Also, if I got semantics of implemented parts correctly. ATM I know only about one missing Mac objects feature (which is almost surely due to my lack of knowledge about Mac Pascal): GPC requires all methods to be defined in the same unit as the object (TCL sources implement methods in different units). And of course test programs are welcome.
Waldek Hebisch wrote:
[snip]
This is experimatal (and incomplete) implementation. I would like to get some feedback about missing features. Also, if I got semantics of implemented parts correctly. ATM I know only about one missing Mac objects feature (which is almost surely due to my lack of knowledge about Mac Pascal): GPC requires all methods to be defined in the same unit as the object (TCL sources implement methods in different units). And of course test programs are welcome.
I'm not really sure the TCL sources downloadable from http://www.pascal-central.com/cwport.html represent legal MacPascal Object Pascal code. I don't use TCL myself, but I had the impression the downloads were just partial pieces used to update the full TCL package that was included with purchased copies of THINK Pascal. Since I haven't tried it, I'm don't know what all gets fixed when you run through the updater process.
That said, I was always under the impression that methods had to be implemented in the same unit containing object type declaration containing the method heading. (For interface only units to external object libraries [i.e., link libraries containing the machine code implementations] , there is no implementation part so there is no method implementation source code for those types of interfaces.)
Although there's never any bet-your-life guarentees that the documentation accurately describes the implementation, the following is a direct quote from the CodeWarrior Pro 4 Pascal Language Reference documentation:
"When declaring a method, the initial heading declaration and the block declaration must both appear in the main program or must both appear in the same compilation unit. The heading declaration appears in the type declaration part, as part of the object type decla- ration. The declaration of the method's block appears in the proce- dure and function declaration part. You must write the object type and a period along with the procedure or function identifier when you declare the block. You may repeat the formal parameter list; if you do, it must be identical to the original."
Gale Paeper gpaeper@empirenet.com
At 3:16 +0200 23/6/05, Waldek Hebisch wrote:
As I wrote I updated may implementation of Delphi classes to gpc-20050331. Now, I have put a patch at:
Sorry for the delay, it took me a while to get gpc compiling, convert over to using gp, install the patch and start converting my object code over to see how it goes.
I don't use the MAC_PASCAL dialect, so for the moment I hacked the diff to comment out the line:
// PNL if (co->pascal_dialect & MAC_PASCAL)
so that objects are always treated as Mac style objects (I imagine in the fullness of time there will be a compiler directive to control this independent of the dialect, but this seemed an easy solution to allow testing the patch.
dispose( self ) complains:
/Source/MyAssocStrings.p: In method `AssocStringsObject.Destroy': /Source/MyAssocStrings.p:254: error: argument 1 to `Dispose' must be a pointer
I turned on {$methods-always-virtual}
There needs to be a control over the "warning: object type has virtual method, but no constructor". Perhaps just methods-always-virtual disables that warning?
Currently it is giving me "error: undeclared identifier `MethodName'" when I try to call a method of the parent object (the parent object is all defined in one unit, and the child all in another unit). I will try to simplify the code causing the problem down to a simple test case.
Thanks, Peter.
Peter N Lewis wrote:
There needs to be a control over the "warning: object type has virtual method, but no constructor". Perhaps just methods-always-virtual disables that warning?
MAC_PASCAL does (and in the future, the object model switch should).
Frank
At 9:24 +0800 27/6/05, Peter N Lewis wrote:
dispose( self ) complains:
/Source/MyAssocStrings.p: In method `AssocStringsObject.Destroy': /Source/MyAssocStrings.p:254: error: argument 1 to `Dispose' must be a pointer
Here is a test program for this case:
{$mac-pascal} program peterN;
type obj = object procedure Destroy; end;
procedure obj.Destroy; begin dispose( self ); end;
var o: obj; begin new(o); o.Destroy; WriteLn( 'OK' ); end.
Enjoy, Peter.
Peter N Lewis wrote:
At 9:24 +0800 27/6/05, Peter N Lewis wrote:
dispose( self ) complains:
/Source/MyAssocStrings.p: In method `AssocStringsObject.Destroy': /Source/MyAssocStrings.p:254: error: argument 1 to `Dispose' must be a pointer
Here is a test program for this case:
{$mac-pascal} program peterN;
type obj = object procedure Destroy; end;
procedure obj.Destroy; begin dispose( self ); end;
var o: obj; begin new(o); o.Destroy; WriteLn( 'OK' ); end.
The problem was that `self' was not a pointer but a reference (like for BP objects). The following should fix it:
diff -u p.nn/declarations.c p/declarations.c --- p.nn/declarations.c 2005-06-23 02:05:16.000000000 +0200 +++ p/declarations.c 2005-06-30 03:40:04.350829024 +0200 @@ -2849,6 +2849,18 @@ { /* Implicitly do `with Self do' */ tree self = lookup_name (self_id), t; + if (self && TREE_CODE (TREE_TYPE (self)) == REFERENCE_TYPE) + { + tree stp = TYPE_POINTER_TO (TREE_TYPE (TREE_TYPE (self))); + if (stp && PASCAL_TYPE_CLASS (stp)) + { + tree d = build_decl (CONST_DECL, self_id, stp); + DECL_INITIAL (d) = convert (stp, self); + IDENTIFIER_VALUE (self_id) = d; + pushdecl_nocheck (d); + DECL_CONTEXT (d) = current_function_decl; + } + } if (self) shadowed = pascal_shadow_record_fields (build_indirect_ref (self, "`Self' reference"), NULL_TREE); /* Mark the fields as declared in the current scope (fjf280b.pas) */
The problem was that `self' was not a pointer but a reference (like for BP objects). The following should fix it:
Yep, that seems to solve the problem.
Thanks!
Currently I'm going through about 250 units getting them all to compile under GPC.
The biggest challenges I'm facing are:
Lack of univ parameter support (I see Sun Workshop Compiler docs http://www.ictp.trieste.it/~manuals/programming/sun/pascal/lang_ref/ref_proghead.doc.html#742, so it is not just Mac Pascals).
Lack of {$unused( param )} directive - needs to be commended out with ifdef __GPC__ for each one (and then I don't understand why GPC is not itself warning about the unused parameters...)
Lexical vs Syntactical case difference warnings (CW Pascal complains when you refer to something with a different case to what it was defined as, GPC complains when two identifiers have different case, even if they are referring to different things (such as a function name and a record field).
Lack of short string support (ironically, this would be the hardest of the three to implement in GPC, and is the one causing the least problems).
Of course, I still have to actually *run* the code when I eventually finish getting them all to compile - but I'm sure that will not be a problem ;-) Enjoy, Peter.
Peter N Lewis wrote:
The biggest challenges I'm facing are:
Lack of univ parameter support (I see Sun Workshop Compiler docs http://www.ictp.trieste.it/~manuals/programming/sun/pascal/lang_ref/ref_proghead.doc.html#742, so it is not just Mac Pascals).
At first glance, it seems to be different. AFAIUI, the Mac Pascal version requires the same size for the parameter. This page says:
: univ is most often used for passing arrays, where you can call a : procedure or function with different array sizes. In that case, : you generally would pass another parameter that gives the actual : size of the array, as follows:
I.e., obviously not the same size. The example is about a var-parameter (where internally a pointer is passed, so in this regard the size is the same), but it doesn't seem to say that the statement applies only to var-parameters.
BTW, I think the example is pretty bad anyway. Why "convert" (by using univ) a variable-size array to 1..100? When the actual parameter is larger, the code would fail with a spurious range-check error. If they want to allow for variable array sizes, they should have used a conformant array parameter, which according to this page, this compiler supports as well. And, given the example as it is written, wouldn't the compiler allow for any type for the actual parameter (not only array [1 .. something] of real)? This would be really bogus.
Anyway, implementing it for different-size value parameters would be hazardous AFAICT, and I can't imagine anybody really wants this.
So what do you really need? I think defining a sane subset might be the only way out of this long-standing dilemma. Types that happen to have the same size on a given platform, e.g. a pointer and some integer type, seem too fragile, and I can't easily imagine a good use for such conversions. OTOH, all pointer types (in GPC) always have the same size, so converting between pointers would be less risky, and more meaningful. Is this sufficient? What kinds of parameters are required, only value, or also var paremeters?
And if we could restrict it to pointers, do I get it right that the routine externally behaves as if the parameter were an untyped pointer (i.e., `Pointer' in BP and GPC), and internally the pointer is converted to the given type before the routine starts?
Lack of {$unused( param )} directive - needs to be commended out with ifdef __GPC__ for each one (and then I don't understand why GPC is not itself warning about the unused parameters...)
Nomally it does with -Wunused-parameters (or -Wall which includes it). Did you use this option? If so, can you provide an example?
Frank
Frank Heckenbach wrote:
Peter N Lewis wrote:
The biggest challenges I'm facing are:
Lack of univ parameter support (I see Sun Workshop Compiler docs <http://www.ictp.trieste.it/~manuals/programming/sun/pascal/lang_ref/ ref_proghead.doc.html#742>, so it is not just Mac Pascals).
At first glance, it seems to be different. AFAIUI, the Mac Pascal version requires the same size for the parameter. This page says:
: univ is most often used for passing arrays, where you can call a : procedure or function with different array sizes. In that case, : you generally would pass another parameter that gives the actual : size of the array, as follows:
I.e., obviously not the same size. The example is about a var-parameter (where internally a pointer is passed, so in this regard the size is the same), but it doesn't seem to say that the statement applies only to var-parameters.
BTW, I think the example is pretty bad anyway. Why "convert" (by using univ) a variable-size array to 1..100? When the actual parameter is larger, the code would fail with a spurious range-check error. If they want to allow for variable array sizes, they should have used a conformant array parameter, which according to this page, this compiler supports as well. And, given the example as it is written, wouldn't the compiler allow for any type for the actual parameter (not only array [1 .. something] of real)? This would be really bogus.
Anyway, implementing it for different-size value parameters would be hazardous AFAICT, and I can't imagine anybody really wants this.
I agree that value parameters should have the same size.
So what do you really need? I think defining a sane subset might be the only way out of this long-standing dilemma. Types that happen to have the same size on a given platform, e.g. a pointer and some integer type, seem too fragile, and I can't easily imagine a good use for such conversions.
I don't see a reason why a conversion from a pointer to an integer type is "too fragile". If the compiler checks the sizes, the only risk is an error messages when sizes ever change. Yes, I agree that it is not "good style" for platform independent code, but even then the decision is up to the programmer. I value that GPC is great for writing platform-independent code, but we have to be realistic too. As of today, this only applies to non-GUI programs. As soon as you start to write GUI applications, the software is heavily dependent on the OS and platform-independence is no longer an argument, because you have made a decision beforehand on what platforms the software should run.
I will be quite happy if, at some point in the future, we will be able to write high-quality platform-independent GUI software for all platforms using GPC and GtK, Qt, GNU Step, Lazarus or whatever framework, but even then we should think about the many millions of lines of code that have been written already - and that we don't want to throw away, because it took us many years of our life and utmost devotion to write.
OTOH, all pointer types (in GPC) always have the same size, so converting between pointers would be less risky, and more meaningful. Is this sufficient? What kinds of parameters are required, only value, or also var paremeters?
Both value and var parameters.
And if we could restrict it to pointers, do I get it right that the routine externally behaves as if the parameter were an untyped pointer (i.e., `Pointer' in BP and GPC), and internally the pointer is converted to the given type before the routine starts?
There is also the unfortunate case (discussed long ago) where an untyped 'Pointer' parameter of a formal procedural parameter is rejected by the compiler when the corresponding pointer parameter of the actual procedural parameter is typed.
Lack of {$unused( param )} directive - needs to be commended out with ifdef __GPC__ for each one (and then I don't understand why GPC is not itself warning about the unused parameters...)
Nomally it does with -Wunused-parameters (or -Wall which includes it). Did you use this option? If so, can you provide an example?
Isn't at least -O1 required when checking for unused parameters (etc.)
Regards,
Adriaan van Os
Adriaan van Os wrote:
I don't see a reason why a conversion from a pointer to an integer type is "too fragile".
Because pointer and integer types can have different sizes on different platforms. We've had this argumment before. The compatibility of parameters would then vary from system to system.
If the compiler checks the sizes, the only risk is an error messages when sizes ever change. Yes, I agree that it is not "good style" for platform independent code, but even then the decision is up to the programmer.
Bogus argument that can be used to support any crappy feature.
I tried to find a constructive solution, but if it's "all or nothing" to you, including unsafe pointer-integer conversions, I don't think we'll reach a solution.
I value that GPC is great for writing platform-independent code, but we have to be realistic too. As of today, this only applies to non-GUI programs.
No, it doesn't.
As soon as you start to write GUI applications, the software is heavily dependent on the OS and platform-independence is no longer an argument, because you have made a decision beforehand on what platforms the software should run.
You've seen no portable GUI software yet? AFAIK, there's even X11 for Windows by now. Not to mention portable GUI toolkits such as Qt ...
It will be dependent on the OS probably if you write it the Windows or Mac way, but Unix GUIs have few special OS dependencies.
And if we could restrict it to pointers, do I get it right that the routine externally behaves as if the parameter were an untyped pointer (i.e., `Pointer' in BP and GPC), and internally the pointer is converted to the given type before the routine starts?
There is also the unfortunate case (discussed long ago) where an untyped 'Pointer' parameter of a formal procedural parameter is rejected by the compiler when the corresponding pointer parameter of the actual procedural parameter is typed.
For var-parameters, this is?
Isn't at least -O1 required when checking for unused parameters (etc.)
No, for using unintialized variables.
Frank
At 12:36 +0200 1/7/05, Frank Heckenbach wrote:
Peter N Lewis wrote:
At first glance, it seems to be different. AFAIUI, the Mac Pascal version requires the same size for the parameter. This page says:
: univ is most often used for passing arrays, where you can call a : procedure or function with different array sizes. In that case, : you generally would pass another parameter that gives the actual : size of the array, as follows:
So what do you really need? I think defining a sane subset might be the only way out of this long-standing dilemma.
I would be perfectly happy with univ working only for pointer or scalar types, and requiring the size of the parameter to match. I would be reasonably happy with only working with pointer types and integers with the same size as pointer. I would be acceptably happy with only working with pointer types.
Types that happen to have the same size on a given platform, e.g. a pointer and some integer type, seem too fragile, and I can't easily imagine a good use for such conversions.
One option is to define IntegerPtr or such which is an integer the same size as pointer. At least it is easy to define in one place a system-specific integer size that matches the size of pointers on that system.
On the Mac, it is typical for libraries to use a userdata field which is 4 bytes, often an SInt32 or Ptr=^UInt8, and it is useful to be able to store a UInt32 or Pointer when storing such data, and so univ SInt32 would be useful to accept both.
I definitely agree, any univ implementation should at a minimum require the sizes to match.
OTOH, all pointer types (in GPC) always have the same size, so converting between pointers would be less risky, and more meaningful. Is this sufficient? What kinds of parameters are required, only value, or also var paremeters?
value and var is required. The typical cases would be such as:
procedure MyCFRelease( var cf: CFTypePtr ); procedure CFShow( cf: CFTypePtr ); procedure SetUserData( obj: Whatever; userdata: unit SInt32 ); procedure GetUserData( obj: Whatever; var userdata: unit SInt32 );
And if we could restrict it to pointers, do I get it right that the routine externally behaves as if the parameter were an untyped pointer (i.e., `Pointer' in BP and GPC), and internally the pointer is converted to the given type before the routine starts?
Pretty much, although it would certainly be helpful to allow compatible sized integers as well as pointers. Generally there should be no need to "convert" the data since it should be size and binary compatible and just type changed.
Lack of {$unused( param )} directive - needs to be commended out with ifdef __GPC__ for each one (and then I don't understand why GPC is not itself warning about the unused parameters...)
Nomally it does with -Wunused-parameters (or -Wall which includes it). Did you use this option? If so, can you provide an example?
I have -Wall, but I haven't seen them, perhaps it is the -O0 as Adriaan suggests?
Given GPC does has -Wunused-parameters, {$unused()} becomes even more useful.
Thanks, Peter.
Does GPC support telling whether an object is a member of a particular object class hierarchy?
Mac Pascals have
member( obj, ObjectType )
which returns a boolean, true if obj is an object of type ObjectType.
I've included a sample program below.
If GPC has an alternative way of telling this, that will probably solve my problem, although this may still be an issue for compatibility.
Thanks, Peter.
{$methods-always-virtual} program peterU;
type ObjectBase = object procedure Doit; end; ObjectA = object(ObjectBase) procedure Doit; override; end; ObjectB = object(ObjectBase) procedure Doit; override; end;
procedure ObjectBase.Doit; begin end;
procedure ObjectA.Doit; begin end;
procedure ObjectB.Doit; begin end;
var base: ObjectBase; a: ObjectA; b: ObjectB; begin New(base); New(a); New(b); if member( base, ObjectBase ) and not member( base, ObjectA ) and not member( base, ObjectB ) and member( a, ObjectBase ) and member( a, ObjectA ) and not member( a, ObjectB ) and member( b, ObjectBase ) and not member( b, ObjectA ) and member( b, ObjectB ) then begin WriteLn( 'OK' ); end else begin WriteLn( 'failed' ); end; end.
Peter N Lewis wrote:
Does GPC support telling whether an object is a member of a particular object class hierarchy?
Mac Pascals have
member( obj, ObjectType )
obj is ObjectType
which returns a boolean, true if obj is an object of type ObjectType.
I've included a sample program below.
If GPC has an alternative way of telling this, that will probably solve my problem, although this may still be an issue for compatibility.
Maybe a macro could help ...
if member( base, ObjectBase )
This is always true due to the declaration, so GPC warns.
and member( a, ObjectBase )
GPC does not accept this one. This is "more than true", as by declaration, a is always of a subtype of ObjectBase already. So it's probably not a practically interesting case.
member( b, ObjectA )
This can never be true (by declaration). Again, probably not relevant in practice.
Frank
Peter N Lewis wrote:
Does GPC support telling whether an object is a member of a particular object class hierarchy?
Mac Pascals have
member( obj, ObjectType )
which returns a boolean, true if obj is an object of type ObjectType.
I've included a sample program below.
If GPC has an alternative way of telling this, that will probably solve my problem, although this may still be an issue for compatibility.
Thanks, Peter.
GPC uses `is' operator for this purpose. However, there are poblems: 1) `is' was disabled for Mac Pascal 2) `is' did not work for Mac objects (classes). Patch below add needed support. 3) after adding {$define member(a,b) (a is b)} to your program (and with the patch) I get:
peterU2.pas:36: warning: `is' always yields `True' if the right operand peterU2.pas:36: warning: is the declared type of the left operand. peterU2.pas:38: error: right operand of `is' must be a derived type peterU2.pas:38: error: of the declared type of the left operand peterU2.pas:38: warning: `is' always yields `True' if the right operand peterU2.pas:38: warning: is the declared type of the left operand. peterU2.pas:39: error: right operand of `is' must be a derived type peterU2.pas:39: error: of the declared type of the left operand peterU2.pas:40: error: right operand of `is' must be a derived type peterU2.pas:40: error: of the declared type of the left operand peterU2.pas:41: error: right operand of `is' must be a derived type peterU2.pas:41: error: of the declared type of the left operand peterU2.pas:41: warning: `is' always yields `True' if the right operand peterU2.pas:41: warning: is the declared type of the left operand.
In particular, GPC considers `a is ObjectB' as error if ObjectB is not a derived class of class of a. While we may add some support for useless tests of this sort, it seems better to give error by default
diff -u p.nn/objects.c p/objects.c --- p.nn/objects.c 2005-06-22 07:32:06.000000000 +0200 +++ p/objects.c 2005-07-02 15:22:38.514561976 +0200 @@ -705,6 +705,16 @@ build_is_as (tree left, tree right, int op) { const char *opname = (op == p_is) ? "is" : "as"; + int want_class = 0; + tree oleft = left; + if (TREE_CODE (right) == POINTER_TYPE && PASCAL_TYPE_CLASS (right)) + { + right = TREE_TYPE (right); + want_class = 1; + } + if (TREE_CODE (TREE_TYPE (left)) == POINTER_TYPE + && PASCAL_TYPE_CLASS (TREE_TYPE (left))) + left = build_indirect_ref (left, NULL); if (!PASCAL_TYPE_OBJECT (right)) error ("right operand of `%s' must be an object type", opname); else if (!PASCAL_TYPE_OBJECT (TREE_TYPE (left))) @@ -718,7 +728,11 @@ || TREE_CODE (l) == NON_LVALUE_EXPR) l = TREE_OPERAND (l, 0); while (t && TYPE_MAIN_VARIANT (t) != tl) - t = TYPE_LANG_BASE (t); + { + t = TYPE_LANG_BASE (t); + if (t && TREE_CODE (t) == POINTER_TYPE) + t = TREE_TYPE (t); + } if (!t) { error ("right operand of `%s' must be a derived type", opname); @@ -738,7 +752,7 @@ { warning ("`as' has no effect if the right operand is"); warning (" the declared type of the left operand"); - return left; + return oleft; } } /* Variables, value parameters and components are not polymorphic. @@ -784,12 +798,13 @@ within the RTS so the compiler can optimize a construction like `if foo is bar then something (foo as bar)'. */ p_right = build_pointer_type (right); - return build_indirect_ref (save_expr ( + res = save_expr ( build (COMPOUND_EXPR, p_right, build (COND_EXPR, void_type_node, res, convert (void_type_node, integer_zero_node), build_predef_call (p_as, NULL_TREE)), - convert (p_right, build_pascal_unary_op (ADDR_EXPR, left)))), NULL); + convert (p_right, build_pascal_unary_op (ADDR_EXPR, left)))); + return want_class ? res : build_indirect_ref (res, NULL); } } } diff -u p.nn/predef.def p/predef.def --- p.nn/predef.def 2005-06-22 03:59:53.000000000 +0200 +++ p/predef.def 2005-07-02 14:29:45.660909048 +0200 @@ -57,7 +57,7 @@ PREDEF_KEYWORD (and, 0, ANY_PASCAL) /* Boolean or bitwise `and' operator or part of the <and then> operator */ PREDEF_KEYWORD (and_then, 1, E_O_PASCAL) /* short-circuit Boolean <and> operator */ PREDEF_KEYWORD (array, 0, ANY_PASCAL) /* array type declaration */ -PREDEF_KEYWORD (as, 1, O_D_PASCAL) /* object type membership test and conversion */ +PREDEF_KEYWORD (as, 1, O_D_M_PASCAL) /* object type membership test and conversion */ PREDEF_KEYWORD (asm, 1, B_D_PASCAL) /* GNU style inline assembler code */ PREDEF_KEYWORD (asmname, 1, GNU_PASCAL) /* DEPRECATED! linker name of routines and variables */ PREDEF_KEYWORD (attribute, 1, GNU_PASCAL) /* attributes of routines and variables */ @@ -89,7 +89,7 @@ PREDEF_KEYWORD (in, 0, ANY_PASCAL) /* set membership test or part of a <for> loop iterating through sets */ PREDEF_KEYWORD (inherited, 1, O_B_D_M_PASCAL) /* reference to methods of ancestor object types */ PREDEF_KEYWORD (initialization, 1, BORLAND_DELPHI) /* unit initialization */ -PREDEF_KEYWORD (is, 1, O_D_PASCAL) /* object type membership test */ +PREDEF_KEYWORD (is, 1, O_D_M_PASCAL) /* object type membership test */ PREDEF_KEYWORD (label, 0, ANY_PASCAL) /* label declaration for a <goto> statement */ PREDEF_KEYWORD (mod, 0, ANY_PASCAL) /* integer remainder operator */ PREDEF_KEYWORD (near, 0, B_D_PASCAL) /* BP directive (ignored) */
At 15:17 +0200 2/7/05, Waldek Hebisch wrote:
GPC uses `is' operator for this purpose. However, there are poblems:
- `is' was disabled for Mac Pascal
- `is' did not work for Mac objects (classes). Patch below add needed support.
- after adding {$define member(a,b) (a is b)} to your program (and with the patch) I get:
peterU2.pas:36: warning: `is' always yields `True' if the right operand peterU2.pas:36: warning: is the declared type of the left operand. peterU2.pas:38: error: right operand of `is' must be a derived type peterU2.pas:38: error: of the declared type of the left operand peterU2.pas:38: warning: `is' always yields `True' if the right operand peterU2.pas:38: warning: is the declared type of the left operand. peterU2.pas:39: error: right operand of `is' must be a derived type peterU2.pas:39: error: of the declared type of the left operand peterU2.pas:40: error: right operand of `is' must be a derived type peterU2.pas:40: error: of the declared type of the left operand peterU2.pas:41: error: right operand of `is' must be a derived type peterU2.pas:41: error: of the declared type of the left operand peterU2.pas:41: warning: `is' always yields `True' if the right operand peterU2.pas:41: warning: is the declared type of the left operand.
In particular, GPC considers `a is ObjectB' as error if ObjectB is not a derived class of class of a. While we may add some support for useless tests of this sort, it seems better to give error by default
I believe that is entirely acceptable.
Adriaan: Can you add "{$define member(a,b) (a is b)}" to your porting guidelines for CW -> GPC?
The patch appears to work (at least it compiles. 75 more units and I'll be able to start testing if it works ;-)
Thanks, Peter.
Peter N Lewis wrote:
Adriaan: Can you add "{$define member(a,b) (a is b)}" to your porting guidelines for CW -> GPC?
For safety you might want to add extra parentheses around a (not b which must be a type name and therefore neither needs nor allows for extra parentheses):
{$define member(a,b) ((a) is b)}
Frank
With the various MacPascal/Delphi object support patches posted on this list, fjf903c.pas (in the testsuite) crashes gpc.
{$mac-pascal}
program fjf903c;
type {$local W-} a = object procedure p; end;
b = object (a) procedure p; override; end; {$endlocal}
procedure a.p; begin WriteLn ('failed') end;
procedure b.p; begin WriteLn ('OK') end;
var v: a;
begin v := New (b); v.p end.
Exception: EXC_BAD_ACCESS (0x0001) Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000034
Thread 0 Crashed: 0 gpc1 0x0006ab7c dbxout_type + 0x1e74 (dbxout.c:1020) 1 gpc1 0x00068f24 dbxout_type + 0x21c (dbxout.c:1879) 2 gpc1 0x0006bc14 dbxout_symbol + 0x4f0 (dbxout.c:2263) 3 gpc1 0x000bd0fc rest_of_decl_compilation + 0x1e4 (toplev.c:1988) 4 gpc1 0x0001823c declare_types + 0x178 (declarations.c:3185) 5 gpc1 0x0000d698 yyuserAction + 0xaa70 (parse.y:579) 6 gpc1 0x00010928 main_yyparse + 0x738 (parse.c:7905) 7 gpc1 0x000c1104 toplev_main + 0x828 (toplev.c:1826) 8 gpc1 0x00001a80 _start + 0x188 (crt.c:267) 9 dyld 0x8fe1a278 _dyld_start + 0x64
[G5:gcc/p/test] adriaan% gpc -v Reading specs from /Developer/Pascal/gpc344d1/lib/gcc/powerpc-apple-darwin7/3.4.4/specs Configured with: ../gcc-3.4.4/configure --enable-languages=pascal,c --enable-threads=posix --target=powerpc-apple-darwin7 --host=powerpc-apple-darwin7 --build=powerpc-apple-darwin7 --prefix=/Developer/Pascal/gpc344d1 Thread model: posix gpc version 20050331, based on gcc-3.4.4
Regards,
Adriaan van Os
Adriaan van Os wrote:
With the various MacPascal/Delphi object support patches posted on this list, fjf903c.pas (in the testsuite) crashes gpc.
<snip>
Exception: EXC_BAD_ACCESS (0x0001) Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000034
Thread 0 Crashed: 0 gpc1 0x0006ab7c dbxout_type + 0x1e74 (dbxout.c:1020)
Apparently dbxout.c assumes that all object look like C++ objects. The following backend patch should fix the crash:
--- gcc-3.4.3/gcc/dbxout.c.bb 2005-06-14 03:33:07.000000000 +0200 +++ gcc-3.4.3/gcc/dbxout.c 2005-07-22 00:17:41.389503512 +0200 @@ -1011,13 +1011,17 @@ tree type_encoding; tree fndecl; tree last; +#ifndef GPC char formatted_type_identifier_length[16]; int type_identifier_length; +#endif
if (methods == NULL_TREE) return;
+#ifndef GPC type_encoding = DECL_NAME (TYPE_NAME (type)); +#endif
#if 0 /* C++: Template classes break some assumptions made by this code about @@ -1037,9 +1041,11 @@ } #endif
+#ifndef GPC type_identifier_length = IDENTIFIER_LENGTH (type_encoding);
sprintf (formatted_type_identifier_length, "%d", type_identifier_length); +#endif
if (TREE_CODE (methods) != TREE_VEC) fndecl = methods;
Waldek Hebisch wrote:
Adriaan van Os wrote:
With the various MacPascal/Delphi object support patches posted on this list, fjf903c.pas (in the testsuite) crashes gpc.
<snip> > Exception: EXC_BAD_ACCESS (0x0001) > Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000034 > > Thread 0 Crashed: > 0 gpc1 0x0006ab7c dbxout_type + 0x1e74 (dbxout.c:1020)
Apparently dbxout.c assumes that all object look like C++ objects.
Or it used to. Seems the code you deactivated was already dead code in the original. (Apparently remaining from 2.95.x where formatted_type_identifier_length was actually used.)
Frank
Frank Heckenbach wrote:
Waldek Hebisch wrote:
Apparently dbxout.c assumes that all object look like C++ objects.
Or it used to. Seems the code you deactivated was already dead code in the original. (Apparently remaining from 2.95.x where formatted_type_identifier_length was actually used.)
Yes, the code was dead (so it is safe to comment it out). But still, the code was assumed safe to execute.
Waldek Hebisch wrote:
Adriaan van Os wrote:
With the various MacPascal/Delphi object support patches posted on this list, fjf903c.pas (in the testsuite) crashes gpc.
<snip> > Exception: EXC_BAD_ACCESS (0x0001) > Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000034 > > Thread 0 Crashed: > 0 gpc1 0x0006ab7c dbxout_type + 0x1e74 (dbxout.c:1020)
Apparently dbxout.c assumes that all object look like C++ objects. The following backend patch should fix the crash:
--- gcc-3.4.3/gcc/dbxout.c.bb 2005-06-14 03:33:07.000000000 +0200 +++ gcc-3.4.3/gcc/dbxout.c 2005-07-22 00:17:41.389503512 +0200 @@ -1011,13 +1011,17 @@ tree type_encoding; tree fndecl; tree last; +#ifndef GPC char formatted_type_identifier_length[16]; int type_identifier_length; +#endif
if (methods == NULL_TREE) return;
+#ifndef GPC type_encoding = DECL_NAME (TYPE_NAME (type)); +#endif
#if 0 /* C++: Template classes break some assumptions made by this code about @@ -1037,9 +1041,11 @@ } #endif
+#ifndef GPC type_identifier_length = IDENTIFIER_LENGTH (type_encoding);
sprintf (formatted_type_identifier_length, "%d", type_identifier_length); +#endif
if (TREE_CODE (methods) != TREE_VEC) fndecl = methods;
This solves the problem, thanks.
Regards,
Adriaan van Os
Peter N Lewis wrote:
Types that happen to have the same size on a given platform, e.g. a pointer and some integer type, seem too fragile, and I can't easily imagine a good use for such conversions.
One option is to define IntegerPtr or such which is an integer the same size as pointer.
We have this type already, it's called PtrInt. That's not the problem. But with such a rule, the parameter would also allow, say, CInteger, if it happened to have the same size as a pointer which may or may not be the case.
And if we could restrict it to pointers, do I get it right that the routine externally behaves as if the parameter were an untyped pointer (i.e., `Pointer' in BP and GPC), and internally the pointer is converted to the given type before the routine starts?
Pretty much, although it would certainly be helpful to allow compatible sized integers as well as pointers. Generally there should be no need to "convert" the data since it should be size and binary compatible and just type changed.
This is what converting means (in Pascal, not assembler).
Lack of {$unused( param )} directive - needs to be commended out with ifdef __GPC__ for each one (and then I don't understand why GPC is not itself warning about the unused parameters...)
Nomally it does with -Wunused-parameters (or -Wall which includes it). Did you use this option? If so, can you provide an example?
I have -Wall, but I haven't seen them, perhaps it is the -O0 as Adriaan suggests?
Ah, sorry, it requires -Wall -W (both).
Given GPC does has -Wunused-parameters, {$unused()} becomes even more useful.
I think we've discussed compiler directives vs. attributes or statements (Discard) before. Restarting an old discussion without new points really only wastes time of all of us. (Discard is there, attributes could be possible, would add new syntax which hopefully won't conflict, but would have to check, compiler directives would be quite contrary to the existing principle of compiler directives which don't directly refer to particular Pascal code elements, but rather influence the general behaviour of the compiler.)
Frank
Given GPC does has -Wunused-parameters, {$unused()} becomes even
more useful.
I think we've discussed compiler directives vs. attributes or statements (Discard) before.
I don't suppose there is any change Discard could take more than one parameter and discard them all? Peter.
Peter N Lewis wrote:
Given GPC does has -Wunused-parameters, {$unused()} becomes even
more useful.
I think we've discussed compiler directives vs. attributes or statements (Discard) before.
I don't suppose there is any change Discard could take more than one parameter and discard them all?
I would not be difficult to add. OTOH, it would make it a more special extensions. As has been noted repeatedly, the lest "costly" extensions are those that behave like a predefined routine (though, here, accepting any type).
Frank
I don't suppose there is any change Discard could take more than one parameter and discard them all?
I would not be difficult to add. OTOH, it would make it a more special extensions. As has been noted repeatedly, the lest "costly" extensions are those that behave like a predefined routine (though, here, accepting any type).
Well, my current solution is a whole bunch of Macros labeld Discard2, Discard3, ... Discard6, that take N parameters and expand to N calls to Discard. Not ideal, but it will work.
Discard ( a,b,c ) seems nice and clean to me, but I don't know the structure of GPC well enough to understand what complications it might add. Peter.
Peter N Lewis wrote:
I don't suppose there is any change Discard could take more than one parameter and discard them all?
I would not be difficult to add. OTOH, it would make it a more special extensions. As has been noted repeatedly, the lest "costly" extensions are those that behave like a predefined routine (though, here, accepting any type).
Well, my current solution is a whole bunch of Macros labeld Discard2, Discard3, ... Discard6, that take N parameters and expand to N calls to Discard. Not ideal, but it will work.
Discard ( a,b,c ) seems nice and clean to me, but I don't know the structure of GPC well enough to understand what complications it might add.
As I said, it wouldn't add considerable complications, that's not the problem.
My doubt is WRT what kind of extension we'd introduce and if it's warranted. This doesn't affect GPC directly, but it might affect other compilers trying to be compatible, and possibly even future versions of GPC. Due to some recent observations how unintentional misfeatures creep into usage and are hard to correct later (`absolute' extensions and other things), I've become more cautious about this aspect.
The existing `Discard' can (almost) be emulated with a procedure taking an untyped parameter (which is also not standard, sure, but supported by more compilers). A `Discard' with any number of arguments would require a "varags" procedure or at least "varargs macros" or something like that to emulate ...
This doesn't mean it's impossible to add it, if the advantages outweigh, but I'm not yet sure of that ...
FWIW, I myself use sequences of `Discard' when necessary. So far haven't felt particularly bad about it ...
Frank
At 12:36 +0200 1/7/05, Frank Heckenbach wrote:
Lack of univ parameter support (I see Sun Workshop Compiler docs
So what do you really need?
Every use of univ in the Apple Universal Interfaces is a pointer (they are all just Ptr, but that is unsurprising since they don't specify the implementation anyway, and they are probably defined as void * in the C interfaces).
In my own code, I have roughly 500 odd uses, including:
Ptr PtrPtr
MyListHeadPtr MyListItemPtr DCtlArrayPtr FSXParamBlockRecPtr BookmarksBarItemPtr MovableModalStatePtr MyQElemPtr ParmBlkPtr QElemPtr CFPropertyListRef CFTypeRef
UInt32 SInt32 SInt16 UInt16 SInt64 UInt64
The use breaks down as:
* General arbitrary memory pointer (eg for BlockMove, FileWriteData, etc) * Pointers to polymorphic type (eg CFPropertyListRef is a "subclass" of CFTypeRef, and shares functions like Destroy, Show, etc). * Pointers to extendable types (eg MyQElemPtr points to a record that must start with a QElemRecord, but then continues with user data). * Storage/Retrieval of user data (eg, user data is 32 bits, and can store an arbitrary user data like a reference number or pointer). * Low level data manipulation (like read/write 16/32/64 bit quantities from a file).
So basically Pointer and sized integer are the uses I have, and the sized integer that matches the size of pointer needs to be compatible. Also, ideally, it would be compatible with function pointer as well, since that would be one thing that might want to be stored in a userdata field.
Thanks, Peter.
Peter N Lewis wrote:
At 12:36 +0200 1/7/05, Frank Heckenbach wrote:
Lack of univ parameter support (I see Sun Workshop Compiler docs
So what do you really need?
Every use of univ in the Apple Universal Interfaces is a pointer (they are all just Ptr, but that is unsurprising since they don't specify the implementation anyway, and they are probably defined as void * in the C interfaces).
In my own code, I have roughly 500 odd uses, including:
Ptr PtrPtr
MyListHeadPtr MyListItemPtr DCtlArrayPtr FSXParamBlockRecPtr BookmarksBarItemPtr MovableModalStatePtr MyQElemPtr ParmBlkPtr QElemPtr CFPropertyListRef CFTypeRef
UInt32 SInt32 SInt16 UInt16 SInt64 UInt64
The use breaks down as:
- General arbitrary memory pointer (eg for BlockMove, FileWriteData, etc)
- Pointers to polymorphic type (eg CFPropertyListRef is a "subclass"
of CFTypeRef, and shares functions like Destroy, Show, etc).
- Pointers to extendable types (eg MyQElemPtr points to a record that
must start with a QElemRecord, but then continues with user data).
- Storage/Retrieval of user data (eg, user data is 32 bits, and can
store an arbitrary user data like a reference number or pointer).
- Low level data manipulation (like read/write 16/32/64 bit
quantities from a file).
So basically Pointer and sized integer are the uses I have, and the sized integer that matches the size of pointer needs to be compatible. Also, ideally, it would be compatible with function pointer as well, since that would be one thing that might want to be stored in a userdata field.
I think so. We have some problems with function pointers. Another thread a while ago pointed me to them, but they seem difficult to fix, and I haven't done this yet. (In that thread, AFAIR, Waldek fixed the problem at hand, and also noted the deeper problems.) So this should happen sooner or later (I hope sooner ;-).
Anyway, if I get this right, the vast majority of your uses, are actually pointers/references, including all in Apple's headers.
BTW, the mentioning of C interfaces is a good point. AFAIK, `void *' is the closest thing you can do in C anyway, and there is no parameter that accepts either pointers or integers (barring completely undeclared functions and varargs which have no checking at all, of course). So I could ask heretically, do we want even looser type checking than C? ;-)
Seriously, I'd really prefer to go for the "acceptably happy" solution (referring to your other mail), in particular if it does not even impede the Apple interfaces (which you can't change at will, I understand).
Frank
I think so. We have some problems with function pointers. Another thread a while ago pointed me to them, but they seem difficult to fix, and I haven't done this yet. (In that thread, AFAIR, Waldek fixed the problem at hand, and also noted the deeper problems.) So this should happen sooner or later (I hope sooner ;-).
This issue I have with function pointers is two fold:
Not being able to cast them to/from an arbitrary pointer (which makes storing them or passing them through a confined interface where procedure types are not appropriate challenging), and not being able to case one procedural variable to another one, even if they are reasonably compatible.
While both these restrictions may have safety reasons, generally I end up needing to do them anyway to comply with various restricted interfaces, which then means I have to find some other way of complying, such as changing all the parameters to exactly match a the specification, and then casting the all back again inside the procedure or such, which really does not improve safety.
Still, I can live with this, it's just a nuisance. To my mind, type casts exist to allow me to say "I know what I'm doing, it may not be safe, but I have made the conscious decision by putting the type cast explicitly in the code that I want to proceed". Peter.
Peter N Lewis wrote:
I think so. We have some problems with function pointers. Another thread a while ago pointed me to them, but they seem difficult to fix, and I haven't done this yet. (In that thread, AFAIR, Waldek fixed the problem at hand, and also noted the deeper problems.) So this should happen sooner or later (I hope sooner ;-).
This issue I have with function pointers is two fold:
Not being able to cast them to/from an arbitrary pointer (which makes storing them or passing them through a confined interface where procedure types are not appropriate challenging), and not being able to case one procedural variable to another one, even if they are reasonably compatible.
Yes, I think both should work (with casting probably even for all function pointers then, since it may be difficult to define what reasonably compatible, and anyway, type-casts are meant to override typing rules). I hope we can fix this soon.
Frank
With methods-always-virtual, if a method, GetObj, returns an object, and you call a method directly from the call to GetObj, gpc fails with an error.
Ie, obj.GetObj.Method( whatever ) fails.
Using a temporary variable works fine, ie:
obj2 := obj.GetObj; obj2.Method( whatever )
compiles without problems.
Test program and error output below.
Thanks, Peter.
% gp peterV.pas /peterV.pas:7: warning: object type has virtual method, but no constructor /peterV.pas:11: warning: object type has virtual method, but no constructor /peterV.pas: In main program: /peterV.pas:30: error: request for field `Doit' in something not /peterV.pas:30: error: a record, schema or object
{$methods-always-virtual} program peterV;
type ObjectA = object procedure Doit; end; ObjectB = object obj: ObjectA; function GetA: ObjectA; end;
procedure ObjectA.Doit; begin WriteLn( 'OK' ); end;
function ObjectB.GetA: ObjectA; begin return obj; end;
var a: ObjectA; b: ObjectB; begin New(a); New(b); b.obj := a; b.GetA.Doit; end.
Peter N Lewis wrote"
With methods-always-virtual, if a method, GetObj, returns an object, and you call a method directly from the call to GetObj, gpc fails with an error.
Ie, obj.GetObj.Method( whatever ) fails.
Using a temporary variable works fine, ie:
obj2 := obj.GetObj; obj2.Method( whatever )
compiles without problems.
The following should fix the problem:
--- p.nn3/types.c 2005-06-22 06:22:32.000000000 +0200 +++ p/types.c 2005-07-14 03:35:44.000000000 +0200 @@ -1893,7 +1893,8 @@ datum = undo_schema_dereference (probably_call_function (datum)); type = TREE_TYPE (datum); } - else if (TREE_CODE (type) == POINTER_TYPE && PASCAL_TYPE_CLASS (type)) + + if (TREE_CODE (type) == POINTER_TYPE && PASCAL_TYPE_CLASS (type)) { // datum = build_pascal_pointer_reference (datum); datum = build_indirect_ref (datum, NULL);
At 17:46 +0200 15/7/05, Waldek Hebisch wrote:
Peter N Lewis wrote"
With methods-always-virtual, if a method, GetObj, returns an object, and you call a method directly from the call to GetObj, gpc fails with an error.
Ie, obj.GetObj.Method( whatever ) fails.
The following should fix the problem:
Yes, that appears to correct the test case, I will check more thoroughly in Interarchy and let you know if I see any errors with this.
Thanks, Peter.
BTW, the mentioning of C interfaces is a good point. AFAIK, `void *' is the closest thing you can do in C anyway, and there is no parameter that accepts either pointers or integers (barring completely undeclared functions and varargs which have no checking at all, of course). So I could ask heretically, do we want even looser type checking than C? ;-)
Do not we already have a "typeless" parameter that takes anything?
And, it is better than C and the "typeless" parameter in that at least the interface is self-documenting - the function can clearly express what it wants as an input even if it does not enforce it. This is better than the case of using Pointer, void * or typeless parameters in that they do not express any requirement of the parameter and leave it up to documentation (which for most projects inevitably is either written after the fact or is left inaccurately written.
Seriously, I'd really prefer to go for the "acceptably happy" solution (referring to your other mail), in particular if it does not even impede the Apple interfaces (which you can't change at will, I understand).
The only problem with that is that it does not allow for UInt16/SInt16, UInt32/SInt32, or UInt64/SInt64 compatible parameters (such as a function that writes a byte order dependent number to disk).
How about univ Ptr compatible with pointer types, univ Integer compatible with same sized scalar types?
That would get almost all the useful cases, and a Ptr/PtrCard cast could be used explicitly as required for the case where a pointer needs to be stored.
Thanks, Peter.
Using methods-always-virtual gives a problem for interface-only/implementation-only compiles.
With the example shown below, if you compile with
gpc -c peterQ.pas
all is well, but if you compile as gp often does, first with interface-only and then with implementation-only:
gpc -c --interface-only peterQ.pas gpc -c --implementation-only peterQ.pas
gpc thinks the object defined in the interface is not methods-always-virtual.
Note that using the command line switch --methods-always-virtual in both compiles makes no difference.
Thanks, Peter.
{$methods-always-virtual} unit peterQ;
interface
type MyObject = object procedure Destroy; end;
procedure Create;
implementation
procedure MyObject.Destroy; begin Dispose( self ); end;
procedure Create; var obj: MyObject; begin New(obj); obj.Destroy; end;
end.
zany:~/unix/c/testgpco% gpc -c peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor zany:~/unix/c/testgpco% gpc -c --interface-only peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor zany:~/unix/c/testgpco% gpc -c --implementation-only peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor peterQ.pas: In method `MyObject.Destroy': peterQ.pas:17: error: argument 1 to `Dispose' must be a pointer
Peter N Lewis wrote:
Using methods-always-virtual gives a problem for interface-only/implementation-only compiles.
With the example shown below, if you compile with
gpc -c peterQ.pas
all is well, but if you compile as gp often does, first with interface-only and then with implementation-only:
gpc -c --interface-only peterQ.pas gpc -c --implementation-only peterQ.pas
gpc thinks the object defined in the interface is not methods-always-virtual.
Why do you think so? The messages say it has a virtual method.
This warning is suppressed with --mac-pascal, not with --methods-always-virtual in case you mean this.
Frank
At 12:15 +0200 1/7/05, Frank Heckenbach wrote:
Peter N Lewis wrote:
gpc -c --interface-only peterQ.pas gpc -c --implementation-only peterQ.pas
gpc thinks the object defined in the interface is not
methods-always-virtual.
Why do you think so? The messages say it has a virtual method.
This warning is suppressed with --mac-pascal, not with --methods-always-virtual in case you mean this.
At 16:02 +0800 1/7/05, Peter N Lewis wrote:
peterQ.pas: In method `MyObject.Destroy': peterQ.pas:17: error: argument 1 to `Dispose' must be a pointer
This is the indication - it is indicating the obj is not considered a pointer suitable for use in new.
Note that with the example given,
gpc -c peterQ.pas
works, but:
gpc -c --interface-only peterQ.pas gpc -c --implementation-only peterQ.pas
fails with an error.
My guess is that it is reading the interface from the GPI, emitting the "virtual method, but no constructor" warning, and then forgetting that the object is a pointer. Peter.
Peter N Lewis wrote:
Using methods-always-virtual gives a problem for interface-only/implementation-only compiles.
With the example shown below, if you compile with
gpc -c peterQ.pas
all is well, but if you compile as gp often does, first with interface-only and then with implementation-only:
gpc -c --interface-only peterQ.pas gpc -c --implementation-only peterQ.pas
gpc thinks the object defined in the interface is not methods-always-virtual.
Note that using the command line switch --methods-always-virtual in both compiles makes no difference.
<snip>
zany:~/unix/c/testgpco% gpc -c peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor zany:~/unix/c/testgpco% gpc -c --interface-only peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor zany:~/unix/c/testgpco% gpc -c --implementation-only peterQ.pas peterQ.pas:9: warning: object type has virtual method, but no constructor peterQ.pas: In method `MyObject.Destroy': peterQ.pas:17: error: argument 1 to `Dispose' must be a pointer
That is still problem of `self' beeing a reference: the information needed to decide if `self' should be a pointer was not passed trough .gpi files. The following should fix this:
--- p.nn/module.c 2005-03-25 21:32:59.000000000 +0100 +++ p/module.c 2005-07-01 13:47:45.044573312 +0200 @@ -2012,6 +2012,7 @@ #ifdef EGCS store_node (TYPE_SIZE_UNIT (t)); #endif + store_node (TYPE_POINTER_TO (t)); store_node (TYPE_GET_INITIALIZER (t)); store_node (TYPE_MAIN_VARIANT (t) == t ? NULL_TREE : TYPE_MAIN_VARIANT (t)); break; @@ -2478,6 +2479,7 @@ #ifdef EGCS TYPE_SIZE_UNIT (t) = load_node (); #endif + TYPE_POINTER_TO (t) = load_node (); tmp = load_node (); if (tmp) { --- p.nn/utils/gpidump.pas 2005-03-31 01:01:01.000000000 +0200 +++ p/utils/gpidump.pas 2005-07-01 14:05:53.575091520 +0200 @@ -836,6 +836,7 @@ {$ifdef EGCS} Ref ('size_unit'); {$endif} + Ref ('pointer_to'); OptRef ('initializer'); OptRef ('main_variant'); end;
At 9:24 +0800 27/6/05, Peter N Lewis wrote:
Currently it is giving me "error: undeclared identifier `MethodName'" when I try to call a method of the parent object (the parent object is all defined in one unit, and the child all in another unit). I will try to simplify the code causing the problem down to a simple test case.
I tracked this down to a problem with my source - MW supports private, but only for variables, and does not support public, so the code looked like:
type o = object // public pub: integer; private priv: integer; // public procedure PubMethod; // private procedure PrivMethod; end;
GPC honours the private, and so the methods were all hidden from the child object.
Given the very poor level of implementation of private/public in Mac Pascals, I would doubt this is worth GPC bothering to be compatible with.
Enjoy, Peter.