Initial revision
[AROS-Contrib.git] / development / compilers / freepascal / compiler / psub.pas
blob1552203e7b16a2370128bdd107c0d2f57e380cda
2 $Id$
3 Copyright (c) 1998-2000 by Florian Klaempfl, Daniel Mantione
5 Does the parsing of the procedures/functions
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 ****************************************************************************
23 unit psub;
24 interface
26 uses
27 cobjects,
28 symconst,tokens,symtable;
30 const
31 pd_global = $1; { directive must be global }
32 pd_body = $2; { directive needs a body }
33 pd_implemen = $4; { directive can be used implementation section }
34 pd_interface = $8; { directive can be used interface section }
35 pd_object = $10; { directive can be used object declaration }
36 pd_procvar = $20; { directive can be used procvar declaration }
37 pd_notobject = $40;{ directive can not be used object declaration }
39 procedure compile_proc_body(const proc_names:Tstringcontainer;
40 make_global,parent_has_class:boolean);
41 procedure parse_proc_head(options:tproctypeoption);
42 procedure parse_proc_dec;
43 function is_proc_directive(tok:ttoken):boolean;
44 procedure parse_var_proc_directives(var sym : psym);
45 procedure parse_object_proc_directives(var sym : pprocsym);
46 procedure read_proc;
47 function check_identical_proc(var p : pprocdef) : boolean;
49 implementation
51 uses
52 globtype,systems,
53 strings,globals,verbose,files,
54 scanner,aasm,tree,types,
55 import,gendef,htypechk,
56 {$ifdef newcg}
57 cgbase,
58 {$else newcg}
59 hcodegen,temp_gen,
60 {$endif newcg}
61 pass_1,cpubase,cpuasm
62 {$ifndef NOPASS2}
63 ,pass_2
64 {$endif}
65 {$ifdef GDB}
66 ,gdb
67 {$endif GDB}
68 {$ifdef newcg}
69 {$ifndef NOOPT}
70 ,aopt
71 {$endif}
72 {$else}
73 {$ifdef i386}
74 ,tgeni386
75 ,cgai386
76 {$ifndef NOOPT}
77 ,aopt386
78 {$endif}
79 {$endif}
80 {$ifdef m68k}
81 ,tgen68k,cga68k
82 {$endif}
83 {$endif newcg}
84 { parser specific stuff }
85 ,pbase,ptype,pdecl,pexpr,pstatmnt
86 {$ifdef newcg}
87 ,tgcpu,convtree,cgobj,tgeni386 { for the new code generator tgeni386 is only a dummy }
88 {$endif newcg}
91 var
92 realname:string; { contains the real name of a procedure as it's typed }
95 procedure parse_proc_head(options:tproctypeoption);
96 var sp:stringid;
97 pd:Pprocdef;
98 paramoffset:longint;
99 sym:Psym;
100 hs:string;
101 st : psymtable;
102 overloaded_level:word;
103 storepos,procstartfilepos : tfileposinfo;
104 begin
105 { Save the position where this procedure really starts and set col to 1 which
106 looks nicer }
107 procstartfilepos:=tokenpos;
108 { procstartfilepos.column:=1; I do not agree here !!
109 lets keep excat position PM }
111 if (options=potype_operator) then
112 begin
113 sp:=overloaded_names[optoken];
114 realname:=sp;
116 else
117 begin
118 sp:=pattern;
119 realname:=orgpattern;
120 consume(_ID);
121 end;
123 { method ? }
124 if not(parse_only) and
125 (lexlevel=normal_function_level) and
126 try_to_consume(_POINT) then
127 begin
128 storepos:=tokenpos;
129 tokenpos:=procstartfilepos;
130 getsym(sp,true);
131 sym:=srsym;
132 tokenpos:=storepos;
133 { load proc name }
134 sp:=pattern;
135 realname:=orgpattern;
136 procstartfilepos:=tokenpos;
137 { qualifier is class name ? }
138 if (sym^.typ<>typesym) or
139 (ptypesym(sym)^.restype.def^.deftype<>objectdef) then
140 begin
141 Message(parser_e_class_id_expected);
142 aktprocsym:=nil;
143 consume(_ID);
145 else
146 begin
147 { used to allow private syms to be seen }
148 aktobjectdef:=pobjectdef(ptypesym(sym)^.restype.def);
149 procinfo^._class:=pobjectdef(ptypesym(sym)^.restype.def);
150 aktprocsym:=pprocsym(procinfo^._class^.symtable^.search(sp));
151 consume(_ID);
152 {The procedure has been found. So it is
153 a global one. Set the flags to mark this.}
154 procinfo^.flags:=procinfo^.flags or pi_is_global;
155 aktobjectdef:=nil;
156 { we solve this below }
157 if not(assigned(aktprocsym)) then
158 Message(parser_e_methode_id_expected);
159 end;
161 else
162 begin
163 { check for constructor/destructor which is not allowed here }
164 if (not parse_only) and
165 (options in [potype_constructor,potype_destructor]) then
166 Message(parser_e_constructors_always_objects);
168 tokenpos:=procstartfilepos;
169 aktprocsym:=pprocsym(symtablestack^.search(sp));
171 if not(parse_only) then
172 begin
173 {The procedure we prepare for is in the implementation
174 part of the unit we compile. It is also possible that we
175 are compiling a program, which is also some kind of
176 implementaion part.
178 We need to find out if the procedure is global. If it is
179 global, it is in the global symtable.}
180 if not assigned(aktprocsym) and
181 (symtablestack^.symtabletype=staticsymtable) then
182 begin
183 {Search the procedure in the global symtable.}
184 aktprocsym:=Pprocsym(search_a_symtable(sp,globalsymtable));
185 if assigned(aktprocsym) then
186 begin
187 {Check if it is a procedure.}
188 if aktprocsym^.typ<>procsym then
189 DuplicateSym(aktprocsym);
190 {The procedure has been found. So it is
191 a global one. Set the flags to mark this.}
192 procinfo^.flags:=procinfo^.flags or pi_is_global;
193 end;
194 end;
195 end;
196 end;
198 { Create the mangledname }
199 {$ifndef UseNiceNames}
200 if assigned(procinfo^._class) then
201 begin
202 if (pos('_$$_',procprefix)=0) then
203 hs:=procprefix+'_$$_'+procinfo^._class^.objname^+'_$$_'+sp
204 else
205 hs:=procprefix+'_$'+sp;
207 else
208 begin
209 if lexlevel=normal_function_level then
210 hs:=procprefix+'_'+sp
211 else
212 hs:=procprefix+'_$'+sp;
213 end;
214 {$else UseNiceNames}
215 if assigned(procinfo^._class) then
216 begin
217 if (pos('_5Class_',procprefix)=0) then
218 hs:=procprefix+'_5Class_'+procinfo^._class^.name^+'_'+tostr(length(sp))+sp
219 else
220 hs:=procprefix+'_'+tostr(length(sp))+sp;
222 else
223 begin
224 if lexlevel=normal_function_level then
225 hs:=procprefix+'_'+tostr(length(sp))+sp
226 else
227 hs:=lowercase(procprefix)+'_'+tostr(length(sp))+sp;
228 end;
229 {$endif UseNiceNames}
231 if assigned(aktprocsym) then
232 begin
233 { Check if overloaded is a procsym, we use a different error message
234 for tp7 so it looks more compatible }
235 if aktprocsym^.typ<>procsym then
236 begin
237 if (m_fpc in aktmodeswitches) then
238 Message1(parser_e_overloaded_no_procedure,aktprocsym^.name)
239 else
240 DuplicateSym(aktprocsym);
241 { try to recover by creating a new aktprocsym }
242 tokenpos:=procstartfilepos;
243 aktprocsym:=new(pprocsym,init(sp));
244 end;
246 else
247 begin
248 { create a new procsym and set the real filepos }
249 tokenpos:=procstartfilepos;
250 aktprocsym:=new(pprocsym,init(sp));
251 { for operator we have only one definition for each overloaded
252 operation }
253 if (options=potype_operator) then
254 begin
255 { the only problem is that nextoverloaded might not be in a unit
256 known for the unit itself }
257 { not anymore PM }
258 if assigned(overloaded_operators[optoken]) then
259 aktprocsym^.definition:=overloaded_operators[optoken]^.definition;
260 {$ifndef DONOTCHAINOPERATORS}
261 overloaded_operators[optoken]:=aktprocsym;
262 {$endif DONOTCHAINOPERATORS}
263 end;
264 symtablestack^.insert(aktprocsym);
265 end;
267 st:=symtablestack;
268 pd:=new(pprocdef,init);
269 pd^.symtablelevel:=symtablestack^.symtablelevel;
271 if assigned(procinfo^._class) then
272 pd^._class := procinfo^._class;
274 { set the options from the caller (podestructor or poconstructor) }
275 pd^.proctypeoption:=options;
277 { calculate the offset of the parameters }
278 paramoffset:=8;
280 { calculate frame pointer offset }
281 if lexlevel>normal_function_level then
282 begin
283 procinfo^.framepointer_offset:=paramoffset;
284 inc(paramoffset,target_os.size_of_pointer);
285 { this is needed to get correct framepointer push for local
286 forward functions !! }
287 pd^.parast^.symtablelevel:=lexlevel;
288 end;
290 if assigned (procinfo^._Class) and
291 not(procinfo^._Class^.is_class) and
292 (pd^.proctypeoption in [potype_constructor,potype_destructor]) then
293 inc(paramoffset,target_os.size_of_pointer);
295 { self pointer offset }
296 { self isn't pushed in nested procedure of methods }
297 if assigned(procinfo^._class) and (lexlevel=normal_function_level) then
298 begin
299 procinfo^.selfpointer_offset:=paramoffset;
300 if assigned(aktprocsym^.definition) and
301 not(po_containsself in aktprocsym^.definition^.procoptions) then
302 inc(paramoffset,target_os.size_of_pointer);
303 end;
305 { con/-destructor flag ? }
306 if assigned (procinfo^._Class) and
307 procinfo^._class^.is_class and
308 (pd^.proctypeoption in [potype_destructor,potype_constructor]) then
309 inc(paramoffset,target_os.size_of_pointer);
311 procinfo^.para_offset:=paramoffset;
313 pd^.parast^.datasize:=0;
315 pd^.nextoverloaded:=aktprocsym^.definition;
316 aktprocsym^.definition:=pd;
317 { this is probably obsolete now PM }
318 aktprocsym^.definition^.fileinfo:=procstartfilepos;
319 aktprocsym^.definition^.setmangledname(hs);
320 aktprocsym^.definition^.procsym:=aktprocsym;
322 if not parse_only then
323 begin
324 overloaded_level:=0;
325 { we need another procprefix !!! }
326 { count, but only those in the same unit !!}
327 while assigned(pd) and
328 (pd^.owner^.symtabletype in [globalsymtable,staticsymtable]) do
329 begin
330 { only count already implemented functions }
331 if not(pd^.forwarddef) then
332 inc(overloaded_level);
333 pd:=pd^.nextoverloaded;
334 end;
335 if overloaded_level>0 then
336 procprefix:=hs+'$'+tostr(overloaded_level)+'$'
337 else
338 procprefix:=hs+'$';
339 end;
341 { this must also be inserted in the right symtable !! PM }
342 { otherwise we get subbtle problems with
343 definitions of args defs in staticsymtable for
344 implementation of a global method }
345 if token=_LKLAMMER then
346 parameter_dec(aktprocsym^.definition);
348 { so we only restore the symtable now }
349 symtablestack:=st;
350 if (options=potype_operator) then
351 overloaded_operators[optoken]:=aktprocsym;
352 end;
355 procedure parse_proc_dec;
357 hs : string;
358 isclassmethod : boolean;
359 begin
360 inc(lexlevel);
361 { read class method }
362 if token=_CLASS then
363 begin
364 consume(_CLASS);
365 isclassmethod:=true;
367 else
368 isclassmethod:=false;
369 case token of
370 _FUNCTION : begin
371 consume(_FUNCTION);
372 parse_proc_head(potype_none);
373 if token<>_COLON then
374 begin
375 if not(aktprocsym^.definition^.forwarddef) or
376 (m_repeat_forward in aktmodeswitches) then
377 begin
378 consume(_COLON);
379 consume_all_until(_SEMICOLON);
380 end;
382 else
383 begin
384 consume(_COLON);
385 inc(testcurobject);
386 single_type(aktprocsym^.definition^.rettype,hs,false);
387 aktprocsym^.definition^.test_if_fpu_result;
388 dec(testcurobject);
389 end;
390 end;
391 _PROCEDURE : begin
392 consume(_PROCEDURE);
393 parse_proc_head(potype_none);
394 aktprocsym^.definition^.rettype.def:=voiddef;
395 end;
396 _CONSTRUCTOR : begin
397 consume(_CONSTRUCTOR);
398 parse_proc_head(potype_constructor);
399 if assigned(procinfo^._class) and
400 procinfo^._class^.is_class then
401 begin
402 { CLASS constructors return the created instance }
403 aktprocsym^.definition^.rettype.def:=procinfo^._class;
405 else
406 begin
407 { OBJECT constructors return a boolean }
408 {$IfDef GDB}
409 { GDB doesn't like unnamed types !}
410 aktprocsym^.definition^.rettype.def:=globaldef('boolean');
411 {$else GDB}
412 aktprocsym^.definition^.rettype.def:=new(porddef,init(bool8bit,0,1));
413 {$Endif GDB}
414 end;
415 end;
416 _DESTRUCTOR : begin
417 consume(_DESTRUCTOR);
418 parse_proc_head(potype_destructor);
419 aktprocsym^.definition^.rettype.def:=voiddef;
420 end;
421 _OPERATOR : begin
422 if lexlevel>normal_function_level then
423 Message(parser_e_no_local_operator);
424 consume(_OPERATOR);
425 if not(token in [_PLUS..last_overloaded]) then
426 Message(parser_e_overload_operator_failed);
427 optoken:=token;
428 consume(Token);
429 procinfo^.flags:=procinfo^.flags or pi_operator;
430 parse_proc_head(potype_operator);
431 if token<>_ID then
432 begin
433 opsym:=nil;
434 if not(m_result in aktmodeswitches) then
435 consume(_ID);
437 else
438 begin
439 opsym:=new(pvarsym,initdef(pattern,voiddef));
440 consume(_ID);
441 end;
442 if not try_to_consume(_COLON) then
443 begin
444 consume(_COLON);
445 aktprocsym^.definition^.rettype.def:=generrordef;
446 consume_all_until(_SEMICOLON);
448 else
449 begin
450 single_type(aktprocsym^.definition^.rettype,hs,false);
451 aktprocsym^.definition^.test_if_fpu_result;
452 if (optoken in [_EQUAL,_GT,_LT,_GTE,_LTE]) and
453 ((aktprocsym^.definition^.rettype.def^.deftype<>
454 orddef) or (porddef(aktprocsym^.definition^.
455 rettype.def)^.typ<>bool8bit)) then
456 Message(parser_e_comparative_operator_return_boolean);
457 if assigned(opsym) then
458 opsym^.vartype.def:=aktprocsym^.definition^.rettype.def;
459 { We need to add the return type in the mangledname
460 to allow overloading with just different results !! (PM) }
461 aktprocsym^.definition^.setmangledname(
462 aktprocsym^.definition^.mangledname+'$$'+hs);
463 if (optoken=_ASSIGNMENT) and
464 is_equal(aktprocsym^.definition^.rettype.def,
465 pvarsym(aktprocsym^.definition^.parast^.symindex^.first)^.vartype.def) then
466 message(parser_e_no_such_assignment)
467 else if not isoperatoracceptable(aktprocsym^.definition,optoken) then
468 Message(parser_e_overload_impossible);
469 end;
470 end;
471 end;
472 if isclassmethod and
473 assigned(aktprocsym) then
474 {$ifdef INCLUDEOK}
475 include(aktprocsym^.definition^.procoptions,po_classmethod);
476 {$else}
477 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_classmethod];
478 {$endif}
479 { support procedure proc;stdcall export; in Delphi mode only }
480 if not((m_delphi in aktmodeswitches) and
481 is_proc_directive(token)) then
482 consume(_SEMICOLON);
483 dec(lexlevel);
484 end;
487 {****************************************************************************
488 Procedure directive handlers
489 ****************************************************************************}
491 {$ifdef tp}
492 {$F+}
493 {$endif}
495 procedure pd_far(const procnames:Tstringcontainer);
496 begin
497 Message(parser_w_proc_far_ignored);
498 end;
500 procedure pd_near(const procnames:Tstringcontainer);
501 begin
502 Message(parser_w_proc_near_ignored);
503 end;
505 procedure pd_export(const procnames:Tstringcontainer);
506 begin
507 if assigned(procinfo^._class) then
508 Message(parser_e_methods_dont_be_export);
509 if lexlevel<>normal_function_level then
510 Message(parser_e_dont_nest_export);
511 { only os/2 needs this }
512 if target_info.target=target_i386_os2 then
513 begin
514 procnames.insert(realname);
515 procinfo^.exported:=true;
516 if cs_link_deffile in aktglobalswitches then
517 deffile.AddExport(aktprocsym^.definition^.mangledname);
518 end;
519 end;
521 procedure pd_inline(const procnames:Tstringcontainer);
522 begin
523 if not(cs_support_inline in aktmoduleswitches) then
524 Message(parser_e_proc_inline_not_supported);
525 end;
527 procedure pd_forward(const procnames:Tstringcontainer);
528 begin
529 aktprocsym^.definition^.forwarddef:=true;
530 end;
532 procedure pd_stdcall(const procnames:Tstringcontainer);
533 begin
534 end;
536 procedure pd_safecall(const procnames:Tstringcontainer);
537 begin
538 end;
540 procedure pd_alias(const procnames:Tstringcontainer);
541 begin
542 consume(_COLON);
543 procnames.insert(get_stringconst);
544 end;
546 procedure pd_asmname(const procnames:Tstringcontainer);
547 begin
548 aktprocsym^.definition^.setmangledname(target_os.Cprefix+pattern);
549 if token=_CCHAR then
550 consume(_CCHAR)
551 else
552 consume(_CSTRING);
553 { we don't need anything else }
554 aktprocsym^.definition^.forwarddef:=false;
555 end;
557 procedure pd_intern(const procnames:Tstringcontainer);
558 begin
559 consume(_COLON);
560 aktprocsym^.definition^.extnumber:=get_intconst;
561 end;
563 procedure pd_interrupt(const procnames:Tstringcontainer);
564 begin
565 {$ifndef i386}
566 Message(parser_w_proc_interrupt_ignored);
567 {$else i386}
568 if lexlevel<>normal_function_level then
569 Message(parser_e_dont_nest_interrupt);
570 {$endif i386}
571 end;
573 procedure pd_system(const procnames:Tstringcontainer);
574 begin
575 aktprocsym^.definition^.setmangledname(realname);
576 end;
578 procedure pd_abstract(const procnames:Tstringcontainer);
579 begin
580 if (po_virtualmethod in aktprocsym^.definition^.procoptions) then
581 {$ifdef INCLUDEOK}
582 include(aktprocsym^.definition^.procoptions,po_abstractmethod)
583 {$else}
584 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_abstractmethod]
585 {$endif}
586 else
587 Message(parser_e_only_virtual_methods_abstract);
588 { the method is defined }
589 aktprocsym^.definition^.forwarddef:=false;
590 end;
592 procedure pd_virtual(const procnames:Tstringcontainer);
593 {$ifdef WITHDMT}
595 pt : ptree;
596 {$endif WITHDMT}
597 begin
598 if (aktprocsym^.definition^.proctypeoption=potype_constructor) and
599 not(aktprocsym^.definition^._class^.is_class) then
600 Message(parser_e_constructor_cannot_be_not_virtual);
601 {$ifdef WITHDMT}
602 if not(aktprocsym^.definition^._class^.is_class) and
603 (token<>_SEMICOLON) then
604 begin
605 { any type of parameter is allowed here! }
607 pt:=comp_expr(true);
608 do_firstpass(pt);
609 if is_constintnode(pt) then
610 begin
611 include(aktprocsym^.definition^.procoptions,po_msgint);
612 aktprocsym^.definition^.messageinf.i:=pt^.value;
614 else
615 Message(parser_e_ill_msg_expr);
616 disposetree(pt);
617 end;
618 {$endif WITHDMT}
619 end;
621 procedure pd_static(const procnames:Tstringcontainer);
622 begin
623 if (cs_static_keyword in aktmoduleswitches) then
624 begin
625 {$ifdef INCLUDEOK}
626 include(aktprocsym^.symoptions,sp_static);
627 include(aktprocsym^.definition^.procoptions,po_staticmethod);
628 {$else}
629 aktprocsym^.symoptions:=aktprocsym^.symoptions+[sp_static];
630 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_staticmethod];
631 {$endif}
632 end;
633 end;
635 procedure pd_override(const procnames:Tstringcontainer);
636 begin
637 if not(aktprocsym^.definition^._class^.is_class) then
638 Message(parser_e_no_object_override);
639 end;
641 procedure pd_overload(const procnames:Tstringcontainer);
642 begin
643 end;
645 procedure pd_message(const procnames:Tstringcontainer);
647 pt : ptree;
648 begin
649 { check parameter type }
650 if not(po_containsself in aktprocsym^.definition^.procoptions) and
651 ((aktprocsym^.definition^.para^.count<>1) or
652 (pparaitem(aktprocsym^.definition^.para^.first)^.paratyp<>vs_var)) then
653 Message(parser_e_ill_msg_param);
654 pt:=comp_expr(true);
655 do_firstpass(pt);
656 if pt^.treetype=stringconstn then
657 begin
658 {$ifdef INCLUDEOK}
659 include(aktprocsym^.definition^.procoptions,po_msgstr);
660 {$else}
661 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_msgstr];
662 {$endif}
663 aktprocsym^.definition^.messageinf.str:=strnew(pt^.value_str);
665 else
666 if is_constintnode(pt) then
667 begin
668 {$ifdef INCLUDEOK}
669 include(aktprocsym^.definition^.procoptions,po_msgint);
670 {$else}
671 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+[po_msgint];
672 {$endif}
673 aktprocsym^.definition^.messageinf.i:=pt^.value;
675 else
676 Message(parser_e_ill_msg_expr);
677 disposetree(pt);
678 end;
681 procedure resetvaluepara(p:pnamedindexobject);{$ifndef FPC}far;{$endif}
682 begin
683 if psym(p)^.typ=varsym then
684 with pvarsym(p)^ do
685 if copy(name,1,3)='val' then
686 aktprocsym^.definition^.parast^.symsearch^.rename(name,copy(name,4,length(name)));
687 end;
690 procedure pd_cdecl(const procnames:Tstringcontainer);
691 begin
692 if aktprocsym^.definition^.deftype<>procvardef then
693 aktprocsym^.definition^.setmangledname(target_os.Cprefix+realname);
694 { do not copy on local !! }
695 if (aktprocsym^.definition^.deftype=procdef) and
696 assigned(aktprocsym^.definition^.parast) then
697 aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}resetvaluepara);
698 end;
701 procedure pd_pascal(const procnames:Tstringcontainer);
702 var st,parast : psymtable;
703 lastps,ps : psym;
704 begin
705 new(st,init(parasymtable));
706 parast:=aktprocsym^.definition^.parast;
707 lastps:=nil;
708 while assigned(parast^.symindex^.first) and (lastps<>psym(parast^.symindex^.first)) do
709 begin
710 ps:=psym(parast^.symindex^.first);
711 while assigned(ps^.indexnext) and (psym(ps^.indexnext)<>lastps) do
712 ps:=psym(ps^.indexnext);
713 ps^.owner:=st;
714 { recalculate the corrected offset }
715 { the really_insert_in_data procedure
716 for parasymtable should only calculateoffset PM }
717 ps^.insert_in_data;
718 { reset the owner correctly }
719 ps^.owner:=parast;
720 lastps:=ps;
721 end;
722 end;
725 procedure pd_register(const procnames:Tstringcontainer);
726 begin
727 Message1(parser_w_proc_directive_ignored,'REGISTER');
728 end;
731 procedure pd_reintroduce(const procnames:Tstringcontainer);
732 begin
733 Message1(parser_w_proc_directive_ignored,'REINTRODUCE');
734 end;
737 procedure pd_syscall(const procnames:Tstringcontainer);
738 begin
739 aktprocsym^.definition^.forwarddef:=false;
740 aktprocsym^.definition^.extnumber:=get_intconst;
741 end;
744 procedure pd_external(const procnames:Tstringcontainer);
746 If import_dll=nil the procedure is assumed to be in another
747 object file. In that object file it should have the name to
748 which import_name is pointing to. Otherwise, the procedure is
749 assumed to be in the DLL to which import_dll is pointing to. In
750 that case either import_nr<>0 or import_name<>nil is true, so
751 the procedure is either imported by number or by name. (DM)
754 import_dll,
755 import_name : string;
756 import_nr : word;
757 begin
758 aktprocsym^.definition^.forwarddef:=false;
759 { If the procedure should be imported from a DLL, a constant string follows.
760 This isn't really correct, an contant string expression follows
761 so we check if an semicolon follows, else a string constant have to
762 follow (FK) }
763 import_nr:=0;
764 import_name:='';
765 if not(token=_SEMICOLON) and not(idtoken=_NAME) then
766 begin
767 import_dll:=get_stringconst;
768 if (idtoken=_NAME) then
769 begin
770 consume(_NAME);
771 import_name:=get_stringconst;
772 end;
773 if (idtoken=_INDEX) then
774 begin
775 {After the word index follows the index number in the DLL.}
776 consume(_INDEX);
777 import_nr:=get_intconst;
778 end;
779 if (import_nr=0) and (import_name='') then
780 {if (aktprocsym^.definition^.options and pocdecl)<>0 then
781 import_name:=aktprocsym^.definition^.mangledname
782 else
783 Message(parser_w_empty_import_name);}
784 { this should work both for win32 and Linux !! PM }
785 import_name:=realname;
786 if not(current_module^.uses_imports) then
787 begin
788 current_module^.uses_imports:=true;
789 importlib^.preparelib(current_module^.modulename^);
790 end;
791 if not(m_repeat_forward in aktmodeswitches) then
792 begin
793 { we can only have one overloaded here ! }
794 if assigned(aktprocsym^.definition^.nextoverloaded) then
795 importlib^.importprocedure(aktprocsym^.definition^.nextoverloaded^.mangledname,
796 import_dll,import_nr,import_name)
797 else
798 importlib^.importprocedure(aktprocsym^.mangledname,import_dll,import_nr,import_name);
800 else
801 importlib^.importprocedure(aktprocsym^.mangledname,import_dll,import_nr,import_name);
803 else
804 begin
805 if (idtoken=_NAME) then
806 begin
807 consume(_NAME);
808 import_name:=get_stringconst;
809 aktprocsym^.definition^.setmangledname(import_name);
811 else
812 begin
813 { external shouldn't override the cdecl/system name }
814 if not (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
815 aktprocsym^.definition^.setmangledname(aktprocsym^.name);
816 end;
817 end;
818 end;
820 {$ifdef TP}
821 {$F-}
822 {$endif}
824 {$ifdef Delphi}
825 {$define TP}
826 {$endif Delphi}
828 {const
829 namelength=15;}
830 type
831 pd_handler=procedure(const procnames:Tstringcontainer);
832 proc_dir_rec=record
833 idtok : ttoken;
834 pd_flags : longint;
835 handler : pd_handler;
836 pocall : tproccalloptions;
837 pooption : tprocoptions;
838 mutexclpocall : tproccalloptions;
839 mutexclpotype : tproctypeoptions;
840 mutexclpo : tprocoptions;
841 end;
842 const
843 {Should contain the number of procedure directives we support.}
844 num_proc_directives=31;
845 proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
848 idtok:_ABSTRACT;
849 pd_flags : pd_interface+pd_object;
850 handler : {$ifndef TP}@{$endif}pd_abstract;
851 pocall : [];
852 pooption : [po_abstractmethod];
853 mutexclpocall : [pocall_internproc,pocall_inline];
854 mutexclpotype : [potype_constructor,potype_destructor];
855 mutexclpo : [po_exports,po_interrupt,po_external]
857 idtok:_ALIAS;
858 pd_flags : pd_implemen+pd_body;
859 handler : {$ifndef TP}@{$endif}pd_alias;
860 pocall : [];
861 pooption : [];
862 mutexclpocall : [pocall_inline];
863 mutexclpotype : [];
864 mutexclpo : [po_external]
866 idtok:_ASMNAME;
867 pd_flags : pd_interface+pd_implemen;
868 handler : {$ifndef TP}@{$endif}pd_asmname;
869 pocall : [pocall_cdecl,pocall_clearstack];
870 pooption : [po_external];
871 mutexclpocall : [pocall_internproc];
872 mutexclpotype : [];
873 mutexclpo : [po_external]
875 idtok:_ASSEMBLER;
876 pd_flags : pd_implemen+pd_body;
877 handler : nil;
878 pocall : [];
879 pooption : [po_assembler];
880 mutexclpocall : [];
881 mutexclpotype : [];
882 mutexclpo : [po_external]
884 idtok:_CDECL;
885 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
886 handler : {$ifndef TP}@{$endif}pd_cdecl;
887 pocall : [pocall_cdecl,pocall_clearstack];
888 pooption : [po_savestdregs];
889 mutexclpocall : [pocall_internproc,pocall_leftright,pocall_inline];
890 mutexclpotype : [];
891 mutexclpo : [po_assembler,po_external]
893 idtok:_DYNAMIC;
894 pd_flags : pd_interface+pd_object;
895 handler : {$ifndef TP}@{$endif}pd_virtual;
896 pocall : [];
897 pooption : [po_virtualmethod];
898 mutexclpocall : [pocall_internproc,pocall_inline];
899 mutexclpotype : [];
900 mutexclpo : [po_exports,po_interrupt,po_external]
902 idtok:_EXPORT;
903 pd_flags : pd_body+pd_global+pd_interface+pd_implemen{??};
904 handler : {$ifndef TP}@{$endif}pd_export;
905 pocall : [];
906 pooption : [po_exports];
907 mutexclpocall : [pocall_internproc,pocall_inline];
908 mutexclpotype : [];
909 mutexclpo : [po_external,po_interrupt]
911 idtok:_EXTERNAL;
912 pd_flags : pd_implemen+pd_interface;
913 handler : {$ifndef TP}@{$endif}pd_external;
914 pocall : [];
915 pooption : [po_external];
916 mutexclpocall : [pocall_internproc,pocall_inline,pocall_palmossyscall];
917 mutexclpotype : [];
918 mutexclpo : [po_exports,po_interrupt,po_assembler]
920 idtok:_FAR;
921 pd_flags : pd_implemen+pd_body+pd_interface+pd_procvar;
922 handler : {$ifndef TP}@{$endif}pd_far;
923 pocall : [];
924 pooption : [];
925 mutexclpocall : [pocall_internproc,pocall_inline];
926 mutexclpotype : [];
927 mutexclpo : []
929 idtok:_FORWARD;
930 pd_flags : pd_implemen;
931 handler : {$ifndef TP}@{$endif}pd_forward;
932 pocall : [];
933 pooption : [];
934 mutexclpocall : [pocall_internproc,pocall_inline];
935 mutexclpotype : [];
936 mutexclpo : [po_external]
938 idtok:_INLINE;
939 pd_flags : pd_implemen+pd_body;
940 handler : {$ifndef TP}@{$endif}pd_inline;
941 pocall : [pocall_inline];
942 pooption : [];
943 mutexclpocall : [pocall_internproc];
944 mutexclpotype : [potype_constructor,potype_destructor];
945 mutexclpo : [po_exports,po_external,po_interrupt]
947 idtok:_INTERNCONST;
948 pd_flags : pd_implemen+pd_body;
949 handler : {$ifndef TP}@{$endif}pd_intern;
950 pocall : [pocall_internconst];
951 pooption : [];
952 mutexclpocall : [];
953 mutexclpotype : [potype_operator];
954 mutexclpo : []
956 idtok:_INTERNPROC;
957 pd_flags : pd_implemen;
958 handler : {$ifndef TP}@{$endif}pd_intern;
959 pocall : [pocall_internproc];
960 pooption : [];
961 mutexclpocall : [pocall_inline,pocall_clearstack,pocall_leftright,pocall_cdecl];
962 mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
963 mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck]
965 idtok:_INTERRUPT;
966 pd_flags : pd_implemen+pd_body;
967 handler : {$ifndef TP}@{$endif}pd_interrupt;
968 pocall : [];
969 pooption : [po_interrupt];
970 mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_clearstack,pocall_leftright,pocall_inline];
971 mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
972 mutexclpo : [po_external]
974 idtok:_IOCHECK;
975 pd_flags : pd_implemen+pd_body;
976 handler : nil;
977 pocall : [];
978 pooption : [po_iocheck];
979 mutexclpocall : [pocall_internproc];
980 mutexclpotype : [];
981 mutexclpo : [po_external]
983 idtok:_MESSAGE;
984 pd_flags : pd_interface+pd_object;
985 handler : {$ifndef TP}@{$endif}pd_message;
986 pocall : [];
987 pooption : []; { can be po_msgstr or po_msgint }
988 mutexclpocall : [pocall_inline,pocall_internproc];
989 mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
990 mutexclpo : [po_interrupt,po_external]
992 idtok:_NEAR;
993 pd_flags : pd_implemen+pd_body+pd_procvar;
994 handler : {$ifndef TP}@{$endif}pd_near;
995 pocall : [];
996 pooption : [];
997 mutexclpocall : [pocall_internproc];
998 mutexclpotype : [];
999 mutexclpo : []
1001 idtok:_OVERLOAD;
1002 pd_flags : pd_implemen+pd_interface+pd_body;
1003 handler : {$ifndef TP}@{$endif}pd_overload;
1004 pocall : [];
1005 pooption : [po_overload];
1006 mutexclpocall : [pocall_internproc];
1007 mutexclpotype : [];
1008 mutexclpo : []
1010 idtok:_OVERRIDE;
1011 pd_flags : pd_interface+pd_object;
1012 handler : {$ifndef TP}@{$endif}pd_override;
1013 pocall : [];
1014 pooption : [po_overridingmethod,po_virtualmethod];
1015 mutexclpocall : [pocall_inline,pocall_internproc];
1016 mutexclpotype : [];
1017 mutexclpo : [po_exports,po_external,po_interrupt]
1019 idtok:_PASCAL;
1020 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1021 handler : {$ifndef TP}@{$endif}pd_pascal;
1022 pocall : [pocall_leftright];
1023 pooption : [];
1024 mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_internproc,
1025 pocall_stdcall,pocall_clearstack,pocall_inline];
1026 mutexclpotype : [];
1027 mutexclpo : [po_external]
1029 idtok:_POPSTACK;
1030 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1031 handler : nil;
1032 pocall : [pocall_clearstack];
1033 pooption : [];
1034 mutexclpocall : [pocall_inline,pocall_internproc];
1035 mutexclpotype : [];
1036 mutexclpo : [po_assembler,po_external]
1038 idtok:_PUBLIC;
1039 pd_flags : pd_implemen+pd_body+pd_global+pd_notobject;
1040 handler : nil;
1041 pocall : [];
1042 pooption : [];
1043 mutexclpocall : [pocall_internproc,pocall_inline];
1044 mutexclpotype : [];
1045 mutexclpo : [po_external]
1047 idtok:_REGISTER;
1048 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1049 handler : {$ifndef TP}@{$endif}pd_register;
1050 pocall : [pocall_register];
1051 pooption : [];
1052 mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_internproc];
1053 mutexclpotype : [];
1054 mutexclpo : [po_external]
1056 idtok:_REINTRODUCE;
1057 pd_flags : pd_interface+pd_object;
1058 handler : {$ifndef TP}@{$endif}pd_reintroduce;
1059 pocall : [];
1060 pooption : [];
1061 mutexclpocall : [];
1062 mutexclpotype : [];
1063 mutexclpo : []
1065 idtok:_SAFECALL;
1066 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1067 handler : {$ifndef TP}@{$endif}pd_safecall;
1068 pocall : [pocall_safecall];
1069 pooption : [po_savestdregs];
1070 mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_internproc,pocall_inline];
1071 mutexclpotype : [];
1072 mutexclpo : [po_external]
1074 idtok:_SAVEREGISTERS;
1075 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1076 handler : nil;
1077 pocall : [];
1078 pooption : [po_saveregisters];
1079 mutexclpocall : [pocall_internproc];
1080 mutexclpotype : [];
1081 mutexclpo : [po_external]
1083 idtok:_STATIC;
1084 pd_flags : pd_interface+pd_object;
1085 handler : {$ifndef TP}@{$endif}pd_static;
1086 pocall : [];
1087 pooption : [po_staticmethod];
1088 mutexclpocall : [pocall_inline,pocall_internproc];
1089 mutexclpotype : [potype_constructor,potype_destructor];
1090 mutexclpo : [po_external,po_interrupt,po_exports]
1092 idtok:_STDCALL;
1093 pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
1094 handler : {$ifndef TP}@{$endif}pd_stdcall;
1095 pocall : [pocall_stdcall];
1096 pooption : [po_savestdregs];
1097 mutexclpocall : [pocall_leftright,pocall_cdecl,pocall_inline,pocall_internproc];
1098 mutexclpotype : [];
1099 mutexclpo : [po_external]
1101 idtok:_SYSCALL;
1102 pd_flags : pd_interface;
1103 handler : {$ifndef TP}@{$endif}pd_syscall;
1104 pocall : [pocall_palmossyscall];
1105 pooption : [];
1106 mutexclpocall : [pocall_cdecl,pocall_inline,pocall_internproc];
1107 mutexclpotype : [];
1108 mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
1110 idtok:_SYSTEM;
1111 pd_flags : pd_implemen;
1112 handler : {$ifndef TP}@{$endif}pd_system;
1113 pocall : [pocall_clearstack];
1114 pooption : [];
1115 mutexclpocall : [pocall_leftright,pocall_inline,pocall_internproc];
1116 mutexclpotype : [];
1117 mutexclpo : [po_external,po_assembler,po_interrupt]
1119 idtok:_VIRTUAL;
1120 pd_flags : pd_interface+pd_object;
1121 handler : {$ifndef TP}@{$endif}pd_virtual;
1122 pocall : [];
1123 pooption : [po_virtualmethod];
1124 mutexclpocall : [pocall_inline,pocall_internproc];
1125 mutexclpotype : [];
1126 mutexclpo : [po_external,po_interrupt,po_exports]
1131 function is_proc_directive(tok:ttoken):boolean;
1133 i : longint;
1134 begin
1135 is_proc_directive:=false;
1136 for i:=1 to num_proc_directives do
1137 if proc_direcdata[i].idtok=idtoken then
1138 begin
1139 is_proc_directive:=true;
1140 exit;
1141 end;
1142 end;
1145 function parse_proc_direc(const proc_names:Tstringcontainer;var pdflags:word):boolean;
1147 Parse the procedure directive, returns true if a correct directive is found
1150 p : longint;
1151 found : boolean;
1152 name : string;
1153 begin
1154 parse_proc_direc:=false;
1155 name:=pattern;
1156 found:=false;
1157 for p:=1 to num_proc_directives do
1158 if proc_direcdata[p].idtok=idtoken then
1159 begin
1160 found:=true;
1161 break;
1162 end;
1164 { Check if the procedure directive is known }
1165 if not found then
1166 begin
1167 { parsing a procvar type the name can be any
1168 next variable !! }
1169 if (pdflags and (pd_procvar or pd_object))=0 then
1170 Message1(parser_w_unknown_proc_directive_ignored,name);
1171 exit;
1172 end;
1174 { static needs a special treatment }
1175 if (idtoken=_STATIC) and not (cs_static_keyword in aktmoduleswitches) then
1176 exit;
1178 { Conflicts between directives ? }
1179 if (aktprocsym^.definition^.proctypeoption in proc_direcdata[p].mutexclpotype) or
1180 ((aktprocsym^.definition^.proccalloptions*proc_direcdata[p].mutexclpocall)<>[]) or
1181 ((aktprocsym^.definition^.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
1182 begin
1183 Message1(parser_e_proc_dir_conflict,name);
1184 exit;
1185 end;
1187 { Check if the directive is only for objects }
1188 if ((proc_direcdata[p].pd_flags and pd_object)<>0) and
1189 not assigned(aktprocsym^.definition^._class) then
1190 begin
1191 exit;
1192 end;
1193 { check if method and directive not for object public }
1194 if ((proc_direcdata[p].pd_flags and pd_notobject)<>0) and
1195 assigned(aktprocsym^.definition^._class) then
1196 begin
1197 exit;
1198 end;
1200 { consume directive, and turn flag on }
1201 consume(token);
1202 parse_proc_direc:=true;
1204 { Check the pd_flags if the directive should be allowed }
1205 if ((pdflags and pd_interface)<>0) and
1206 ((proc_direcdata[p].pd_flags and pd_interface)=0) then
1207 begin
1208 Message1(parser_e_proc_dir_not_allowed_in_interface,name);
1209 exit;
1210 end;
1211 if ((pdflags and pd_implemen)<>0) and
1212 ((proc_direcdata[p].pd_flags and pd_implemen)=0) then
1213 begin
1214 Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
1215 exit;
1216 end;
1217 if ((pdflags and pd_procvar)<>0) and
1218 ((proc_direcdata[p].pd_flags and pd_procvar)=0) then
1219 begin
1220 Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
1221 exit;
1222 end;
1224 { Return the new pd_flags }
1225 if (proc_direcdata[p].pd_flags and pd_body)=0 then
1226 pdflags:=pdflags and (not pd_body);
1227 if (proc_direcdata[p].pd_flags and pd_global)<>0 then
1228 pdflags:=pdflags or pd_global;
1230 { Add the correct flag }
1231 aktprocsym^.definition^.proccalloptions:=aktprocsym^.definition^.proccalloptions+proc_direcdata[p].pocall;
1232 aktprocsym^.definition^.procoptions:=aktprocsym^.definition^.procoptions+proc_direcdata[p].pooption;
1234 { Adjust positions of args for cdecl or stdcall }
1235 if (aktprocsym^.definition^.deftype=procdef) and
1236 (([pocall_cdecl,pocall_stdcall]*aktprocsym^.definition^.proccalloptions)<>[]) then
1237 aktprocsym^.definition^.parast^.set_alignment(target_os.size_of_longint);
1239 { Call the handler }
1240 if pointer({$ifndef FPC}@{$endif}proc_direcdata[p].handler)<>nil then
1241 proc_direcdata[p].handler(proc_names);
1242 end;
1244 {***************************************************************************}
1246 function check_identical_proc(var p : pprocdef) : boolean;
1248 Search for idendical definitions,
1249 if there is a forward, then kill this.
1251 Returns the result of the forward check.
1253 Removed from unter_dec to keep the source readable
1256 hd,pd : Pprocdef;
1257 storeparast : psymtable;
1258 ad,fd : psym;
1259 s : string;
1260 begin
1261 check_identical_proc:=false;
1262 p:=nil;
1263 pd:=aktprocsym^.definition;
1264 if assigned(pd) then
1265 begin
1266 { Is there an overload/forward ? }
1267 if assigned(pd^.nextoverloaded) then
1268 begin
1269 { walk the procdef list }
1270 while (assigned(pd)) and (assigned(pd^.nextoverloaded)) do
1271 begin
1272 hd:=pd^.nextoverloaded;
1274 { check the parameters }
1275 if (not(m_repeat_forward in aktmodeswitches) and
1276 (aktprocsym^.definition^.para^.count=0)) or
1277 (equal_paras(aktprocsym^.definition^.para,hd^.para,cp_none) and
1278 { for operators equal_paras is not enough !! }
1279 ((aktprocsym^.definition^.proctypeoption<>potype_operator) or (optoken<>_ASSIGNMENT) or
1280 is_equal(hd^.rettype.def,aktprocsym^.definition^.rettype.def))) then
1281 begin
1282 if not equal_paras(aktprocsym^.definition^.para,hd^.para,cp_all) and
1283 ((m_repeat_forward in aktmodeswitches) or
1284 (aktprocsym^.definition^.para^.count>0)) then
1285 begin
1286 MessagePos1(aktprocsym^.definition^.fileinfo,parser_e_header_dont_match_forward,
1287 aktprocsym^.demangledName);
1288 exit;
1289 end;
1290 if hd^.forwarddef then
1291 { remove the forward definition but don't delete it, }
1292 { the symtable is the owner !! }
1293 begin
1294 { Check if the procedure type and return type are correct }
1295 if (hd^.proctypeoption<>aktprocsym^.definition^.proctypeoption) or
1296 (not(is_equal(hd^.rettype.def,aktprocsym^.definition^.rettype.def)) and
1297 (m_repeat_forward in aktmodeswitches)) then
1298 begin
1299 MessagePos1(aktprocsym^.definition^.fileinfo,parser_e_header_dont_match_forward,
1300 aktprocsym^.demangledName);
1301 exit;
1302 end;
1303 { Check calling convention, no check for internconst,internproc which
1304 are only defined in interface or implementation }
1305 if (hd^.proccalloptions-[pocall_internconst,pocall_internproc]<>
1306 aktprocsym^.definition^.proccalloptions-[pocall_internconst,pocall_internproc]) then
1307 begin
1308 { only trigger an error, becuase it doesn't hurt, for delphi check
1309 if the current implementation has no proccalloptions, then
1310 take the options from the interface }
1311 if (m_delphi in aktmodeswitches) then
1312 begin
1313 if (aktprocsym^.definition^.proccalloptions=[]) then
1314 aktprocsym^.definition^.proccalloptions:=hd^.proccalloptions
1315 else
1316 MessagePos(aktprocsym^.definition^.fileinfo,parser_e_call_convention_dont_match_forward);
1318 else
1319 MessagePos(aktprocsym^.definition^.fileinfo,parser_e_call_convention_dont_match_forward);
1320 { set the mangledname to the interface name so it doesn't trigger
1321 the Note about different manglednames (PFV) }
1322 aktprocsym^.definition^.setmangledname(hd^.mangledname);
1323 end;
1324 { manglednames are equal? }
1325 hd^.count:=false;
1326 if (m_repeat_forward in aktmodeswitches) or
1327 aktprocsym^.definition^.haspara then
1328 begin
1329 if (hd^.mangledname<>aktprocsym^.definition^.mangledname) then
1330 begin
1331 if not(po_external in aktprocsym^.definition^.procoptions) then
1332 MessagePos2(aktprocsym^.definition^.fileinfo,parser_n_interface_name_diff_implementation_name,hd^.mangledname,
1333 aktprocsym^.definition^.mangledname);
1334 { reset the mangledname of the interface part to be sure }
1335 { this is wrong because the mangled name might have been used already !! }
1336 if hd^.is_used then
1337 renameasmsymbol(hd^.mangledname,aktprocsym^.definition^.mangledname);
1338 hd^.setmangledname(aktprocsym^.definition^.mangledname);
1339 { so we need to keep the name of interface !!
1340 No!!!! The procedure directives can change the mangledname.
1341 I fixed this by first calling check_identical_proc and then doing
1342 the proc directives, but this is not a good solution.(DM)}
1343 { this is also wrong (PM)
1344 aktprocsym^.definition^.setmangledname(hd^.mangledname);}
1346 else
1347 begin
1348 { If mangled names are equal, therefore }
1349 { they have the same number of parameters }
1350 { Therefore we can check the name of these }
1351 { parameters... }
1352 if hd^.forwarddef and aktprocsym^.definition^.forwarddef then
1353 begin
1354 MessagePos1(aktprocsym^.definition^.fileinfo,
1355 parser_e_function_already_declared_public_forward,aktprocsym^.demangledName);
1356 check_identical_proc:=true;
1357 { Remove other forward from the list to reduce errors }
1358 pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
1359 exit;
1360 end;
1361 ad:=psym(hd^.parast^.symindex^.first);
1362 fd:=psym(aktprocsym^.definition^.parast^.symindex^.first);
1363 if assigned(ad) and assigned(fd) then
1364 begin
1365 while assigned(ad) and assigned(fd) do
1366 begin
1367 s:=ad^.name;
1368 if s<>fd^.name then
1369 begin
1370 MessagePos3(aktprocsym^.definition^.fileinfo,parser_e_header_different_var_names,
1371 aktprocsym^.name,s,fd^.name);
1372 break;
1373 end;
1374 { it is impossible to have a nil pointer }
1375 { for only one parameter - since they }
1376 { have the same number of parameters. }
1377 { Left = next parameter. }
1378 ad:=psym(ad^.left);
1379 fd:=psym(fd^.left);
1380 end;
1381 end;
1382 end;
1383 end;
1384 { also the para_offset }
1385 hd^.parast^.address_fixup:=aktprocsym^.definition^.parast^.address_fixup;
1386 hd^.count:=true;
1388 { remove pd^.nextoverloaded from the list }
1389 { and add aktprocsym^.definition }
1390 pd^.nextoverloaded:=pd^.nextoverloaded^.nextoverloaded;
1391 hd^.nextoverloaded:=aktprocsym^.definition^.nextoverloaded;
1392 { Alert! All fields of aktprocsym^.definition that are modified
1393 by the procdir handlers must be copied here!.}
1394 hd^.forwarddef:=false;
1395 hd^.hasforward:=true;
1396 hd^.proccalloptions:=hd^.proccalloptions + aktprocsym^.definition^.proccalloptions;
1397 hd^.procoptions:=hd^.procoptions + aktprocsym^.definition^.procoptions;
1398 if aktprocsym^.definition^.extnumber=-1 then
1399 aktprocsym^.definition^.extnumber:=hd^.extnumber
1400 else
1401 if hd^.extnumber=-1 then
1402 hd^.extnumber:=aktprocsym^.definition^.extnumber;
1403 { switch parast for warning in implementation PM }
1404 if (m_repeat_forward in aktmodeswitches) or
1405 aktprocsym^.definition^.haspara then
1406 begin
1407 storeparast:=hd^.parast;
1408 hd^.parast:=aktprocsym^.definition^.parast;
1409 aktprocsym^.definition^.parast:=storeparast;
1410 end;
1411 if pd=aktprocsym^.definition then
1412 p:=nil
1413 else
1414 p:=pd;
1415 aktprocsym^.definition:=hd;
1416 check_identical_proc:=true;
1418 else
1419 { abstract methods aren't forward defined, but this }
1420 { needs another error message }
1421 if not(po_abstractmethod in pd^.nextoverloaded^.procoptions) then
1422 MessagePos(aktprocsym^.definition^.fileinfo,parser_e_overloaded_have_same_parameters)
1423 else
1424 MessagePos(aktprocsym^.definition^.fileinfo,parser_e_abstract_no_definition);
1425 break;
1426 end;
1428 { check for allowing overload directive }
1429 if not(m_fpc in aktmodeswitches) then
1430 begin
1431 { overload directive turns on overloading }
1432 if ((po_overload in aktprocsym^.definition^.procoptions) or
1433 ((po_overload in hd^.procoptions))) then
1434 begin
1435 { check if all procs have overloading, but not if the proc was
1436 already declared forward, then the check is already done }
1437 if not(hd^.hasforward) and
1438 (aktprocsym^.definition^.forwarddef=hd^.forwarddef) and
1439 not((po_overload in aktprocsym^.definition^.procoptions) and
1440 ((po_overload in hd^.procoptions))) then
1441 begin
1442 MessagePos1(aktprocsym^.definition^.fileinfo,parser_e_no_overload_for_all_procs,aktprocsym^.name);
1443 break;
1444 end;
1446 else
1447 begin
1448 if not(hd^.forwarddef) then
1449 begin
1450 MessagePos(aktprocsym^.definition^.fileinfo,parser_e_procedure_overloading_is_off);
1451 break;
1452 end;
1453 end;
1454 end;
1456 { try next overloaded }
1457 pd:=pd^.nextoverloaded;
1458 end;
1460 else
1461 begin
1462 { there is no overloaded, so its always identical with itself }
1463 check_identical_proc:=true;
1464 end;
1465 end;
1466 { insert opsym only in the right symtable }
1467 if ((procinfo^.flags and pi_operator)<>0) and assigned(opsym)
1468 and not parse_only then
1469 begin
1470 if ret_in_param(aktprocsym^.definition^.rettype.def) then
1471 begin
1472 pprocdef(aktprocsym^.definition)^.parast^.insert(opsym);
1473 { this increases the data size }
1474 { correct this to get the right ret $value }
1475 dec(pprocdef(aktprocsym^.definition)^.parast^.datasize,opsym^.getpushsize);
1476 { this allows to read the funcretoffset }
1477 opsym^.address:=-4;
1478 opsym^.varspez:=vs_var;
1480 else
1481 pprocdef(aktprocsym^.definition)^.localst^.insert(opsym);
1482 end;
1483 end;
1485 procedure compile_proc_body(const proc_names:Tstringcontainer;
1486 make_global,parent_has_class:boolean);
1488 Compile the body of a procedure
1491 oldexitlabel,oldexit2label : pasmlabel;
1492 oldfaillabel,oldquickexitlabel:Pasmlabel;
1493 _class,hp:Pobjectdef;
1494 { switches can change inside the procedure }
1495 entryswitches, exitswitches : tlocalswitches;
1496 oldaktmaxfpuregisters,localmaxfpuregisters : longint;
1497 { code for the subroutine as tree }
1498 {$ifdef newcg}
1499 code:ptree;
1500 {$else newcg}
1501 code:ptree;
1502 {$endif newcg}
1503 { size of the local strackframe }
1504 stackframe:longint;
1505 { true when no stackframe is required }
1506 nostackframe:boolean;
1507 { number of bytes which have to be cleared by RET }
1508 parasize:longint;
1509 { filepositions }
1510 entrypos,
1511 savepos,
1512 exitpos : tfileposinfo;
1513 begin
1514 { calculate the lexical level }
1515 inc(lexlevel);
1516 if lexlevel>32 then
1517 Message(parser_e_too_much_lexlevel);
1519 { static is also important for local procedures !! }
1520 if (po_staticmethod in aktprocsym^.definition^.procoptions) then
1521 allow_only_static:=true
1522 else if (lexlevel=normal_function_level) then
1523 allow_only_static:=false;
1525 { save old labels }
1526 oldexitlabel:=aktexitlabel;
1527 oldexit2label:=aktexit2label;
1528 oldquickexitlabel:=quickexitlabel;
1529 oldfaillabel:=faillabel;
1530 { get new labels }
1531 getlabel(aktexitlabel);
1532 getlabel(aktexit2label);
1533 { exit for fail in constructors }
1534 if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
1535 begin
1536 getlabel(faillabel);
1537 getlabel(quickexitlabel);
1538 end;
1539 { reset break and continue labels }
1540 block_type:=bt_general;
1541 aktbreaklabel:=nil;
1542 aktcontinuelabel:=nil;
1544 { insert symtables for the class, by only if it is no nested function }
1545 if assigned(procinfo^._class) and not(parent_has_class) then
1546 begin
1547 { insert them in the reverse order ! }
1548 hp:=nil;
1549 repeat
1550 _class:=procinfo^._class;
1551 while _class^.childof<>hp do
1552 _class:=_class^.childof;
1553 hp:=_class;
1554 _class^.symtable^.next:=symtablestack;
1555 symtablestack:=_class^.symtable;
1556 until hp=procinfo^._class;
1557 end;
1559 { insert parasymtable in symtablestack}
1560 { only if lexlevel > 1 !!! global symtable should be right after staticsymtazble
1561 for checking of same names used in interface and implementation !! }
1562 if lexlevel>=normal_function_level then
1563 begin
1564 aktprocsym^.definition^.parast^.next:=symtablestack;
1565 symtablestack:=aktprocsym^.definition^.parast;
1566 symtablestack^.symtablelevel:=lexlevel;
1567 end;
1568 { insert localsymtable in symtablestack}
1569 aktprocsym^.definition^.localst^.next:=symtablestack;
1570 symtablestack:=aktprocsym^.definition^.localst;
1571 symtablestack^.symtablelevel:=lexlevel;
1572 { constant symbols are inserted in this symboltable }
1573 constsymtable:=symtablestack;
1575 { reset the temporary memory }
1576 cleartempgen;
1578 {$ifdef newcg}
1579 tg.usedinproc:=[];
1580 {$else newcg}
1581 { no registers are used }
1582 usedinproc:=0;
1583 {$endif newcg}
1584 { save entry info }
1585 entrypos:=aktfilepos;
1586 entryswitches:=aktlocalswitches;
1587 localmaxfpuregisters:=aktmaxfpuregisters;
1588 {$ifdef newcg}
1589 {$ifdef dummy}
1590 { parse the code ... }
1591 if (po_assembler in aktprocsym^.definition^.procoptions) then
1592 code:=convtree2node(assembler_block)
1593 else
1594 code:=convtree2node(block(current_module^.islibrary));
1595 {$endif dummy}
1596 { parse the code ... }
1597 if (po_assembler in aktprocsym^.definition^.procoptions) then
1598 code:=assembler_block
1599 else
1600 code:=block(current_module^.islibrary);
1601 {$else newcg}
1602 { parse the code ... }
1603 if (po_assembler in aktprocsym^.definition^.procoptions) then
1604 code:=assembler_block
1605 else
1606 code:=block(current_module^.islibrary);
1607 {$endif newcg}
1609 { get a better entry point }
1610 if assigned(code) then
1611 entrypos:=code^.fileinfo;
1613 { save exit info }
1614 exitswitches:=aktlocalswitches;
1615 exitpos:=last_endtoken_filepos;
1617 { save current filepos }
1618 savepos:=aktfilepos;
1620 {When we are called to compile the body of a unit, aktprocsym should
1621 point to the unit initialization. If the unit has no initialization,
1622 aktprocsym=nil. But in that case code=nil. hus we should check for
1623 code=nil, when we use aktprocsym.}
1625 { set the framepointer to esp for assembler functions }
1626 { but only if the are no local variables }
1627 { already done in assembler_block }
1628 {$ifdef newcg}
1629 tg.setfirsttemp(procinfo^.firsttemp_offset);
1630 {$else newcg}
1631 setfirsttemp(procinfo^.firsttemp_offset);
1632 {$endif newcg}
1634 { ... and generate assembler }
1635 { but set the right switches for entry !! }
1636 aktlocalswitches:=entryswitches;
1637 oldaktmaxfpuregisters:=aktmaxfpuregisters;
1638 aktmaxfpuregisters:=localmaxfpuregisters;
1639 {$ifndef NOPASS2}
1640 {$ifdef newcg}
1641 if assigned(code) then
1642 generatecode(code);
1643 {$else newcg}
1644 if assigned(code) then
1645 generatecode(code);
1646 {$endif newcg}
1647 { set switches to status at end of procedure }
1648 aktlocalswitches:=exitswitches;
1650 if assigned(code) then
1651 begin
1652 aktprocsym^.definition^.code:=code;
1654 { the procedure is now defined }
1655 aktprocsym^.definition^.forwarddef:=false;
1656 end;
1658 {$ifdef newcg}
1659 stackframe:=tg.gettempsize;
1660 {$else newcg}
1661 stackframe:=gettempsize;
1662 {$endif newcg}
1664 { first generate entry code with the correct position and switches }
1665 aktfilepos:=entrypos;
1666 aktlocalswitches:=entryswitches;
1667 {$ifdef newcg}
1668 if assigned(code) then
1669 cg^.g_entrycode(procinfo^.aktentrycode,proc_names,make_global,stackframe,parasize,nostackframe,false);
1670 {$else newcg}
1671 if assigned(code) then
1672 genentrycode(procinfo^.aktentrycode,proc_names,make_global,stackframe,parasize,nostackframe,false);
1673 {$endif newcg}
1675 { FPC_POPADDRSTACK destroys all registers (JM) }
1676 if (procinfo^.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0 then
1677 usedinproc := $ff;
1679 { now generate exit code with the correct position and switches }
1680 aktfilepos:=exitpos;
1681 aktlocalswitches:=exitswitches;
1682 if assigned(code) then
1683 begin
1684 {$ifdef newcg}
1685 cg^.g_exitcode(procinfo^.aktexitcode,parasize,nostackframe,false);
1686 {$else newcg}
1687 genexitcode(procinfo^.aktexitcode,parasize,nostackframe,false);
1688 {$endif newcg}
1689 { Now we can set the used registers }
1690 {$ifdef newcg}
1691 aktprocsym^.definition^.usedregisters:=tg.usedinproc;
1692 {$else newcg}
1693 aktprocsym^.definition^.usedregisters:=usedinproc;
1694 {$endif newcg}
1696 procinfo^.aktproccode^.insertlist(procinfo^.aktentrycode);
1697 procinfo^.aktproccode^.concatlist(procinfo^.aktexitcode);
1698 {$ifdef i386}
1699 {$ifndef NoOpt}
1700 if (cs_optimize in aktglobalswitches) and
1701 { do not optimize pure assembler procedures }
1702 ((procinfo^.flags and pi_is_assembler)=0) then
1703 Optimize(procinfo^.aktproccode);
1704 {$endif NoOpt}
1705 {$endif}
1706 { save local data (casetable) also in the same file }
1707 if assigned(procinfo^.aktlocaldata) and
1708 (not procinfo^.aktlocaldata^.empty) then
1709 begin
1710 procinfo^.aktproccode^.concat(new(pai_section,init(sec_data)));
1711 procinfo^.aktproccode^.concatlist(procinfo^.aktlocaldata);
1712 procinfo^.aktproccode^.concat(new(pai_section,init(sec_code)));
1713 end;
1714 { now we can insert a cut }
1715 if (cs_create_smart in aktmoduleswitches) then
1716 codesegment^.concat(new(pai_cut,init));
1718 { add the procedure to the codesegment }
1719 codesegment^.concatlist(procinfo^.aktproccode);
1720 end;
1721 {$else}
1722 if assigned(code) then
1723 firstpass(code);
1724 {$endif NOPASS2}
1726 { ... remove symbol tables, for the browser leave the static table }
1727 { if (cs_browser in aktmoduleswitches) and (symtablestack^.symtabletype=staticsymtable) then
1728 symtablestack^.next:=symtablestack^.next^.next
1729 else }
1730 if lexlevel>=normal_function_level then
1731 symtablestack:=symtablestack^.next^.next
1732 else
1733 symtablestack:=symtablestack^.next;
1735 { ... check for unused symbols }
1736 { but only if there is no asm block }
1737 if assigned(code) then
1738 begin
1739 if (Errorcount=0) then
1740 begin
1741 aktprocsym^.definition^.localst^.check_forwards;
1742 aktprocsym^.definition^.localst^.checklabels;
1743 end;
1744 if (procinfo^.flags and pi_uses_asm)=0 then
1745 begin
1746 { not for unit init, becuase the var can be used in finalize,
1747 it will be done in proc_unit }
1748 if not(aktprocsym^.definition^.proctypeoption
1749 in [potype_proginit,potype_unitinit,potype_unitfinalize]) then
1750 aktprocsym^.definition^.localst^.allsymbolsused;
1751 aktprocsym^.definition^.parast^.allsymbolsused;
1752 end;
1753 end;
1755 { the local symtables can be deleted, but the parast }
1756 { doesn't, (checking definitons when calling a }
1757 { function }
1758 { not for a inline procedure !! (PM) }
1759 { at lexlevel = 1 localst is the staticsymtable itself }
1760 { so no dispose here !! }
1761 if assigned(code) and
1762 not(cs_browser in aktmoduleswitches) and
1763 not(pocall_inline in aktprocsym^.definition^.proccalloptions) then
1764 begin
1765 if lexlevel>=normal_function_level then
1766 dispose(aktprocsym^.definition^.localst,done);
1767 aktprocsym^.definition^.localst:=nil;
1768 end;
1770 {$ifdef newcg}
1771 { all registers can be used again }
1772 tg.resetusableregisters;
1773 { only now we can remove the temps }
1774 tg.resettempgen;
1775 {$else newcg}
1776 { all registers can be used again }
1777 resetusableregisters;
1778 { only now we can remove the temps }
1779 resettempgen;
1780 {$endif newcg}
1782 { remove code tree, if not inline procedure }
1783 if assigned(code) and not(pocall_inline in aktprocsym^.definition^.proccalloptions) then
1784 {$ifdef newcg}
1785 {!!!!!!! dispose(code,done); }
1786 disposetree(code);
1787 {$else newcg}
1788 disposetree(code);
1789 {$endif newcg}
1791 { remove class member symbol tables }
1792 while symtablestack^.symtabletype=objectsymtable do
1793 symtablestack:=symtablestack^.next;
1795 aktmaxfpuregisters:=oldaktmaxfpuregisters;
1797 { restore filepos, the switches are already set }
1798 aktfilepos:=savepos;
1799 { restore labels }
1800 aktexitlabel:=oldexitlabel;
1801 aktexit2label:=oldexit2label;
1802 quickexitlabel:=oldquickexitlabel;
1803 faillabel:=oldfaillabel;
1805 { reset to normal non static function }
1806 if (lexlevel=normal_function_level) then
1807 allow_only_static:=false;
1808 { previous lexlevel }
1809 dec(lexlevel);
1810 end;
1813 procedure parse_proc_directives(Anames:Pstringcontainer;var pdflags:word);
1815 Parse the procedure directives. It does not matter if procedure directives
1816 are written using ;procdir; or ['procdir'] syntax.
1819 res : boolean;
1820 begin
1821 while token in [_ID,_LECKKLAMMER] do
1822 begin
1823 if try_to_consume(_LECKKLAMMER) then
1824 begin
1825 repeat
1826 parse_proc_direc(Anames^,pdflags);
1827 until not try_to_consume(_COMMA);
1828 consume(_RECKKLAMMER);
1829 { we always expect at least '[];' }
1830 res:=true;
1832 else
1833 res:=parse_proc_direc(Anames^,pdflags);
1834 { A procedure directive normally followed by a semicolon, but in
1835 a const section we should stop when _EQUAL is found }
1836 if res then
1837 begin
1838 if (block_type=bt_const) and
1839 (token=_EQUAL) then
1840 break;
1841 { support procedure proc;stdcall export; in Delphi mode only }
1842 if not((m_delphi in aktmodeswitches) and
1843 is_proc_directive(token)) then
1844 consume(_SEMICOLON);
1846 else
1847 break;
1848 end;
1849 end;
1851 procedure parse_var_proc_directives(var sym : psym);
1853 anames : pstringcontainer;
1854 pdflags : word;
1855 oldsym : pprocsym;
1856 pd : pabstractprocdef;
1857 begin
1858 oldsym:=aktprocsym;
1859 anames:=new(pstringcontainer,init);
1860 pdflags:=pd_procvar;
1861 { we create a temporary aktprocsym to read the directives }
1862 aktprocsym:=new(pprocsym,init(sym^.name));
1863 case sym^.typ of
1864 varsym :
1865 pd:=pabstractprocdef(pvarsym(sym)^.vartype.def);
1866 typedconstsym :
1867 pd:=pabstractprocdef(ptypedconstsym(sym)^.typedconsttype.def);
1868 typesym :
1869 pd:=pabstractprocdef(ptypesym(sym)^.restype.def);
1870 else
1871 internalerror(994932432);
1872 end;
1873 if pd^.deftype<>procvardef then
1874 internalerror(994932433);
1875 pabstractprocdef(aktprocsym^.definition):=pd;
1876 { names should never be used anyway }
1877 inc(lexlevel);
1878 parse_proc_directives(anames,pdflags);
1879 dec(lexlevel);
1880 aktprocsym^.definition:=nil;
1881 dispose(aktprocsym,done);
1882 dispose(anames,done);
1883 aktprocsym:=oldsym;
1884 end;
1886 procedure parse_object_proc_directives(var sym : pprocsym);
1888 anames : pstringcontainer;
1889 pdflags : word;
1890 begin
1891 pdflags:=pd_object;
1892 anames:=new(pstringcontainer,init);
1893 inc(lexlevel);
1894 parse_proc_directives(anames,pdflags);
1895 dec(lexlevel);
1896 dispose(anames,done);
1897 if (po_containsself in aktprocsym^.definition^.procoptions) and
1898 (([po_msgstr,po_msgint]*aktprocsym^.definition^.procoptions)=[]) then
1899 Message(parser_e_self_in_non_message_handler);
1900 end;
1902 procedure checkvaluepara(p:pnamedindexobject);{$ifndef FPC}far;{$endif}
1904 vs : pvarsym;
1905 s : string;
1906 begin
1907 with pvarsym(p)^ do
1908 begin
1909 if copy(name,1,3)='val' then
1910 begin
1911 s:=Copy(name,4,255);
1912 if not(po_assembler in aktprocsym^.definition^.procoptions) then
1913 begin
1914 vs:=new(Pvarsym,initdef(s,vartype.def));
1915 vs^.fileinfo:=fileinfo;
1916 vs^.varspez:=varspez;
1917 aktprocsym^.definition^.localst^.insert(vs);
1918 {$ifdef INCLUDEOK}
1919 include(vs^.varoptions,vo_is_local_copy);
1920 {$else}
1921 vs^.varoptions:=vs^.varoptions+[vo_is_local_copy];
1922 {$endif}
1923 vs^.varstate:=vs_assigned;
1924 localvarsym:=vs;
1925 inc(refs); { the para was used to set the local copy ! }
1926 { warnings only on local copy ! }
1927 varstate:=vs_used;
1929 else
1930 begin
1931 aktprocsym^.definition^.parast^.rename(name,s);
1932 end;
1933 end;
1934 end;
1935 end;
1938 procedure read_proc;
1940 Parses the procedure directives, then parses the procedure body, then
1941 generates the code for it
1944 oldprefix : string;
1945 oldprocsym : Pprocsym;
1946 oldprocinfo : pprocinfo;
1947 oldconstsymtable : Psymtable;
1948 oldfilepos : tfileposinfo;
1949 names : Pstringcontainer;
1950 pdflags : word;
1951 prevdef,stdef : pprocdef;
1952 begin
1953 { save old state }
1954 oldprocsym:=aktprocsym;
1955 oldprefix:=procprefix;
1956 oldconstsymtable:=constsymtable;
1957 oldprocinfo:=procinfo;
1958 { create a new procedure }
1959 new(names,init);
1960 {$ifdef fixLeaksOnError}
1961 strContStack.push(names);
1962 {$endif fixLeaksOnError}
1963 codegen_newprocedure;
1964 with procinfo^ do
1965 begin
1966 parent:=oldprocinfo;
1967 { clear flags }
1968 flags:=0;
1969 { standard frame pointer }
1970 framepointer:=frame_pointer;
1971 { funcret_is_valid:=false; }
1972 funcret_state:=vs_declared;
1973 { is this a nested function of a method ? }
1974 if assigned(oldprocinfo) then
1975 _class:=oldprocinfo^._class;
1976 end;
1978 parse_proc_dec;
1980 procinfo^.sym:=aktprocsym;
1981 procinfo^.def:=aktprocsym^.definition;
1983 { set the default function options }
1984 if parse_only then
1985 begin
1986 aktprocsym^.definition^.forwarddef:=true;
1987 { set also the interface flag, for better error message when the
1988 implementation doesn't much this header }
1989 aktprocsym^.definition^.interfacedef:=true;
1990 pdflags:=pd_interface;
1992 else
1993 begin
1994 pdflags:=pd_body;
1995 if current_module^.in_implementation then
1996 pdflags:=pdflags or pd_implemen;
1997 if (not current_module^.is_unit) or (cs_create_smart in aktmoduleswitches) then
1998 pdflags:=pdflags or pd_global;
1999 procinfo^.exported:=false;
2000 aktprocsym^.definition^.forwarddef:=false;
2001 end;
2003 { parse the directives that may follow }
2004 inc(lexlevel);
2005 parse_proc_directives(names,pdflags);
2006 dec(lexlevel);
2008 { set aktfilepos to the beginning of the function declaration }
2009 oldfilepos:=aktfilepos;
2010 aktfilepos:=aktprocsym^.definition^.fileinfo;
2012 { search for forward declarations }
2013 if not check_identical_proc(prevdef) then
2014 begin
2015 { A method must be forward defined (in the object declaration) }
2016 if assigned(procinfo^._class) and (not assigned(oldprocinfo^._class)) then
2017 begin
2018 Message1(parser_e_header_dont_match_any_member,aktprocsym^.demangledName);
2019 aktprocsym^.write_parameter_lists(aktprocsym^.definition);
2021 else
2022 begin
2023 { Give a better error if there is a forward def in the interface and only
2024 a single implementation }
2025 if (not aktprocsym^.definition^.forwarddef) and
2026 assigned(aktprocsym^.definition^.nextoverloaded) and
2027 aktprocsym^.definition^.nextoverloaded^.forwarddef and
2028 aktprocsym^.definition^.nextoverloaded^.interfacedef and
2029 not(assigned(aktprocsym^.definition^.nextoverloaded^.nextoverloaded)) then
2030 begin
2031 Message1(parser_e_header_dont_match_forward,aktprocsym^.demangledName);
2032 aktprocsym^.write_parameter_lists(aktprocsym^.definition);
2034 else
2035 begin
2036 { check the global flag }
2037 if (procinfo^.flags and pi_is_global)<>0 then
2038 Message(parser_e_overloaded_must_be_all_global);
2039 end;
2040 end;
2041 end;
2043 { set return type here, becuase the aktprocsym^.definition can be
2044 changed by check_identical_proc (PFV) }
2045 procinfo^.returntype.def:=aktprocsym^.definition^.rettype.def;
2047 {$ifdef i386}
2048 if (po_interrupt in aktprocsym^.definition^.procoptions) then
2049 begin
2050 { we push Flags and CS as long
2051 to cope with the IRETD
2052 and we save 6 register + 4 selectors }
2053 inc(procinfo^.para_offset,8+6*4+4*2);
2054 end;
2055 {$endif i386}
2057 { pointer to the return value ? }
2058 if ret_in_param(procinfo^.returntype.def) then
2059 begin
2060 procinfo^.return_offset:=procinfo^.para_offset;
2061 inc(procinfo^.para_offset,target_os.size_of_pointer);
2062 end;
2063 { allows to access the parameters of main functions in nested functions }
2064 aktprocsym^.definition^.parast^.address_fixup:=procinfo^.para_offset;
2066 { when it is a value para and it needs a local copy then rename
2067 the parameter and insert a copy in the localst. This is not done
2068 for assembler procedures }
2069 if (not parse_only) and (not aktprocsym^.definition^.forwarddef) then
2070 aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}checkvaluepara);
2072 { restore file pos }
2073 aktfilepos:=oldfilepos;
2075 { compile procedure when a body is needed }
2076 if (pdflags and pd_body)<>0 then
2077 begin
2078 Message1(parser_p_procedure_start,aktprocsym^.demangledname);
2079 names^.insert(aktprocsym^.definition^.mangledname);
2080 { set _FAIL as keyword if constructor }
2081 if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
2082 tokeninfo^[_FAIL].keyword:=m_all;
2083 if assigned(aktprocsym^.definition^._class) then
2084 tokeninfo^[_SELF].keyword:=m_all;
2086 compile_proc_body(names^,((pdflags and pd_global)<>0),assigned(oldprocinfo^._class));
2088 { reset _FAIL as normal }
2089 if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
2090 tokeninfo^[_FAIL].keyword:=m_none;
2091 if assigned(aktprocsym^.definition^._class) and (lexlevel=main_program_level) then
2092 tokeninfo^[_SELF].keyword:=m_none;
2093 consume(_SEMICOLON);
2094 end;
2095 { close }
2096 {$ifdef fixLeaksOnError}
2097 if names <> strContStack.pop then
2098 writeln('problem with strContStack in psub!');
2099 {$endif fixLeaksOnError}
2100 dispose(names,done);
2101 codegen_doneprocedure;
2102 { Restore old state }
2103 constsymtable:=oldconstsymtable;
2104 { from now on all refernece to mangledname means
2105 that the function is already used }
2106 aktprocsym^.definition^.count:=true;
2107 { restore the interface order to maintain CRC values PM }
2108 if assigned(prevdef) and assigned(aktprocsym^.definition^.nextoverloaded) then
2109 begin
2110 stdef:=aktprocsym^.definition;
2111 aktprocsym^.definition:=stdef^.nextoverloaded;
2112 stdef^.nextoverloaded:=prevdef^.nextoverloaded;
2113 prevdef^.nextoverloaded:=stdef;
2114 end;
2115 aktprocsym:=oldprocsym;
2116 procprefix:=oldprefix;
2117 procinfo:=oldprocinfo;
2118 opsym:=nil;
2119 end;
2121 end.
2124 $Log$
2125 Revision 1.1 2002/02/19 08:23:36 sasu
2126 Initial revision
2128 Revision 1.1.2.10 2000/11/26 22:41:47 florian
2129 * pascal modifier in units works now
2131 Revision 1.1.2.9 2000/11/08 16:34:35 jonas
2132 * if a procedure uses exceptions (be it implicit or explicit), the
2133 usedregisters are set to all (because FPC_POPADDRSTACK doesn't save
2134 any registers)
2136 Revision 1.1.2.8 2000/10/24 22:19:41 peter
2137 * set usedregisters after writing entry and exit code
2139 Revision 1.1.2.7 2000/09/24 21:38:34 peter
2140 * calling convention checking for delphi mode fixed
2142 Revision 1.1.2.6 2000/09/10 20:10:47 peter
2143 * overload checking in implementation removed
2145 Revision 1.1.2.5 2000/08/16 18:26:00 peter
2146 * splitted namedobjectitem.next into indexnext and listnext so it
2147 can be used in both lists
2148 * don't allow "word = word" type definitions
2150 Revision 1.1.2.4 2000/08/13 12:50:20 peter
2151 * class member decl wrong then no other error after it
2152 * -vb has now also line numbering
2153 * -vb is also used for interface/implementation different decls and
2154 doesn't list the current function
2156 Revision 1.1.2.3 2000/08/08 19:18:06 peter
2157 * delphi compatibility with proc directives after func/proc without ;
2159 Revision 1.1.2.2 2000/08/06 14:14:57 peter
2160 * overload directive checks fixes
2162 Revision 1.1.2.1 2000/07/30 16:40:40 peter
2163 * overload directive support is more delphi compatible
2165 Revision 1.1 2000/07/13 06:29:55 michael
2166 + Initial import
2168 Revision 1.67 2000/07/07 20:42:55 pierre
2169 * get a failure on webtbf/tbug890
2171 Revision 1.66 2000/07/06 19:04:59 peter
2172 * allow in delphi mode directives without semicolons between
2174 Revision 1.65 2000/06/25 20:13:51 florian
2175 * fixed a problem with forward declarations in TP mode, probably introduced by
2176 Pierre's last changes
2178 Revision 1.64 2000/06/20 12:47:52 pierre
2179 * equal_paras and convertable_paras changed by transforming third parameter
2180 into an enum with three possible values:
2181 cp_none, cp_value_equal_const and cp_all.
2183 Revision 1.63 2000/06/18 18:12:40 peter
2184 * support overload keyword
2186 Revision 1.62 2000/06/02 21:24:48 pierre
2187 * operator overloading now uses isbinaryoperatoracceptable
2188 and is unaryoperatoracceptable
2190 Revision 1.61 2000/05/10 19:22:51 pierre
2191 * Delphi defines TP so that code compiles
2192 sent by Kovacs Attila Zoltan
2194 Revision 1.60 2000/05/09 14:19:08 pierre
2195 * calculate para_offset for interrupt procedures
2197 Revision 1.59 2000/04/26 08:54:19 pierre
2198 * More changes for operator bug
2199 Order_overloaded method removed because it conflicted with
2200 new implementation where the defs are ordered
2201 according to the unit loading order !
2203 Revision 1.58 2000/04/25 23:55:29 pierre
2204 + Hint about unused unit
2205 * Testop bug fixed !!
2206 Now the operators are only applied if the unit is explicitly loaded
2208 Revision 1.57 2000/04/24 12:48:37 peter
2209 * removed unused vars
2211 Revision 1.56 2000/03/31 22:56:47 pierre
2212 * fix the handling of value parameters in cdecl function
2214 Revision 1.55 2000/03/27 11:57:22 pierre
2215 * fix for bug 890
2217 Revision 1.54 2000/03/23 22:17:51 pierre
2218 * fix tf000008 bug
2220 Revision 1.53 2000/03/16 16:41:13 pierre
2221 * fix for bug 807
2223 Revision 1.52 2000/03/15 23:10:00 pierre
2224 * fix for bug 848 (that still genrated wrong code)
2225 + better testing for variables used in assembler
2226 (gives an error if variable is not directly reachable !)
2228 Revision 1.51 2000/02/27 14:44:39 peter
2229 * if calling convention doesn't match don't print note about
2230 different manglednames
2232 Revision 1.50 2000/02/20 20:49:45 florian
2233 * newcg is compiling
2234 * fixed the dup id problem reported by Paul Y.
2236 Revision 1.49 2000/02/17 14:53:42 florian
2237 * some updates for the newcg
2239 Revision 1.48 2000/02/09 13:23:00 peter
2240 * log truncated
2242 Revision 1.47 2000/02/08 13:55:13 peter
2243 * reset section back to code after localdata
2245 Revision 1.46 2000/02/04 20:00:22 florian
2246 * an exception in a construcor calls now the destructor (this applies only
2247 to classes)
2249 Revision 1.45 2000/02/04 14:54:17 jonas
2250 * moved call to resetusableregs to compile_proc_body (put it right before the
2251 reset of the temp generator) so the optimizer can know which registers are
2252 regvars
2254 Revision 1.44 2000/01/28 23:17:53 florian
2255 * virtual XXXX; support for objects, only if -dWITHDMT is defined
2257 Revision 1.43 2000/01/21 22:06:16 florian
2258 * fixed for the fix of bug 793
2259 * fpu variables modified by nested subroutines aren't regable anymore
2260 * $maxfpuregisters doesn't modify anymore the behavior of a procedure before
2262 Revision 1.42 2000/01/16 22:17:12 peter
2263 * renamed call_offset to para_offset
2265 Revision 1.41 2000/01/11 17:16:06 jonas
2266 * removed a lot of memory leaks when an error is encountered (caused by
2267 procinfo and pstringcontainers). There are still plenty left though :)
2269 Revision 1.40 2000/01/07 01:14:31 peter
2270 * updated copyright to 2000
2272 Revision 1.39 1999/12/22 01:01:52 peter
2273 - removed freelabel()
2274 * added undefined label detection in internal assembler, this prevents
2275 a lot of ld crashes and wrong .o files
2276 * .o files aren't written anymore if errors have occured
2277 * inlining of assembler labels is now correct
2279 Revision 1.38 1999/12/06 18:17:09 peter
2280 * newcg compiler compiles again
2282 Revision 1.37 1999/11/30 10:40:48 peter
2283 + ttype, tsymlist
2285 Revision 1.36 1999/11/22 00:23:09 pierre
2286 * also complain about unused functions in program
2288 Revision 1.35 1999/11/17 17:05:02 pierre
2289 * Notes/hints changes
2291 Revision 1.34 1999/11/10 00:24:02 pierre
2292 * more browser details
2294 Revision 1.33 1999/11/09 23:43:08 pierre
2295 * better browser info
2297 Revision 1.32 1999/11/09 23:06:45 peter
2298 * esi_offset -> selfpointer_offset to be newcg compatible
2299 * hcogegen -> cgbase fixes for newcg
2301 Revision 1.31 1999/11/06 14:34:23 peter
2302 * truncated log to 20 revs
2304 Revision 1.30 1999/10/26 12:30:44 peter
2305 * const parameter is now checked
2306 * better and generic check if a node can be used for assigning
2307 * export fixes
2308 * procvar equal works now (it never had worked at least from 0.99.8)
2309 * defcoll changed to linkedlist with pparaitem so it can easily be
2310 walked both directions
2312 Revision 1.29 1999/10/22 10:39:35 peter
2313 * split type reading from pdecl to ptype unit
2314 * parameter_dec routine is now used for procedure and procvars
2316 Revision 1.28 1999/10/13 10:37:36 peter
2317 * moved mangledname creation of normal proc so it also handles a wrong
2318 method proc