]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Move member access checking to MemberAccess.check
authorJürg Billeter <j@bitron.ch>
Wed, 5 Nov 2008 21:54:46 +0000 (21:54 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 5 Nov 2008 21:54:46 +0000 (21:54 +0000)
2008-11-05  Jürg Billeter  <j@bitron.ch>

* vala/valamemberaccess.vala:
* vala/valasemanticanalyzer.vala:

Move member access checking to MemberAccess.check

svn path=/trunk/; revision=1986

ChangeLog
vala/valamemberaccess.vala
vala/valasemanticanalyzer.vala

index 800c38106f9cb4ecf1e929939ff6e71542c67829..7c17eb0fb71a21fb3c95a0bf423399ff32d0f911 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-11-05  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valamemberaccess.vala:
+       * vala/valasemanticanalyzer.vala:
+
+       Move member access checking to MemberAccess.check
+
 2008-11-05  Jürg Billeter  <j@bitron.ch>
 
        * vala/valabinaryexpression.vala:
index 7436f067c2a4094a5d692749876b513e6fa830df..153453a4bbd9c9afab9cfe4b6eb3950634d7d708 100644 (file)
@@ -174,4 +174,355 @@ public class Vala.MemberAccess : Expression {
                        return false;
                }
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               Symbol base_symbol = null;
+               FormalParameter this_parameter = null;
+               bool may_access_instance_members = false;
+
+               symbol_reference = null;
+
+               if (qualified) {
+                       base_symbol = analyzer.root_symbol;
+                       symbol_reference = analyzer.root_symbol.scope.lookup (member_name);
+               } else if (inner == null) {
+                       if (member_name == "this") {
+                               if (!analyzer.is_in_instance_method ()) {
+                                       error = true;
+                                       Report.error (source_reference, "This access invalid outside of instance methods");
+                                       return false;
+                               }
+                       }
+
+                       base_symbol = analyzer.current_symbol;
+
+                       var sym = analyzer.current_symbol;
+                       while (sym != null && symbol_reference == null) {
+                               if (this_parameter == null) {
+                                       if (sym is CreationMethod) {
+                                               var cm = (CreationMethod) sym;
+                                               this_parameter = cm.this_parameter;
+                                               may_access_instance_members = true;
+                                       } else if (sym is Property) {
+                                               var prop = (Property) sym;
+                                               this_parameter = prop.this_parameter;
+                                               may_access_instance_members = true;
+                                       } else if (sym is Constructor) {
+                                               var c = (Constructor) sym;
+                                               this_parameter = c.this_parameter;
+                                               may_access_instance_members = true;
+                                       } else if (sym is Destructor) {
+                                               var d = (Destructor) sym;
+                                               this_parameter = d.this_parameter;
+                                               may_access_instance_members = true;
+                                       } else if (sym is Method) {
+                                               var m = (Method) sym;
+                                               this_parameter = m.this_parameter;
+                                               may_access_instance_members = (m.binding == MemberBinding.INSTANCE);
+                                       }
+                               }
+
+                               symbol_reference = analyzer.symbol_lookup_inherited (sym, member_name);
+                               sym = sym.parent_symbol;
+                       }
+
+                       if (symbol_reference == null) {
+                               foreach (UsingDirective ns in analyzer.current_using_directives) {
+                                       var local_sym = ns.namespace_symbol.scope.lookup (member_name);
+                                       if (local_sym != null) {
+                                               if (symbol_reference != null) {
+                                                       error = true;
+                                                       Report.error (source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (member_name, symbol_reference.get_full_name (), local_sym.get_full_name ()));
+                                                       return false;
+                                               }
+                                               symbol_reference = local_sym;
+                                       }
+                               }
+                       }
+               } else {
+                       if (inner.error) {
+                               /* if there was an error in the inner expression, skip this check */
+                               error = true;
+                               return false;
+                       }
+
+                       if (pointer_member_access) {
+                               var pointer_type = inner.value_type as PointerType;
+                               if (pointer_type != null && pointer_type.base_type is ValueType) {
+                                       // transform foo->bar to (*foo).bar
+                                       inner = new PointerIndirection (inner, source_reference);
+                                       inner.accept (analyzer);
+                                       pointer_member_access = false;
+                               }
+                       }
+
+                       if (inner is MemberAccess) {
+                               var ma = (MemberAccess) inner;
+                               if (ma.prototype_access) {
+                                       error = true;
+                                       Report.error (source_reference, "Access to instance member `%s' denied".printf (inner.symbol_reference.get_full_name ()));
+                                       return false;
+                               }
+                       }
+
+                       if (inner is MemberAccess || inner is BaseAccess) {
+                               base_symbol = inner.symbol_reference;
+
+                               if (symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
+                                       symbol_reference = base_symbol.scope.lookup (member_name);
+                                       if (inner is BaseAccess) {
+                                               // inner expression is base access
+                                               // access to instance members of the base type possible
+                                               may_access_instance_members = true;
+                                       }
+                               }
+                       }
+
+                       if (symbol_reference == null && inner.value_type != null) {
+                               if (pointer_member_access) {
+                                       symbol_reference = inner.value_type.get_pointer_member (member_name);
+                               } else {
+                                       if (inner.value_type.data_type != null) {
+                                               base_symbol = inner.value_type.data_type;
+                                       }
+                                       symbol_reference = inner.value_type.get_member (member_name);
+                               }
+                               if (symbol_reference != null) {
+                                       // inner expression is variable, field, or parameter
+                                       // access to instance members of the corresponding type possible
+                                       may_access_instance_members = true;
+                               }
+                       }
+
+                       if (symbol_reference == null && inner.value_type != null && inner.value_type.is_dynamic) {
+                               // allow late bound members for dynamic types
+                               var dynamic_object_type = (ObjectType) inner.value_type;
+                               if (parent_node is InvocationExpression) {
+                                       var invoc = (InvocationExpression) parent_node;
+                                       if (invoc.call == this) {
+                                               // dynamic method
+                                               DataType ret_type;
+                                               if (invoc.target_type != null) {
+                                                       ret_type = invoc.target_type.copy ();
+                                                       ret_type.value_owned = true;
+                                               } else if (invoc.parent_node is ExpressionStatement) {
+                                                       ret_type = new VoidType ();
+                                               } else {
+                                                       // expect dynamic object of the same type
+                                                       ret_type = inner.value_type.copy ();
+                                               }
+                                               var m = new DynamicMethod (inner.value_type, member_name, ret_type, source_reference);
+                                               m.invocation = invoc;
+                                               m.add_error_type (new ErrorType (null, null));
+                                               m.access = SymbolAccessibility.PUBLIC;
+                                               m.add_parameter (new FormalParameter.with_ellipsis ());
+                                               dynamic_object_type.type_symbol.scope.add (null, m);
+                                               symbol_reference = m;
+                                       }
+                               } else if (parent_node is Assignment) {
+                                       var a = (Assignment) parent_node;
+                                       if (a.left == this
+                                           && (a.operator == AssignmentOperator.ADD
+                                               || a.operator == AssignmentOperator.SUB)) {
+                                               // dynamic signal
+                                               var s = new DynamicSignal (inner.value_type, member_name, new VoidType (), source_reference);
+                                               s.handler = a.right;
+                                               s.access = SymbolAccessibility.PUBLIC;
+                                               dynamic_object_type.type_symbol.scope.add (null, s);
+                                               symbol_reference = s;
+                                       } else if (a.left == this) {
+                                               // dynamic property assignment
+                                               var prop = new DynamicProperty (inner.value_type, member_name, source_reference);
+                                               prop.access = SymbolAccessibility.PUBLIC;
+                                               prop.set_accessor = new PropertyAccessor (false, true, false, null, prop.source_reference);
+                                               prop.set_accessor.access = SymbolAccessibility.PUBLIC;
+                                               prop.owner = inner.value_type.data_type.scope;
+                                               dynamic_object_type.type_symbol.scope.add (null, prop);
+                                               symbol_reference = prop;
+                                       }
+                               }
+                               if (symbol_reference == null) {
+                                       // dynamic property read access
+                                       var prop = new DynamicProperty (inner.value_type, member_name, source_reference);
+                                       if (target_type != null) {
+                                               prop.property_type = target_type;
+                                       } else {
+                                               // expect dynamic object of the same type
+                                               prop.property_type = inner.value_type.copy ();
+                                       }
+                                       prop.access = SymbolAccessibility.PUBLIC;
+                                       prop.get_accessor = new PropertyAccessor (true, false, false, null, prop.source_reference);
+                                       prop.get_accessor.access = SymbolAccessibility.PUBLIC;
+                                       prop.owner = inner.value_type.data_type.scope;
+                                       dynamic_object_type.type_symbol.scope.add (null, prop);
+                                       symbol_reference = prop;
+                               }
+                               if (symbol_reference != null) {
+                                       may_access_instance_members = true;
+                               }
+                       }
+               }
+
+               if (symbol_reference == null) {
+                       error = true;
+
+                       string base_type_name = "(null)";
+                       if (inner != null && inner.value_type != null) {
+                               base_type_name = inner.value_type.to_string ();
+                       } else if (base_symbol != null) {
+                               base_type_name = base_symbol.get_full_name ();
+                       }
+
+                       Report.error (source_reference, "The name `%s' does not exist in the context of `%s'".printf (member_name, base_type_name));
+                       return false;
+               }
+
+               var member = symbol_reference;
+               var access = SymbolAccessibility.PUBLIC;
+               bool instance = false;
+               bool klass = false;
+               if (member is Field) {
+                       var f = (Field) member;
+                       access = f.access;
+                       instance = (f.binding == MemberBinding.INSTANCE);
+                       klass = (f.binding == MemberBinding.CLASS);
+               } else if (member is Method) {
+                       var m = (Method) member;
+                       access = m.access;
+                       if (!(m is CreationMethod)) {
+                               instance = (m.binding == MemberBinding.INSTANCE);
+                       }
+                       klass = (m.binding == MemberBinding.CLASS);
+               } else if (member is Property) {
+                       var prop = (Property) member;
+                       if (!prop.check (analyzer)) {
+                               error = true;
+                               return false;
+                       }
+                       access = prop.access;
+                       if (lvalue) {
+                               if (prop.set_accessor == null) {
+                                       error = true;
+                                       Report.error (source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
+                                       return false;
+                               }
+                               if (prop.access == SymbolAccessibility.PUBLIC) {
+                                       access = prop.set_accessor.access;
+                               } else if (prop.access == SymbolAccessibility.PROTECTED
+                                          && prop.set_accessor.access != SymbolAccessibility.PUBLIC) {
+                                       access = prop.set_accessor.access;
+                               }
+                       } else {
+                               if (prop.get_accessor == null) {
+                                       error = true;
+                                       Report.error (source_reference, "Property `%s' is write-only".printf (prop.get_full_name ()));
+                                       return false;
+                               }
+                               if (prop.access == SymbolAccessibility.PUBLIC) {
+                                       access = prop.get_accessor.access;
+                               } else if (prop.access == SymbolAccessibility.PROTECTED
+                                          && prop.get_accessor.access != SymbolAccessibility.PUBLIC) {
+                                       access = prop.get_accessor.access;
+                               }
+                       }
+                       instance = (prop.binding == MemberBinding.INSTANCE);
+               } else if (member is Signal) {
+                       instance = true;
+               }
+
+               if (access == SymbolAccessibility.PRIVATE) {
+                       var target_type = member.parent_symbol;
+
+                       bool in_target_type = false;
+                       for (Symbol this_symbol = analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
+                               if (target_type == this_symbol) {
+                                       in_target_type = true;
+                                       break;
+                               }
+                       }
+
+                       if (!in_target_type) {
+                               error = true;
+                               Report.error (source_reference, "Access to private member `%s' denied".printf (member.get_full_name ()));
+                               return false;
+                       }
+               }
+               if ((instance || klass) && !may_access_instance_members) {
+                       prototype_access = true;
+
+                       if (symbol_reference is Method) {
+                               // also set static type for prototype access
+                               // required when using instance methods as delegates in constants
+                               // TODO replace by MethodPrototype
+                               value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
+                       } else if (symbol_reference is Field) {
+                               value_type = new FieldPrototype ((Field) symbol_reference);
+                       }
+               } else {
+                       // implicit this access
+                       if (instance && inner == null) {
+                               inner = new MemberAccess (null, "this", source_reference);
+                               inner.value_type = this_parameter.parameter_type.copy ();
+                               inner.symbol_reference = this_parameter;
+                       }
+
+                       value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
+
+                       // resolve generic return values
+                       if (value_type != null && value_type.type_parameter != null) {
+                               if (inner != null) {
+                                       value_type = analyzer.get_actual_type (inner.value_type, symbol_reference, value_type, this);
+                                       if (value_type == null) {
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       if (symbol_reference is Method) {
+                               var m = (Method) symbol_reference;
+
+                               Method base_method;
+                               if (m.base_method != null) {
+                                       base_method = m.base_method;
+                               } else if (m.base_interface_method != null) {
+                                       base_method = m.base_interface_method;
+                               } else {
+                                       base_method = m;
+                               }
+
+                               if (instance && base_method.parent_symbol != null) {
+                                       inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) base_method.parent_symbol);
+                               }
+                       } else if (symbol_reference is Property) {
+                               var prop = (Property) symbol_reference;
+
+                               Property base_property;
+                               if (prop.base_property != null) {
+                                       base_property = prop.base_property;
+                               } else if (prop.base_interface_property != null) {
+                                       base_property = prop.base_interface_property;
+                               } else {
+                                       base_property = prop;
+                               }
+
+                               if (instance && base_property.parent_symbol != null) {
+                                       inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) base_property.parent_symbol);
+                               }
+                       } else if ((symbol_reference is Field
+                                   || symbol_reference is Signal)
+                                  && instance && symbol_reference.parent_symbol != null) {
+                               inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) symbol_reference.parent_symbol);
+                       }
+               }
+
+               analyzer.current_source_file.add_symbol_dependency (symbol_reference, SourceFileDependencyType.SOURCE);
+
+               return !error;
+       }
 }
