- msg*: found a message to reuse

- pdecobj.pas: removed a check whether a class (helper) tries to inherit from a class helper, because now single_type handles this
- pexpr.pas: 
* prohibit type casts to class helpers (note: this might be needed for ObjC categories as well)
* class helper references may only be used when inheriting from them (needs to be checked for ObjC categories as well)
- ptype.pas:
* single_type: extend check against categories for class helpers
* read_named_type: extend check against categories for class helpers
- symbase.pas: add a method that adds symbol table flags recursivly to a stack of symtables (it stops updating the symtables once a symtable already has that flag or it's a global-/staticsymtable)
- symdef.pas: adjusted the constructor of tobjectdef to use the new method for adding flags 

git-svn-id: branches/svenbarth/classhelpers@16889 -
This commit is contained in:
svenbarth 2011-02-07 18:59:09 +00:00
parent e19bcfae38
commit 7cc7826343
8 changed files with 283 additions and 268 deletions

View File

@ -368,7 +368,7 @@ scanner_w_illegal_warn_identifier=02087_W_Illegal identifier "$1" for $WARN dire
#
# Parser
#
# 03308 is the last used one
# 03307 is the last used one
#
% \section{Parser messages}
% This section lists all parser messages. The parser takes care of the
@ -1264,9 +1264,12 @@ parser_e_objc_message_name_changed=03275_E_Message name "$1" in inherited class
parser_e_no_objc_unique=03276_E_It is not yet possible to make unique copies of Objective-C types
% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
parser_e_no_category_as_types=03277_E_Objective-C categories cannot be used as types
% It is not possible to declare a variable as an instance of an Objective-C category. A
% category adds methods to the scope of an existing class, but does not define a type by itself.
parser_e_no_category_as_types=03277_E_Objective-C categories and Object Pascal class helpers cannot be used as types
% It is not possible to declare a variable as an instance of an Objective-C
% category or an Object Pascal class helper. A category/class helper adds
% methods to the scope of an existing class, but does not define a type by
% itself. An exception of this rule is when inheriting an Object Pascal class
% helper from another class helper.
parser_e_no_category_override=03278_E_Categories do not override, but replace methods. Use "reintroduce" instead.
parser_e_must_use_reintroduce_objc=03279_E_Replaced methods can only be reintroduced in Objective-C, add "reintroduce" (replaced method defined in $1).
parser_h_should_use_reintroduce_objc=03280_H_Replaced methods can only be reintroduced in Objective-C, add "reintroduce" (replaced method defined in $1).
@ -1370,10 +1373,7 @@ parser_e_classhelper_id_expected=03305_E_Class helper identifier expected
parser_e_classhelper_must_extend_subclass=03306_E_Derived class helper must extend a subclass of the class extended by the parent class helper
% When a class helper inherits from another class helper the extended class must
% extend either the same class as the parent class helper or a subclass of it
parser_e_classhelper_not_allowed_here=03307_E_A class helper is not allowed here
% A class helper can only be referenced when inheriting from it. All other uses
% (like variable type, field type, parameter type, with clause) are disallowed.
parser_e_not_allowed_in_classhelper=03308_E_"$1" is not allowed in class helpers
parser_e_not_allowed_in_classhelper=03307_E_"$1" is not allowed in class helpers
% Some directives and specifiers like "virtual", "dynamic", "published" aren't
% allowed inside class helpers in mode ObjFPC (they are ignored in mode Delphi).
% \end{description}

View File

@ -395,8 +395,7 @@ const
parser_e_cant_use_type_parameters_here=03304;
parser_e_classhelper_id_expected=03305;
parser_e_classhelper_must_extend_subclass=03306;
parser_e_classhelper_not_allowed_here=03307;
parser_e_not_allowed_in_classhelper=03308;
parser_e_not_allowed_in_classhelper=03307;
type_e_mismatch=04000;
type_e_incompatible_types=04001;
type_e_not_equal_types=04002;
@ -886,9 +885,9 @@ const
option_info=11024;
option_help_pages=11025;
MsgTxtSize = 58949;
MsgTxtSize = 58938;
MsgIdxMax : array[1..20] of longint=(
24,88,309,99,84,54,111,22,202,63,
24,88,308,99,84,54,111,22,202,63,
49,20,1,1,1,1,1,1,1,1
);

File diff suppressed because it is too large Load Diff

View File

@ -482,29 +482,23 @@ implementation
isn't allowed }
case current_objectdef.objecttype of
odt_class:
if is_objectpascal_classhelper(childof) then
{ a class helper is not allowed as parent or extended
class
}
Message(parser_e_classhelper_not_allowed_here)
if not(is_class(childof)) then
begin
if is_interface(childof) then
begin
{ we insert the interface after the child
is set, see below
}
intfchildof:=childof;
childof:=class_tobject;
end
else
Message(parser_e_mix_of_classes_and_objects);
end
else
if not(is_class(childof)) then
begin
if is_interface(childof) then
begin
{ we insert the interface after the child
is set, see below
}
intfchildof:=childof;
childof:=class_tobject;
end
else
Message(parser_e_mix_of_classes_and_objects);
end
else
if (oo_is_sealed in childof.objectoptions) and
not is_objectpascal_classhelper(current_structdef) then
Message1(parser_e_sealed_descendant,childof.typename);
if (oo_is_sealed in childof.objectoptions) and
not is_objectpascal_classhelper(current_structdef) then
Message1(parser_e_sealed_descendant,childof.typename);
odt_interfacecorba,
odt_interfacecom:
begin

View File

@ -1488,7 +1488,12 @@ implementation
begin
p1:=comp_expr(true,false);
consume(_RKLAMMER);
p1:=ctypeconvnode.create_explicit(p1,hdef);
{ type casts to class helpers aren't allowed }
if is_objectpascal_classhelper(hdef) then
Message(parser_e_no_category_as_types)
{ recovery by not creating a conversion node }
else
p1:=ctypeconvnode.create_explicit(p1,hdef);
end
else { not LKLAMMER }
if (token=_POINT) and
@ -1534,6 +1539,12 @@ implementation
if is_class(hdef) or
is_objcclass(hdef) then
begin
if is_objectpascal_classhelper(hdef) then
begin
Message(parser_e_no_category_as_types);
{ for recovery we use the extended class }
hdef:=tobjectdef(hdef).childof;
end;
if getaddr and (token=_POINT) then
begin
consume(_POINT);

View File

@ -568,7 +568,7 @@ implementation
Message(parser_e_no_generics_as_types);
def:=generrordef;
end
else if is_objccategory(def) then
else if is_classhelper(def) then
begin
Message(parser_e_no_category_as_types);
def:=generrordef
@ -1035,7 +1035,7 @@ implementation
Message(parser_e_no_generics_as_types);
def:=generrordef;
end
else if is_objccategory(def) then
else if is_classhelper(def) then
begin
Message(parser_e_no_category_as_types);
def:=generrordef

View File

@ -114,6 +114,9 @@ interface
procedure insertdef(def:TDefEntry);virtual;
procedure deletedef(def:TDefEntry);
function iscurrentunit:boolean;virtual;
{ includes the flag in this symtable and all parent symtables; if
it's already set the flag is not set again }
procedure includeoption(option:tsymtableoption);
end;
psymtablestackitem = ^TSymtablestackitem;
@ -263,6 +266,26 @@ implementation
result:=false;
end;
procedure TSymtable.includeoption(option: tsymtableoption);
var
st: tsymtable;
begin
if option in tableoptions then
exit;
include(tableoptions,option);
{ iterative approach should be faster than recursion based on calls }
st:=self;
while assigned(st.defowner) do
begin
st:=st.defowner.owner;
{ the flag is already set, so by definition it is set in the
owning symtables as well }
if option in st.tableoptions then
break;
include(st.tableoptions,option);
end;
end;
procedure TSymtable.clear;
var

View File

@ -4148,24 +4148,13 @@ implementation
***************************************************************************}
constructor tobjectdef.create(ot:tobjecttyp;const n:string;c:tobjectdef);
procedure update_unit_symtable_options;
var
st: tsymtable;
begin
st:=owner;
while not(st.symtabletype in [globalsymtable,staticsymtable]) do
st:=st.defowner.owner;
if objecttype in [odt_classhelper,odt_objccategory] then
include(st.tableoptions,sto_has_classhelper);
end;
begin
inherited create(n,objectdef);
fcurrent_dispid:=0;
objecttype:=ot;
childof:=nil;
update_unit_symtable_options;
if objecttype in [odt_classhelper] then
owner.includeoption(sto_has_classhelper);
symtable:=tObjectSymtable.create(self,n,current_settings.packrecords);
{ create space for vmt !! }
vmtentries:=TFPList.Create;