+2008-03-22 Jürg Billeter <j@bitron.ch>
+
+ * vala/valascope.vala, vala/valasemanticanalyzer.vala,
+ vala/valasymbol.vala: check accessiblity of parameter and return
+ types, fixes bug 433290
+
2008-03-21 Jürg Billeter <j@bitron.ch>
* vapi/Makefile.am, vapi/sdl-gfx.vapi, vapi/sdl-image.vapi,
/* valascope.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter
+ * Copyright (C) 2006-2008 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
}
return sym;
}
+
+ /**
+ * Returns whether the specified scope is an ancestor of this scope.
+ *
+ * @param scope a scope or null for the root scope
+ * @return true if this scope is a subscope of the specified
+ * scope, false otherwise
+ */
+ public bool is_subscope_of (Scope? scope) {
+ if (scope == this) {
+ return true;
+ }
+
+ // null scope is the root scope
+ if (scope == null) {
+ return true;
+ }
+
+ if (parent_scope != null) {
+ return parent_scope.is_subscope_of (scope);
+ }
+
+ return false;
+ }
}
}
}
+ // check whether return type is at least as accessible as the method
+ if (!is_type_accessible (m, m.return_type)) {
+ m.error = true;
+ Report.error (m.source_reference, "return type `%s` is less accessible than method `%s`".printf (m.return_type.to_string (), m.get_full_name ()));
+ return;
+ }
+
foreach (Expression precondition in m.get_preconditions ()) {
if (precondition.error) {
// if there was an error in the precondition, skip this check
current_source_file.add_type_dependency (p.type_reference, SourceFileDependencyType.HEADER_SHALLOW);
}
current_source_file.add_type_dependency (p.type_reference, SourceFileDependencyType.SOURCE);
+
+ // check whether parameter type is at least as accessible as the method
+ if (!is_type_accessible (p, p.type_reference)) {
+ p.error = true;
+ Report.error (p.source_reference, "parameter type `%s` is less accessible than method `%s`".printf (p.type_reference.to_string (), p.parent_symbol.get_full_name ()));
+ return;
+ }
}
/* special treatment for construct formal parameters used in creation methods */
}
}
+ // check whether type is at least as accessible as the specified symbol
+ private bool is_type_accessible (Symbol sym, DataType type) {
+ foreach (Symbol type_symbol in type.get_symbols ()) {
+ Scope method_scope = sym.get_top_accessible_scope ();
+ Scope type_scope = type_symbol.get_top_accessible_scope ();
+ if ((method_scope == null && type_scope != null)
+ || (method_scope != null && !method_scope.is_subscope_of (type_scope))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
private void find_base_class_property (Property! prop, Class! cl) {
var sym = cl.scope.lookup (prop.name);
if (sym is Property) {
return result.str;
}
+
+ // get the top scope from where this symbol is still accessible
+ public Scope? get_top_accessible_scope () {
+ if (access != SymbolAccessibility.PUBLIC) {
+ // private symbols are accessible within the scope where the symbol has been declared
+ Scope scope = owner;
+
+ // skip scopes of normal namespaces, they don't influence accessibility
+ while (scope != null && scope.owner is Namespace && scope.owner.name != null) {
+ scope = scope.parent_scope;
+ }
+
+ return scope;
+ }
+
+ if (parent_symbol == null) {
+ return null;
+ }
+
+ // if this is a public symbol, it's equally accessible as the parent symbol
+ return parent_symbol.get_top_accessible_scope ();
+ }
}
public enum Vala.SymbolAccessibility {