Commit 9a669195 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Do not allow structs to have more than one base type and detect cycles,

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
parent efb68500
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/:
......
......@@ -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");
......
......@@ -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 ();
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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");
}
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment