Преглед на файлове

- 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 -

svenbarth преди 14 години
родител
ревизия
7cc7826343
променени са 8 файла, в които са добавени 261 реда и са изтрити 245 реда
  1. 8 8
      compiler/msg/errore.msg
  2. 3 4
      compiler/msgidx.inc
  3. 195 195
      compiler/msgtxt.inc
  4. 16 22
      compiler/pdecobj.pas
  5. 12 1
      compiler/pexpr.pas
  6. 2 2
      compiler/ptype.pas
  7. 23 0
      compiler/symbase.pas
  8. 2 13
      compiler/symdef.pas

+ 8 - 8
compiler/msg/errore.msg

@@ -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}

+ 3 - 4
compiler/msgidx.inc

@@ -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
   );

Файловите разлики са ограничени, защото са твърде много
+ 195 - 195
compiler/msgtxt.inc


+ 16 - 22
compiler/pdecobj.pas

@@ -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

+ 12 - 1
compiler/pexpr.pas

@@ -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);

+ 2 - 2
compiler/ptype.pas

@@ -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

+ 23 - 0
compiler/symbase.pas

@@ -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

+ 2 - 13
compiler/symdef.pas

@@ -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;

Някои файлове не бяха показани, защото твърде много файлове са промени