]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Do not allow structs to have more than one base type and detect cycles,
authorJürg Billeter <j@bitron.ch>
Fri, 16 Jan 2009 17:21:00 +0000 (17:21 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 16 Jan 2009 17:21:00 +0000 (17:21 +0000)
2009-01-16  Jürg Billeter  <j@bitron.ch>

* vala/valabaseaccess.vala:
* vala/valacodewriter.vala:
* vala/valagenieparser.vala:
* vala/valaparser.vala:
* vala/valasemanticanalyzer.vala:
* vala/valastruct.vala:
* vala/valasymbolresolver.vala:
* vapigen/valagirparser.vala:

Do not allow structs to have more than one base type and detect
cycles, patch by Andreas Brauchli, fixes bug 556063 and bug 567661

svn path=/trunk/; revision=2361

ChangeLog
vala/valabaseaccess.vala
vala/valacodewriter.vala
vala/valagenieparser.vala
vala/valaparser.vala
vala/valasemanticanalyzer.vala
vala/valastruct.vala
vala/valasymbolresolver.vala
vapigen/valagirparser.vala

index 90c7f2a31b743c971b77563f4f20f3edf75ee279..e07f2719a3dd81a14560a638a6be75d4133b13be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2009-01-16  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valabaseaccess.vala:
+       * vala/valacodewriter.vala:
+       * vala/valagenieparser.vala:
+       * vala/valaparser.vala:
+       * vala/valasemanticanalyzer.vala:
+       * vala/valastruct.vala:
+       * vala/valasymbolresolver.vala:
+       * vapigen/valagirparser.vala:
+
+       Do not allow structs to have more than one base type and detect
+       cycles, patch by Andreas Brauchli, fixes bug 556063 and bug 567661
+
 2009-01-16  Jürg Billeter  <j@bitron.ch>
 
        * vapi/packages/gtk+-2.0/:
index 1de0c7a7849928383edc627f8717d9e6644bdfda..42f74b9a983fc32974b571e98c183cf44b0c2f0d 100644 (file)
@@ -68,14 +68,12 @@ public class Vala.BaseAccess : Expression {
                                error = true;
                                Report.error (source_reference, "Base access invalid outside of class and struct");
                                return false;
-                       } else if (analyzer.current_struct.get_base_types ().size != 1) {
+                       } else if (analyzer.current_struct.base_type == null) {
                                error = true;
-                               Report.error (source_reference, "Base access invalid without base type %d".printf (analyzer.current_struct.get_base_types ().size));
+                               Report.error (source_reference, "Base access invalid without base type");
                                return false;
                        }
-                       Iterator<DataType> base_type_it = analyzer.current_struct.get_base_types ().iterator ();
-                       base_type_it.next ();
-                       value_type = base_type_it.get ();
+                       value_type = analyzer.current_struct.base_type;
                } else if (analyzer.current_class.base_class == null) {
                        error = true;
                        Report.error (source_reference, "Base access invalid without base class");
index f3730406eda7a60f8c42fbce2b6f22679e759cf8..0aa35702d9a5f3848b60e17d9def0bfd85805f98 100644 (file)
@@ -317,19 +317,9 @@ public class Vala.CodeWriter : CodeVisitor {
                write_string ("struct ");
                write_identifier (st.name);
 
-               var base_types = st.get_base_types ();
-               if (base_types.size > 0) {
+               if (st.base_type != null) {
                        write_string (" : ");
-               
-                       first = true;
-                       foreach (DataType base_type in base_types) {
-                               if (!first) {
-                                       write_string (", ");
-                               } else {
-                                       first = false;
-                               }
-                               write_type (base_type);
-                       }
+                       write_type (st.base_type);
                }
 
                write_begin_block ();
index 73273d0389e585aee7b16d658acd25f761841d2a..9bbee34f2b80a9a010b11da6e88a3b081f3977ee 100644 (file)
@@ -2909,11 +2909,9 @@ public class Vala.Genie.Parser : CodeVisitor {
                var flags = parse_type_declaration_modifiers ();
                var sym = parse_symbol_name ();
                var type_param_list = parse_type_parameter_list ();
-               var base_types = new ArrayList<DataType> ();
+               DataType base_type = null;
                if (accept (TokenType.COLON)) {
-                       do {
-                               base_types.add (parse_type ());
-                       } while (accept (TokenType.COMMA));
+                       base_type = parse_type ();
                }
                var st = new Struct (sym.name, get_src_com (begin));
                if (ModifierFlags.PRIVATE in flags) {
@@ -2925,8 +2923,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                foreach (TypeParameter type_param in type_param_list) {
                        st.add_type_parameter (type_param);
                }
-               foreach (DataType base_type in base_types) {
-                       st.add_base_type (base_type);
+               if (base_type != null) {
+                       st.base_type = base_type;
                }
 
                expect (TokenType.EOL);
index be5abb855e0d081da06217f001a5b34cfd230303..90e585b11f69f82534a764c264f5f6d6745639b4 100644 (file)
@@ -2398,11 +2398,9 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.STRUCT);
                var sym = parse_symbol_name ();
                var type_param_list = parse_type_parameter_list ();
-               var base_types = new ArrayList<DataType> ();
+               DataType base_type = null;
                if (accept (TokenType.COLON)) {
-                       do {
-                               base_types.add (parse_type ());
-                       } while (accept (TokenType.COMMA));
+                       base_type = parse_type ();
                }
                var st = new Struct (sym.name, get_src_com (begin));
                st.access = access;
@@ -2413,8 +2411,8 @@ public class Vala.Parser : CodeVisitor {
                foreach (TypeParameter type_param in type_param_list) {
                        st.add_type_parameter (type_param);
                }
-               foreach (DataType base_type in base_types) {
-                       st.add_base_type (base_type);
+               if (base_type != null) {
+                       st.base_type = base_type;
                }
 
                parse_declarations (st);
index 3fb94451e48758f97e043879e66b156511708bd9..4efe18328aa417ae66c8c323e739c543f9e021ac 100644 (file)
@@ -219,8 +219,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                } else if (sym is Struct) {
                        var st = (Struct) sym;
-                       foreach (DataType base_type in st.get_base_types ()) {
-                               result = symbol_lookup_inherited (base_type.data_type, name);
+                       if (st.base_type != null) {
+                               result = symbol_lookup_inherited (st.base_type.data_type, name);
                                if (result != null) {
                                        return result;
                                }
@@ -526,8 +526,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                } else if (instance_type.data_type is Struct) {
                        var st = (Struct) instance_type.data_type;
-                       foreach (DataType base_type in st.get_base_types ()) {
-                               instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, base_type, node_reference), type_symbol, node_reference);
+                       if (st.base_type != null) {
+                               instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, st.base_type, node_reference), type_symbol, node_reference);
                                if (instance_base_type != null) {
                                        return instance_base_type;
                                }
index 9cfbe308eb8cd68d4998f5e8f327123b2af7e957..b5ef8fb68ff35903c5a72bfc5662665753a517e2 100644 (file)
@@ -31,9 +31,8 @@ public class Vala.Struct : TypeSymbol {
        private Gee.List<Constant> constants = new ArrayList<Constant> ();
        private Gee.List<Field> fields = new ArrayList<Field> ();
        private Gee.List<Method> methods = new ArrayList<Method> ();
+       private DataType _base_type = null;
 
-       private Gee.List<DataType> base_types = new ArrayList<DataType> ();
-       
        private string cname;
        private string const_cname;
        private string type_id;
@@ -51,6 +50,19 @@ public class Vala.Struct : TypeSymbol {
        private string copy_function;
        private string destroy_function;
 
+       /**
+        * Specifies the base struct.
+        */
+       public DataType? base_type {
+               get {
+                       return _base_type;
+               }
+               set {
+                       value.parent_node = this;
+                       _base_type = value;
+               }
+       }
+
        /**
         * Specifies the default construction method.
         */
@@ -179,8 +191,8 @@ public class Vala.Struct : TypeSymbol {
        }
 
        public override void accept_children (CodeVisitor visitor) {
-               foreach (DataType type in base_types) {
-                       type.accept (visitor);
+               if (base_type != null) {
+                       base_type.accept (visitor);
                }
 
                foreach (TypeParameter p in type_parameters) {
@@ -276,8 +288,8 @@ public class Vala.Struct : TypeSymbol {
         * @return true if this is a boolean type, false otherwise
         */
        public bool is_boolean_type () {
-               foreach (DataType type in base_types) {
-                       var st = type.data_type as Struct;
+               if (base_type != null) {
+                       var st = base_type.data_type as Struct;
                        if (st != null && st.is_boolean_type ()) {
                                return true;
                        }
@@ -291,8 +303,8 @@ public class Vala.Struct : TypeSymbol {
         * @return true if this is an integer type, false otherwise
         */
        public bool is_integer_type () {
-               foreach (DataType type in base_types) {
-                       var st = type.data_type as Struct;
+               if (base_type != null) {
+                       var st = base_type.data_type as Struct;
                        if (st != null && st.is_integer_type ()) {
                                return true;
                        }
@@ -306,8 +318,8 @@ public class Vala.Struct : TypeSymbol {
         * @return true if this is a floating point type, false otherwise
         */
        public bool is_floating_type () {
-               foreach (DataType type in base_types) {
-                       var st = type.data_type as Struct;
+               if (base_type != null) {
+                       var st = base_type.data_type as Struct;
                        if (st != null && st.is_floating_type ()) {
                                return true;
                        }
@@ -404,10 +416,10 @@ public class Vala.Struct : TypeSymbol {
        public override string? get_type_id () {
                if (type_id == null) {
                        if (!has_type_id) {
-                               foreach (DataType type in base_types) {
-                                       var st = type.data_type as Struct;
+                               if (base_type != null) {
+                                       var st = base_type.data_type as Struct;
                                        if (st != null) {
-                                               return st.get_type_id ();;
+                                               return st.get_type_id ();
                                        }
                                }
                                if (is_simple_type ()) {
@@ -428,8 +440,8 @@ public class Vala.Struct : TypeSymbol {
 
        public override string? get_marshaller_type_name () {
                if (marshaller_type_name == null) {
-                       foreach (DataType type in base_types) {
-                               var st = type.data_type as Struct;
+                       if (base_type != null) {
+                               var st = base_type.data_type as Struct;
                                if (st != null) {
                                        return st.get_marshaller_type_name ();
                                }
@@ -451,8 +463,8 @@ public class Vala.Struct : TypeSymbol {
        
        public override string? get_get_value_function () {
                if (get_value_function == null) {
-                       foreach (DataType type in base_types) {
-                               var st = type.data_type as Struct;
+                       if (base_type != null) {
+                               var st = base_type.data_type as Struct;
                                if (st != null) {
                                        return st.get_get_value_function ();
                                }
@@ -472,8 +484,8 @@ public class Vala.Struct : TypeSymbol {
        
        public override string? get_set_value_function () {
                if (set_value_function == null) {
-                       foreach (DataType type in base_types) {
-                               var st = type.data_type as Struct;
+                       if (base_type != null) {
+                               var st = base_type.data_type as Struct;
                                if (st != null) {
                                        return st.get_set_value_function ();
                                }
@@ -505,8 +517,8 @@ public class Vala.Struct : TypeSymbol {
                }
 
                // inherit default value from base type
-               foreach (DataType type in base_types) {
-                       var st = type.data_type as Struct;
+               if (base_type != null) {
+                       var st = base_type.data_type as Struct;
                        if (st != null) {
                                return st.get_default_value ();
                        }
@@ -518,25 +530,6 @@ public class Vala.Struct : TypeSymbol {
                default_value = value;
        }
 
-       /**
-        * Adds the specified struct to the list of base types of this struct.
-        *
-        * @param type a class or interface reference
-        */
-       public void add_base_type (DataType type) {
-               base_types.add (type);
-               type.parent_node = this;
-       }
-
-       /**
-        * Returns a copy of the base type list.
-        *
-        * @return list of base types
-        */
-       public Gee.List<DataType> get_base_types () {
-               return new ReadOnlyList<DataType> (base_types);
-       }
-       
        public override int get_type_parameter_index (string name) {
                int i = 0;
                
@@ -555,8 +548,8 @@ public class Vala.Struct : TypeSymbol {
         * instances are passed by value.
         */
        public bool is_simple_type () {
-               foreach (DataType type in base_types) {
-                       var st = type.data_type as Struct;
+               if (base_type != null) {
+                       var st = base_type.data_type as Struct;
                        if (st != null && st.is_simple_type ()) {
                                return true;
                        }
@@ -573,11 +566,8 @@ public class Vala.Struct : TypeSymbol {
        }
 
        public override void replace_type (DataType old_type, DataType new_type) {
-               for (int i = 0; i < base_types.size; i++) {
-                       if (base_types[i] == old_type) {
-                               base_types[i] = new_type;
-                               return;
-                       }
+               if (base_type == old_type) {
+                       base_type = new_type;
                }
        }
 
@@ -586,12 +576,12 @@ public class Vala.Struct : TypeSymbol {
                        return true;
                }
 
-               foreach (DataType base_type in base_types) {
+               if (base_type != null) {
                        if (base_type.data_type != null && base_type.data_type.is_subtype_of (t)) {
                                return true;
                        }
                }
-               
+
                return false;
        }
 
@@ -677,12 +667,12 @@ public class Vala.Struct : TypeSymbol {
                analyzer.current_symbol = this;
                analyzer.current_struct = this;
 
-               foreach (DataType type in base_types) {
-                       type.check (analyzer);
+               if (base_type != null) {
+                       base_type.check (analyzer);
 
-                       if (!(type is StructValueType)) {
+                       if (!(base_type is StructValueType)) {
                                error = true;
-                               Report.error (source_reference, "The base type `%s` of struct `%s` is not a struct".printf (type.to_string (), get_full_name ()));
+                               Report.error (source_reference, "The base type `%s` of struct `%s` is not a struct".printf (base_type.to_string (), get_full_name ()));
                                return false;
                        }
                }
@@ -690,20 +680,20 @@ public class Vala.Struct : TypeSymbol {
                foreach (TypeParameter p in type_parameters) {
                        p.check (analyzer);
                }
-               
+
                foreach (Field f in fields) {
                        f.check (analyzer);
                }
-               
+
                foreach (Constant c in constants) {
                        c.check (analyzer);
                }
-               
+
                foreach (Method m in methods) {
                        m.check (analyzer);
                }
 
-               if (!external && !external_package && get_base_types ().size == 0 && get_fields ().size == 0) {
+               if (!external && !external_package && base_type == null && get_fields ().size == 0) {
                        Report.error (source_reference, "structs cannot be empty");
                }
 
index 7e189e5aac498a559ee7f18aadb5070fd496a230..58af9f14aa09c74a7a39930ac6e69882a5529c3a 100644 (file)
@@ -83,6 +83,17 @@ public class Vala.SymbolResolver : CodeVisitor {
 
                st.accept_children (this);
 
+               if (st.base_type != null) {
+                       var base_type = st.base_type.data_type as Struct;
+                       if (base_type != null) {
+                               if (base_type.is_subtype_of (st)) {
+                                       st.error = true;
+                                       Report.error (base_type.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
+                                       return;
+                               }
+                       }
+               }
+
                current_scope = current_scope.parent_scope;
        }
 
index f6707afc73b8a35fa4e2565e98575bee70db3003..c3b070b7e3f87d708082872c3815b1b92601c782 100644 (file)
@@ -232,7 +232,7 @@ public class Vala.GirParser : CodeVisitor {
                start_element ("alias");
                var st = new Struct (reader.get_attribute ("name"), get_current_src ());
                st.access = SymbolAccessibility.PUBLIC;
-               st.add_base_type (parse_type_from_name (reader.get_attribute ("target")));
+               st.base_type = parse_type_from_name (reader.get_attribute ("target"));
                next ();
                end_element ("alias");
                return st;