index 6d5a4d6b0bb0b231f48142067edf292691614dd9..e63803687f931e989bb2e323c285e7630de29520 100644 (file)
@@ -30,14 +30,14 @@ using Gee;
 public class Vala.SemanticAnalyzer : CodeVisitor {
        public CodeContext context { get; set; }
 
-       Symbol root_symbol;
+       public Symbol root_symbol;
        public Symbol current_symbol { get; set; }
        public SourceFile current_source_file { get; set; }
        DataType current_return_type;
        Class current_class;
        Struct current_struct;
 
-       Gee.List<UsingDirective> current_using_directives;
+       public Gee.List<UsingDirective> current_using_directives;
 
        public DataType bool_type;
        public DataType string_type;
@@ -1401,7 +1401,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                expr.value_type = new NullType (expr.source_reference);
        }
 
-       private DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
+       public DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
                if (sym is Field) {
                        var f = (Field) sym;
                        var type = f.field_type.copy ();
@@ -1525,346 +1525,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
        
        public override void visit_member_access (MemberAccess expr) {
-               Symbol base_symbol = null;
-               FormalParameter this_parameter = null;
-               bool may_access_instance_members = false;
-
-               expr.symbol_reference = null;
-
-               if (expr.qualified) {
-                       base_symbol = root_symbol;
-                       expr.symbol_reference = root_symbol.scope.lookup (expr.member_name);
-               } else if (expr.inner == null) {
-                       if (expr.member_name == "this") {
-                               if (!is_in_instance_method ()) {
-                                       expr.error = true;
-                                       Report.error (expr.source_reference, "This access invalid outside of instance methods");
-                                       return;
-                               }
-                       }
-
-                       base_symbol = current_symbol;
-
-                       var sym = current_symbol;
-                       while (sym != null && expr.symbol_reference == null) {
-                               if (this_parameter == null) {
-                                       if (sym is CreationMethod) {
-                                               var cm = (CreationMethod) sym;
-                                               this_parameter = cm.this_parameter;
-                                               may_access_instance_members = true;
-                                       } else if (sym is Property) {
-                                               var prop = (Property) sym;
-                                               this_parameter = prop.this_parameter;
-                                               may_access_instance_members = true;
-                                       } else if (sym is Constructor) {
-                                               var c = (Constructor) sym;
-                                               this_parameter = c.this_parameter;
-                                               may_access_instance_members = true;
-                                       } else if (sym is Destructor) {
-                                               var d = (Destructor) sym;
-                                               this_parameter = d.this_parameter;
-                                               may_access_instance_members = true;
-                                       } else if (sym is Method) {
-                                               var m = (Method) sym;
-                                               this_parameter = m.this_parameter;
-                                               may_access_instance_members = (m.binding == MemberBinding.INSTANCE);
-                                       }
-                               }
-
-                               expr.symbol_reference = symbol_lookup_inherited (sym, expr.member_name);
-                               sym = sym.parent_symbol;
-                       }
-
-                       if (expr.symbol_reference == null) {
-                               foreach (UsingDirective ns in current_using_directives) {
-                                       var local_sym = ns.namespace_symbol.scope.lookup (expr.member_name);
-                                       if (local_sym != null) {
-                                               if (expr.symbol_reference != null) {
-                                                       expr.error = true;
-                                                       Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ()));
-                                                       return;
-                                               }
-                                               expr.symbol_reference = local_sym;
-                                       }
-                               }
-                       }
-               } else {
-                       if (expr.inner.error) {
-                               /* if there was an error in the inner expression, skip this check */
-                               expr.error = true;
-                               return;
-                       }
-
-                       if (expr.pointer_member_access) {
-                               var pointer_type = expr.inner.value_type as PointerType;
-                               if (pointer_type != null && pointer_type.base_type is ValueType) {
-                                       // transform foo->bar to (*foo).bar
-                                       expr.inner = new PointerIndirection (expr.inner, expr.source_reference);
-                                       expr.inner.accept (this);
-                                       expr.pointer_member_access = false;
-                               }
-                       }
-
-                       if (expr.inner is MemberAccess) {
-                               var ma = (MemberAccess) expr.inner;
-                               if (ma.prototype_access) {
-                                       expr.error = true;
-                                       Report.error (expr.source_reference, "Access to instance member `%s' denied".printf (expr.inner.symbol_reference.get_full_name ()));
-                                       return;
-                               }
-                       }
-
-                       if (expr.inner is MemberAccess || expr.inner is BaseAccess) {
-                               base_symbol = expr.inner.symbol_reference;
-
-                               if (expr.symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
-                                       expr.symbol_reference = base_symbol.scope.lookup (expr.member_name);
-                                       if (expr.inner is BaseAccess) {
-                                               // inner expression is base access
-                                               // access to instance members of the base type possible
-                                               may_access_instance_members = true;
-                                       }
-                               }
-                       }
-
-                       if (expr.symbol_reference == null && expr.inner.value_type != null) {
-                               if (expr.pointer_member_access) {
-                                       expr.symbol_reference = expr.inner.value_type.get_pointer_member (expr.member_name);
-                               } else {
-                                       if (expr.inner.value_type.data_type != null) {
-                                               base_symbol = expr.inner.value_type.data_type;
-                                       }
-                                       expr.symbol_reference = expr.inner.value_type.get_member (expr.member_name);
-                               }
-                               if (expr.symbol_reference != null) {
-                                       // inner expression is variable, field, or parameter
-                                       // access to instance members of the corresponding type possible
-                                       may_access_instance_members = true;
-                               }
-                       }
-
-                       if (expr.symbol_reference == null && expr.inner.value_type != null && expr.inner.value_type.is_dynamic) {
-                               // allow late bound members for dynamic types
-                               var dynamic_object_type = (ObjectType) expr.inner.value_type;
-                               if (expr.parent_node is InvocationExpression) {
-                                       var invoc = (InvocationExpression) expr.parent_node;
-                                       if (invoc.call == expr) {
-                                               // dynamic method
-                                               DataType ret_type;
-                                               if (invoc.target_type != null) {
-                                                       ret_type = invoc.target_type.copy ();
-                                                       ret_type.value_owned = true;
-                                               } else if (invoc.parent_node is ExpressionStatement) {
-                                                       ret_type = new VoidType ();
-                                               } else {
-                                                       // expect dynamic object of the same type
-                                                       ret_type = expr.inner.value_type.copy ();
-                                               }
-                                               var m = new DynamicMethod (expr.inner.value_type, expr.member_name, ret_type, expr.source_reference);
-                                               m.invocation = invoc;
-                                               m.add_error_type (new ErrorType (null, null));
-                                               m.access = SymbolAccessibility.PUBLIC;
-                                               m.add_parameter (new FormalParameter.with_ellipsis ());
-                                               dynamic_object_type.type_symbol.scope.add (null, m);
-                                               expr.symbol_reference = m;
-                                       }
-                               } else if (expr.parent_node is Assignment) {
-                                       var a = (Assignment) expr.parent_node;
-                                       if (a.left == expr
-                                           && (a.operator == AssignmentOperator.ADD
-                                               || a.operator == AssignmentOperator.SUB)) {
-                                               // dynamic signal
-                                               var s = new DynamicSignal (expr.inner.value_type, expr.member_name, new VoidType (), expr.source_reference);
-                                               s.handler = a.right;
-                                               s.access = SymbolAccessibility.PUBLIC;
-                                               dynamic_object_type.type_symbol.scope.add (null, s);
-                                               expr.symbol_reference = s;
-                                       } else if (a.left == expr) {
-                                               // dynamic property assignment
-                                               var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
-                                               prop.access = SymbolAccessibility.PUBLIC;
-                                               prop.set_accessor = new PropertyAccessor (false, true, false, null, prop.source_reference);
-                                               prop.set_accessor.access = SymbolAccessibility.PUBLIC;
-                                               prop.owner = expr.inner.value_type.data_type.scope;
-                                               dynamic_object_type.type_symbol.scope.add (null, prop);
-                                               expr.symbol_reference = prop;
-                                       }
-                               }
-                               if (expr.symbol_reference == null) {
-                                       // dynamic property read access
-                                       var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
-                                       if (expr.target_type != null) {
-                                               prop.property_type = expr.target_type;
-                                       } else {
-                                               // expect dynamic object of the same type
-                                               prop.property_type = expr.inner.value_type.copy ();
-                                       }
-                                       prop.access = SymbolAccessibility.PUBLIC;
-                                       prop.get_accessor = new PropertyAccessor (true, false, false, null, prop.source_reference);
-                                       prop.get_accessor.access = SymbolAccessibility.PUBLIC;
-                                       prop.owner = expr.inner.value_type.data_type.scope;
-                                       dynamic_object_type.type_symbol.scope.add (null, prop);
-                                       expr.symbol_reference = prop;
-                               }
-                               if (expr.symbol_reference != null) {
-                                       may_access_instance_members = true;
-                               }
-                       }
-               }
-
-               if (expr.symbol_reference == null) {
-                       expr.error = true;
-
-                       string base_type_name = "(null)";
-                       if (expr.inner != null && expr.inner.value_type != null) {
-                               base_type_name = expr.inner.value_type.to_string ();
-                       } else if (base_symbol != null) {
-                               base_type_name = base_symbol.get_full_name ();
-                       }
-
-                       Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_type_name));
-                       return;
-               }
-
-               var member = expr.symbol_reference;
-               var access = SymbolAccessibility.PUBLIC;
-               bool instance = false;
-               bool klass = false;
-               if (member is Field) {
-                       var f = (Field) member;
-                       access = f.access;
-                       instance = (f.binding == MemberBinding.INSTANCE);
-                       klass = (f.binding == MemberBinding.CLASS);
-               } else if (member is Method) {
-                       var m = (Method) member;
-                       access = m.access;
-                       if (!(m is CreationMethod)) {
-                               instance = (m.binding == MemberBinding.INSTANCE);
-                       }
-                       klass = (m.binding == MemberBinding.CLASS);
-               } else if (member is Property) {
-                       var prop = (Property) member;
-                       if (!prop.check (this)) {
-                               expr.error = true;
-                               return;
-                       }
-                       access = prop.access;
-                       if (expr.lvalue) {
-                               if (prop.set_accessor == null) {
-                                       expr.error = true;
-                                       Report.error (expr.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
-                                       return;
-                               }
-                               if (prop.access == SymbolAccessibility.PUBLIC) {
-                                       access = prop.set_accessor.access;
-                               } else if (prop.access == SymbolAccessibility.PROTECTED
-                                          && prop.set_accessor.access != SymbolAccessibility.PUBLIC) {
-                                       access = prop.set_accessor.access;
-                               }
-                       } else {
-                               if (prop.get_accessor == null) {
-                                       expr.error = true;
-                                       Report.error (expr.source_reference, "Property `%s' is write-only".printf (prop.get_full_name ()));
-                                       return;
-                               }
-                               if (prop.access == SymbolAccessibility.PUBLIC) {
-                                       access = prop.get_accessor.access;
-                               } else if (prop.access == SymbolAccessibility.PROTECTED
-                                          && prop.get_accessor.access != SymbolAccessibility.PUBLIC) {
-                                       access = prop.get_accessor.access;
-                               }
-                       }
-                       instance = (prop.binding == MemberBinding.INSTANCE);
-               } else if (member is Signal) {
-                       instance = true;
-               }
-
-               if (access == SymbolAccessibility.PRIVATE) {
-                       var target_type = member.parent_symbol;
-
-                       bool in_target_type = false;
-                       for (Symbol this_symbol = current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
-                               if (target_type == this_symbol) {
-                                       in_target_type = true;
-                                       break;
-                               }
-                       }
-
-                       if (!in_target_type) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Access to private member `%s' denied".printf (member.get_full_name ()));
-                               return;
-                       }
-               }
-               if ((instance || klass) && !may_access_instance_members) {
-                       expr.prototype_access = true;
-
-                       if (expr.symbol_reference is Method) {
-                               // also set static type for prototype access
-                               // required when using instance methods as delegates in constants
-                               // TODO replace by MethodPrototype
-                               expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
-                       } else if (expr.symbol_reference is Field) {
-                               expr.value_type = new FieldPrototype ((Field) expr.symbol_reference);
-                       }
-               } else {
-                       // implicit this access
-                       if (instance && expr.inner == null) {
-                               expr.inner = new MemberAccess (null, "this", expr.source_reference);
-                               expr.inner.value_type = this_parameter.parameter_type.copy ();
-                               expr.inner.symbol_reference = this_parameter;
-                       }
-
-                       expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
-
-                       // resolve generic return values
-                       if (expr.value_type != null && expr.value_type.type_parameter != null) {
-                               if (expr.inner != null) {
-                                       expr.value_type = get_actual_type (expr.inner.value_type, expr.symbol_reference, expr.value_type, expr);
-                                       if (expr.value_type == null) {
-                                               return;
-                                       }
-                               }
-                       }
-
-                       if (expr.symbol_reference is Method) {
-                               var m = (Method) expr.symbol_reference;
-
-                               Method base_method;
-                               if (m.base_method != null) {
-                                       base_method = m.base_method;
-                               } else if (m.base_interface_method != null) {
-                                       base_method = m.base_interface_method;
-                               } else {
-                                       base_method = m;
-                               }
-
-                               if (instance && base_method.parent_symbol != null) {
-                                       expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) base_method.parent_symbol);
-                               }
-                       } else if (expr.symbol_reference is Property) {
-                               var prop = (Property) expr.symbol_reference;
-
-                               Property base_property;
-                               if (prop.base_property != null) {
-                                       base_property = prop.base_property;
-                               } else if (prop.base_interface_property != null) {
-                                       base_property = prop.base_interface_property;
-                               } else {
-                                       base_property = prop;
-                               }
-
-                               if (instance && base_property.parent_symbol != null) {
-                                       expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) base_property.parent_symbol);
-                               }
-                       } else if ((expr.symbol_reference is Field
-                                   || expr.symbol_reference is Signal)
-                                  && instance && expr.symbol_reference.parent_symbol != null) {
-                               expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) expr.symbol_reference.parent_symbol);
-                       }
-               }
-
-               current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE);
+               expr.check (this);
        }
 
        public static DataType get_data_type_for_symbol (TypeSymbol sym) {
@@ -2594,7 +2255,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
-       private bool is_in_instance_method () {
+       public bool is_in_instance_method () {
                var sym = current_symbol;
                while (sym != null) {
                        if (sym is CreationMethod) {