|
@@ -96,18 +96,9 @@ interface
|
|
|
{ subroutine handling }
|
|
|
procedure test_protected_sym(sym : tsym);
|
|
|
procedure test_protected(p : tnode);
|
|
|
- function valid_for_formal_var(p : tnode) : boolean;
|
|
|
- function valid_for_formal_const(p : tnode) : boolean;
|
|
|
function is_procsym_load(p:tnode):boolean;
|
|
|
function is_procsym_call(p:tnode):boolean;
|
|
|
procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
|
|
|
- function valid_for_assign(p:tnode;allowprop:boolean):boolean;
|
|
|
- { sets the callunique flag, if the node is a vecn, }
|
|
|
- { takes care of type casts etc. }
|
|
|
- procedure set_unique(p : tnode);
|
|
|
-
|
|
|
- { sets funcret_is_valid to true, if p contains a funcref node }
|
|
|
- procedure set_funcret_is_valid(p : tnode);
|
|
|
|
|
|
{
|
|
|
type
|
|
@@ -118,6 +109,18 @@ interface
|
|
|
procedure unset_varstate(p : tnode);
|
|
|
procedure set_varstate(p : tnode;must_be_valid : boolean);
|
|
|
|
|
|
+ { sets the callunique flag, if the node is a vecn, }
|
|
|
+ { takes care of type casts etc. }
|
|
|
+ procedure set_unique(p : tnode);
|
|
|
+
|
|
|
+ { sets funcret_is_valid to true, if p contains a funcref node }
|
|
|
+ procedure set_funcret_is_valid(p : tnode);
|
|
|
+
|
|
|
+ function valid_for_formal_var(p : tnode) : boolean;
|
|
|
+ function valid_for_formal_const(p : tnode) : boolean;
|
|
|
+ function valid_for_var(p:tnode):boolean;
|
|
|
+ function valid_for_assignment(p:tnode):boolean;
|
|
|
+
|
|
|
|
|
|
implementation
|
|
|
|
|
@@ -135,6 +138,11 @@ implementation
|
|
|
{$endif}
|
|
|
;
|
|
|
|
|
|
+ type
|
|
|
+ TValidAssign=(Valid_Property,Valid_Void);
|
|
|
+ TValidAssigns=set of TValidAssign;
|
|
|
+
|
|
|
+
|
|
|
{ ld is the left type definition
|
|
|
rd the right type definition
|
|
|
dd the result type definition or voiddef if unkown }
|
|
@@ -496,61 +504,6 @@ implementation
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
- function valid_for_formal_var(p : tnode) : boolean;
|
|
|
- var
|
|
|
- v : boolean;
|
|
|
- begin
|
|
|
- case p.nodetype of
|
|
|
- loadn :
|
|
|
- v:=(tloadnode(p).symtableentry.typ in [typedconstsym,varsym]);
|
|
|
- typeconvn :
|
|
|
- v:=valid_for_formal_var(ttypeconvnode(p).left);
|
|
|
- derefn,
|
|
|
- subscriptn,
|
|
|
- vecn,
|
|
|
- funcretn,
|
|
|
- selfn :
|
|
|
- v:=true;
|
|
|
- calln : { procvars are callnodes first }
|
|
|
- v:=assigned(tcallnode(p).right) and not assigned(tcallnode(p).left);
|
|
|
- addrn :
|
|
|
- begin
|
|
|
- { addrn is not allowed as this generate a constant value,
|
|
|
- but a tp procvar are allowed (PFV) }
|
|
|
- if nf_procvarload in p.flags then
|
|
|
- v:=true
|
|
|
- else
|
|
|
- v:=false;
|
|
|
- end;
|
|
|
- else
|
|
|
- v:=false;
|
|
|
- end;
|
|
|
- valid_for_formal_var:=v;
|
|
|
- end;
|
|
|
-
|
|
|
- function valid_for_formal_const(p : tnode) : boolean;
|
|
|
- var
|
|
|
- v : boolean;
|
|
|
- begin
|
|
|
- { p must have been firstpass'd before }
|
|
|
- { accept about anything but not a statement ! }
|
|
|
- case p.nodetype of
|
|
|
- calln,
|
|
|
- statementn,
|
|
|
- addrn :
|
|
|
- begin
|
|
|
- { addrn is not allowed as this generate a constant value,
|
|
|
- but a tp procvar are allowed (PFV) }
|
|
|
- if nf_procvarload in p.flags then
|
|
|
- v:=true
|
|
|
- else
|
|
|
- v:=false;
|
|
|
- end;
|
|
|
- else
|
|
|
- v:=true;
|
|
|
- end;
|
|
|
- valid_for_formal_const:=v;
|
|
|
- end;
|
|
|
|
|
|
function is_procsym_load(p:tnode):boolean;
|
|
|
begin
|
|
@@ -559,6 +512,7 @@ implementation
|
|
|
and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
{ change a proc call to a procload for assignment to a procvar }
|
|
|
{ this can only happen for proc/function without arguments }
|
|
|
function is_procsym_call(p:tnode):boolean;
|
|
@@ -577,7 +531,182 @@ implementation
|
|
|
end;
|
|
|
|
|
|
|
|
|
- function valid_for_assign(p:tnode;allowprop:boolean):boolean;
|
|
|
+ procedure set_varstate(p : tnode;must_be_valid : boolean);
|
|
|
+ var
|
|
|
+ hsym : tvarsym;
|
|
|
+ begin
|
|
|
+ while assigned(p) do
|
|
|
+ begin
|
|
|
+ if (nf_varstateset in p.flags) then
|
|
|
+ exit;
|
|
|
+ include(p.flags,nf_varstateset);
|
|
|
+ case p.nodetype of
|
|
|
+ typeconvn :
|
|
|
+ begin
|
|
|
+ case ttypeconvnode(p).convtype of
|
|
|
+ tc_cchar_2_pchar,
|
|
|
+ tc_cstring_2_pchar,
|
|
|
+ tc_array_2_pointer :
|
|
|
+ must_be_valid:=false;
|
|
|
+ tc_pchar_2_string,
|
|
|
+ tc_pointer_2_array :
|
|
|
+ must_be_valid:=true;
|
|
|
+ end;
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ end;
|
|
|
+ subscriptn :
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ vecn:
|
|
|
+ begin
|
|
|
+ set_varstate(tbinarynode(p).right,true);
|
|
|
+ if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
|
|
|
+ must_be_valid:=true;
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ end;
|
|
|
+ { do not parse calln }
|
|
|
+ calln :
|
|
|
+ break;
|
|
|
+ callparan :
|
|
|
+ begin
|
|
|
+ set_varstate(tbinarynode(p).right,must_be_valid);
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ end;
|
|
|
+ loadn :
|
|
|
+ begin
|
|
|
+ if (tloadnode(p).symtableentry.typ=varsym) then
|
|
|
+ begin
|
|
|
+ hsym:=tvarsym(tloadnode(p).symtableentry);
|
|
|
+ if must_be_valid and (nf_first in p.flags) then
|
|
|
+ begin
|
|
|
+ if (hsym.varstate=vs_declared_and_first_found) or
|
|
|
+ (hsym.varstate=vs_set_but_first_not_passed) then
|
|
|
+ begin
|
|
|
+ if (assigned(hsym.owner) and
|
|
|
+ assigned(aktprocsym) and
|
|
|
+ (hsym.owner = aktprocsym.definition.localst)) then
|
|
|
+ begin
|
|
|
+ if tloadnode(p).symtable.symtabletype=localsymtable then
|
|
|
+ CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
|
|
|
+ else
|
|
|
+ CGMessage1(sym_n_uninitialized_variable,hsym.realname);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if (nf_first in p.flags) then
|
|
|
+ begin
|
|
|
+ if hsym.varstate=vs_declared_and_first_found then
|
|
|
+ begin
|
|
|
+ { this can only happen at left of an assignment, no ? PM }
|
|
|
+ if (parsing_para_level=0) and not must_be_valid then
|
|
|
+ hsym.varstate:=vs_assigned
|
|
|
+ else
|
|
|
+ hsym.varstate:=vs_used;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if hsym.varstate=vs_set_but_first_not_passed then
|
|
|
+ hsym.varstate:=vs_used;
|
|
|
+ exclude(p.flags,nf_first);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if (hsym.varstate=vs_assigned) and
|
|
|
+ (must_be_valid or (parsing_para_level>0) or
|
|
|
+ (p.resulttype.def.deftype=procvardef)) then
|
|
|
+ hsym.varstate:=vs_used;
|
|
|
+ if (hsym.varstate=vs_declared_and_first_found) and
|
|
|
+ (must_be_valid or (parsing_para_level>0) or
|
|
|
+ (p.resulttype.def.deftype=procvardef)) then
|
|
|
+ hsym.varstate:=vs_set_but_first_not_passed;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ funcretn:
|
|
|
+ begin
|
|
|
+ { no claim if setting higher return value_str }
|
|
|
+ if must_be_valid and
|
|
|
+ (procinfo=pprocinfo(tfuncretnode(p).funcretprocinfo)) and
|
|
|
+ ((procinfo^.funcret_state=vs_declared) or
|
|
|
+ ((nf_is_first_funcret in p.flags) and
|
|
|
+ (procinfo^.funcret_state=vs_declared_and_first_found))) then
|
|
|
+ begin
|
|
|
+ CGMessage(sym_w_function_result_not_set);
|
|
|
+ { avoid multiple warnings }
|
|
|
+ procinfo^.funcret_state:=vs_assigned;
|
|
|
+ end;
|
|
|
+ if (nf_is_first_funcret in p.flags) and not must_be_valid then
|
|
|
+ pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ end;{case }
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure unset_varstate(p : tnode);
|
|
|
+ begin
|
|
|
+ while assigned(p) do
|
|
|
+ begin
|
|
|
+ exclude(p.flags,nf_varstateset);
|
|
|
+ case p.nodetype of
|
|
|
+ typeconvn,
|
|
|
+ subscriptn,
|
|
|
+ vecn :
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure set_unique(p : tnode);
|
|
|
+ begin
|
|
|
+ while assigned(p) do
|
|
|
+ begin
|
|
|
+ case p.nodetype of
|
|
|
+ vecn:
|
|
|
+ begin
|
|
|
+ include(p.flags,nf_callunique);
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ typeconvn,
|
|
|
+ subscriptn,
|
|
|
+ derefn:
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure set_funcret_is_valid(p:tnode);
|
|
|
+ begin
|
|
|
+ while assigned(p) do
|
|
|
+ begin
|
|
|
+ case p.nodetype of
|
|
|
+ funcretn:
|
|
|
+ begin
|
|
|
+ if (nf_is_first_funcret in p.flags) then
|
|
|
+ pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ vecn,
|
|
|
+ {derefn,}
|
|
|
+ typeconvn,
|
|
|
+ subscriptn:
|
|
|
+ p:=tunarynode(p).left;
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ function valid_for_assign(p:tnode;opts:TValidAssigns):boolean;
|
|
|
var
|
|
|
hp : tnode;
|
|
|
gotwith,
|
|
@@ -593,7 +722,8 @@ implementation
|
|
|
gotpointer:=false;
|
|
|
gotwith:=false;
|
|
|
hp:=p;
|
|
|
- if is_void(hp.resulttype.def) then
|
|
|
+ if not(valid_void in opts) and
|
|
|
+ is_void(hp.resulttype.def) then
|
|
|
begin
|
|
|
CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
|
|
|
exit;
|
|
@@ -601,7 +731,7 @@ implementation
|
|
|
while assigned(hp) do
|
|
|
begin
|
|
|
{ property allowed? calln has a property check itself }
|
|
|
- if (not allowprop) and
|
|
|
+ if not(valid_property in opts) and
|
|
|
(nf_isproperty in hp.flags) and
|
|
|
(hp.nodetype<>calln) then
|
|
|
begin
|
|
@@ -687,7 +817,7 @@ implementation
|
|
|
3. property is allowed }
|
|
|
if (gotpointer and gotderef) or
|
|
|
(gotclass and (gotsubscript or gotwith)) or
|
|
|
- ((nf_isproperty in hp.flags) and allowprop) then
|
|
|
+ ((nf_isproperty in hp.flags) and (valid_property in opts)) then
|
|
|
valid_for_assign:=true
|
|
|
else
|
|
|
CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
|
|
@@ -743,184 +873,55 @@ implementation
|
|
|
end;
|
|
|
|
|
|
|
|
|
- procedure set_varstate(p : tnode;must_be_valid : boolean);
|
|
|
- var
|
|
|
- hsym : tvarsym;
|
|
|
+ function valid_for_var(p:tnode):boolean;
|
|
|
begin
|
|
|
- while assigned(p) do
|
|
|
- begin
|
|
|
- if (nf_varstateset in p.flags) then
|
|
|
- exit;
|
|
|
- include(p.flags,nf_varstateset);
|
|
|
- case p.nodetype of
|
|
|
- typeconvn :
|
|
|
- begin
|
|
|
- case ttypeconvnode(p).convtype of
|
|
|
- tc_cchar_2_pchar,
|
|
|
- tc_cstring_2_pchar,
|
|
|
- tc_array_2_pointer :
|
|
|
- must_be_valid:=false;
|
|
|
- tc_pchar_2_string,
|
|
|
- tc_pointer_2_array :
|
|
|
- must_be_valid:=true;
|
|
|
- end;
|
|
|
- p:=tunarynode(p).left;
|
|
|
- end;
|
|
|
- subscriptn :
|
|
|
- p:=tunarynode(p).left;
|
|
|
- vecn:
|
|
|
- begin
|
|
|
- set_varstate(tbinarynode(p).right,true);
|
|
|
- if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
|
|
|
- must_be_valid:=true;
|
|
|
- p:=tunarynode(p).left;
|
|
|
- end;
|
|
|
- { do not parse calln }
|
|
|
- calln :
|
|
|
- break;
|
|
|
- callparan :
|
|
|
- begin
|
|
|
- set_varstate(tbinarynode(p).right,must_be_valid);
|
|
|
- p:=tunarynode(p).left;
|
|
|
- end;
|
|
|
- loadn :
|
|
|
- begin
|
|
|
- if (tloadnode(p).symtableentry.typ=varsym) then
|
|
|
- begin
|
|
|
- hsym:=tvarsym(tloadnode(p).symtableentry);
|
|
|
- if must_be_valid and (nf_first in p.flags) then
|
|
|
- begin
|
|
|
- if (hsym.varstate=vs_declared_and_first_found) or
|
|
|
- (hsym.varstate=vs_set_but_first_not_passed) then
|
|
|
- begin
|
|
|
- if (assigned(hsym.owner) and
|
|
|
- assigned(aktprocsym) and
|
|
|
- (hsym.owner = aktprocsym.definition.localst)) then
|
|
|
- begin
|
|
|
- if tloadnode(p).symtable.symtabletype=localsymtable then
|
|
|
- CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
|
|
|
- else
|
|
|
- CGMessage1(sym_n_uninitialized_variable,hsym.realname);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
- if (nf_first in p.flags) then
|
|
|
- begin
|
|
|
- if hsym.varstate=vs_declared_and_first_found then
|
|
|
- begin
|
|
|
- { this can only happen at left of an assignment, no ? PM }
|
|
|
- if (parsing_para_level=0) and not must_be_valid then
|
|
|
- hsym.varstate:=vs_assigned
|
|
|
- else
|
|
|
- hsym.varstate:=vs_used;
|
|
|
- end
|
|
|
- else
|
|
|
- if hsym.varstate=vs_set_but_first_not_passed then
|
|
|
- hsym.varstate:=vs_used;
|
|
|
- exclude(p.flags,nf_first);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if (hsym.varstate=vs_assigned) and
|
|
|
- (must_be_valid or (parsing_para_level>0) or
|
|
|
- (p.resulttype.def.deftype=procvardef)) then
|
|
|
- hsym.varstate:=vs_used;
|
|
|
- if (hsym.varstate=vs_declared_and_first_found) and
|
|
|
- (must_be_valid or (parsing_para_level>0) or
|
|
|
- (p.resulttype.def.deftype=procvardef)) then
|
|
|
- hsym.varstate:=vs_set_but_first_not_passed;
|
|
|
- end;
|
|
|
- end;
|
|
|
- break;
|
|
|
- end;
|
|
|
- funcretn:
|
|
|
- begin
|
|
|
- { no claim if setting higher return value_str }
|
|
|
- if must_be_valid and
|
|
|
- (procinfo=pprocinfo(tfuncretnode(p).funcretprocinfo)) and
|
|
|
- ((procinfo^.funcret_state=vs_declared) or
|
|
|
- ((nf_is_first_funcret in p.flags) and
|
|
|
- (procinfo^.funcret_state=vs_declared_and_first_found))) then
|
|
|
- begin
|
|
|
- CGMessage(sym_w_function_result_not_set);
|
|
|
- { avoid multiple warnings }
|
|
|
- procinfo^.funcret_state:=vs_assigned;
|
|
|
- end;
|
|
|
- if (nf_is_first_funcret in p.flags) and not must_be_valid then
|
|
|
- pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
|
|
|
- break;
|
|
|
- end;
|
|
|
- else
|
|
|
- break;
|
|
|
- end;{case }
|
|
|
- end;
|
|
|
+ valid_for_var:=valid_for_assign(p,[]);
|
|
|
end;
|
|
|
|
|
|
|
|
|
- procedure unset_varstate(p : tnode);
|
|
|
+ function valid_for_formal_var(p : tnode) : boolean;
|
|
|
begin
|
|
|
- while assigned(p) do
|
|
|
- begin
|
|
|
- exclude(p.flags,nf_varstateset);
|
|
|
- case p.nodetype of
|
|
|
- typeconvn,
|
|
|
- subscriptn,
|
|
|
- vecn :
|
|
|
- p:=tunarynode(p).left;
|
|
|
- else
|
|
|
- break;
|
|
|
- end;
|
|
|
- end;
|
|
|
+ valid_for_formal_var:=valid_for_assign(p,[valid_void]);
|
|
|
end;
|
|
|
|
|
|
|
|
|
- procedure set_unique(p : tnode);
|
|
|
+ function valid_for_formal_const(p : tnode) : boolean;
|
|
|
+ var
|
|
|
+ v : boolean;
|
|
|
begin
|
|
|
- while assigned(p) do
|
|
|
- begin
|
|
|
- case p.nodetype of
|
|
|
- vecn:
|
|
|
- begin
|
|
|
- include(p.flags,nf_callunique);
|
|
|
- break;
|
|
|
- end;
|
|
|
- typeconvn,
|
|
|
- subscriptn,
|
|
|
- derefn:
|
|
|
- p:=tunarynode(p).left;
|
|
|
+ { p must have been firstpass'd before }
|
|
|
+ { accept about anything but not a statement ! }
|
|
|
+ case p.nodetype of
|
|
|
+ calln,
|
|
|
+ statementn,
|
|
|
+ addrn :
|
|
|
+ begin
|
|
|
+ { addrn is not allowed as this generate a constant value,
|
|
|
+ but a tp procvar are allowed (PFV) }
|
|
|
+ if nf_procvarload in p.flags then
|
|
|
+ v:=true
|
|
|
else
|
|
|
- break;
|
|
|
+ v:=false;
|
|
|
end;
|
|
|
- end;
|
|
|
+ else
|
|
|
+ v:=true;
|
|
|
+ end;
|
|
|
+ valid_for_formal_const:=v;
|
|
|
end;
|
|
|
|
|
|
|
|
|
- procedure set_funcret_is_valid(p:tnode);
|
|
|
+ function valid_for_assignment(p:tnode):boolean;
|
|
|
begin
|
|
|
- while assigned(p) do
|
|
|
- begin
|
|
|
- case p.nodetype of
|
|
|
- funcretn:
|
|
|
- begin
|
|
|
- if (nf_is_first_funcret in p.flags) then
|
|
|
- pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
|
|
|
- break;
|
|
|
- end;
|
|
|
- vecn,
|
|
|
- {derefn,}
|
|
|
- typeconvn,
|
|
|
- subscriptn:
|
|
|
- p:=tunarynode(p).left;
|
|
|
- else
|
|
|
- break;
|
|
|
- end;
|
|
|
- end;
|
|
|
+ valid_for_assignment:=valid_for_assign(p,[valid_property]);
|
|
|
end;
|
|
|
|
|
|
end.
|
|
|
{
|
|
|
$Log$
|
|
|
- Revision 1.27 2001-05-18 22:57:08 peter
|
|
|
+ Revision 1.28 2001-06-04 11:48:02 peter
|
|
|
+ * better const to var checking
|
|
|
+
|
|
|
+ Revision 1.27 2001/05/18 22:57:08 peter
|
|
|
* replace constant by cpu dependent value (merged)
|
|
|
|
|
|
Revision 1.26 2001/05/08 08:52:05 jonas
|