From: Jürg Billeter Date: Fri, 16 Jan 2009 17:21:00 +0000 (+0000) Subject: Do not allow structs to have more than one base type and detect cycles, X-Git-Tag: VALA_0_5_6~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a669195374efd68859c70ed6034bcee257c0024;p=thirdparty%2Fvala.git Do not allow structs to have more than one base type and detect cycles, 2009-01-16 Jürg Billeter * 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 --- diff --git a/ChangeLog b/ChangeLog index 90c7f2a31..e07f2719a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2009-01-16 Jürg Billeter + + * 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 * vapi/packages/gtk+-2.0/: diff --git a/vala/valabaseaccess.vala b/vala/valabaseaccess.vala index 1de0c7a78..42f74b9a9 100644 --- a/vala/valabaseaccess.vala +++ b/vala/valabaseaccess.vala @@ -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 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"); diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index f3730406e..0aa35702d 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -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 (); diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala index 73273d038..9bbee34f2 100644 --- a/vala/valagenieparser.vala +++ b/vala/valagenieparser.vala @@ -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 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); diff --git a/vala/valaparser.vala b/vala/valaparser.vala index be5abb855..90e585b11 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -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 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); diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 3fb94451e..4efe18328 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -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; } diff --git a/vala/valastruct.vala b/vala/valastruct.vala index 9cfbe308e..b5ef8fb68 100644 --- a/vala/valastruct.vala +++ b/vala/valastruct.vala @@ -31,9 +31,8 @@ public class Vala.Struct : TypeSymbol { private Gee.List constants = new ArrayList (); private Gee.List fields = new ArrayList (); private Gee.List methods = new ArrayList (); + private DataType _base_type = null; - private Gee.List base_types = new ArrayList (); - 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 get_base_types () { - return new ReadOnlyList (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"); } diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index 7e189e5aa..58af9f14a 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -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; } diff --git a/vapigen/valagirparser.vala b/vapigen/valagirparser.vala index f6707afc7..c3b070b7e 100644 --- a/vapigen/valagirparser.vala +++ b/vapigen/valagirparser.vala @@ -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;