From 7e12e84485fe177458d40303f8a7c8945244a5a8 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Sat, 22 Mar 2008 20:17:22 +0000 Subject: [PATCH] check accessiblity of parameter and return types, fixes bug 433290 2008-03-22 Juerg Billeter * vala/valascope.vala, vala/valasemanticanalyzer.vala, vala/valasymbol.vala: check accessiblity of parameter and return types, fixes bug 433290 svn path=/trunk/; revision=1148 --- ChangeLog | 6 ++++++ vala/valascope.vala | 26 +++++++++++++++++++++++++- vala/valasemanticanalyzer.vala | 28 ++++++++++++++++++++++++++++ vala/valasymbol.vala | 22 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f92435f..c33dcb0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-03-22 Jürg Billeter + + * 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 * vapi/Makefile.am, vapi/sdl-gfx.vapi, vapi/sdl-image.vapi, diff --git a/vala/valascope.vala b/vala/valascope.vala index 8bd9a30..a223ba4 100644 --- a/vala/valascope.vala +++ b/vala/valascope.vala @@ -1,6 +1,6 @@ /* 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 @@ -86,5 +86,29 @@ public class Vala.Scope : Object { } 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; + } } diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 257ea83..45257a0 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -411,6 +411,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } + // 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 @@ -519,6 +526,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { 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 */ @@ -537,6 +551,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } + // 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) { diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala index 3883ceb..a63b96d 100644 --- a/vala/valasymbol.vala +++ b/vala/valasymbol.vala @@ -218,6 +218,28 @@ public abstract class Vala.Symbol : CodeNode { 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 { -- 2.7.4