LCOV - code coverage report
Current view: top level - vala - valasemanticanalyzer.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 92.2 % 793 731
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valasemanticanalyzer.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * Code visitor analyzing and checking code.
      29              :  */
      30         4614 : public class Vala.SemanticAnalyzer : CodeVisitor {
      31         1538 :         CodeContext context;
      32              : 
      33     75737425 :         public Symbol? current_symbol { get; set; }
      34     67819635 :         public SourceFile current_source_file { get; set; }
      35              : 
      36              :         public TypeSymbol? current_type_symbol {
      37         3928 :                 get {
      38         3928 :                         unowned Symbol? sym = current_symbol;
      39        12204 :                         while (sym != null) {
      40        12204 :                                 if (sym is TypeSymbol) {
      41         3928 :                                         return (TypeSymbol) sym;
      42              :                                 }
      43         8276 :                                 sym = sym.parent_symbol;
      44              :                         }
      45         3928 :                         return null;
      46              :                 }
      47              :         }
      48              : 
      49              :         public Class? current_class {
      50         3906 :                 get { return current_type_symbol as Class; }
      51              :         }
      52              : 
      53              : 
      54              :         public Struct? current_struct {
      55           18 :                 get { return current_type_symbol as Struct; }
      56              :         }
      57              : 
      58              :         public Method? current_method {
      59       673011 :                 get {
      60       673011 :                         unowned Symbol? sym = current_symbol;
      61      1689757 :                         while (sym is Block) {
      62      1016746 :                                 sym = sym.parent_symbol;
      63              :                         }
      64       673011 :                         return sym as Method;
      65              :                 }
      66              :         }
      67              : 
      68              :         public Method? current_async_method {
      69           20 :                 get {
      70           20 :                         unowned Symbol? sym = current_symbol;
      71           44 :                         while (sym is Block || sym is Method) {
      72           44 :                                 unowned Method? m = sym as Method;
      73           22 :                                 if (m != null && m.coroutine) {
      74              :                                         break;
      75              :                                 }
      76              : 
      77           24 :                                 sym = sym.parent_symbol;
      78              :                         }
      79           20 :                         return sym as Method;
      80              :                 }
      81              :         }
      82              : 
      83              :         public PropertyAccessor? current_property_accessor {
      84        25310 :                 get {
      85        25310 :                         unowned Symbol? sym = current_symbol;
      86        50737 :                         while (sym is Block) {
      87        25427 :                                 sym = sym.parent_symbol;
      88              :                         }
      89        25310 :                         return sym as PropertyAccessor;
      90              :                 }
      91              :         }
      92              : 
      93              :         public Symbol? current_method_or_property_accessor {
      94       924955 :                 get {
      95       924955 :                         unowned Symbol? sym = current_symbol;
      96      2673184 :                         while (sym is Block) {
      97      1748229 :                                 sym = sym.parent_symbol;
      98              :                         }
      99       924955 :                         if (sym is Method) {
     100              :                                 return sym;
     101         6356 :                         } else if (sym is PropertyAccessor) {
     102              :                                 return sym;
     103              :                         } else {
     104              :                                 return null;
     105              :                         }
     106              :                 }
     107              :         }
     108              : 
     109              :         public DataType? current_return_type {
     110       672794 :                 get {
     111       672794 :                         unowned Method? m = current_method;
     112       672794 :                         if (m != null) {
     113       647505 :                                 return m.return_type;
     114              :                         }
     115              : 
     116        25289 :                         unowned PropertyAccessor? acc = current_property_accessor;
     117        25289 :                         if (acc != null) {
     118        25283 :                                 if (acc.readable) {
     119        25283 :                                         return acc.value_type;
     120              :                                 } else {
     121            0 :                                         return void_type;
     122              :                                 }
     123              :                         }
     124              : 
     125            6 :                         if (is_in_constructor () || is_in_destructor ()) {
     126            6 :                                 return void_type;
     127              :                         }
     128              : 
     129       672794 :                         return null;
     130              :                 }
     131              :         }
     132              : 
     133         1538 :         public Block insert_block;
     134              : 
     135         3076 :         public DataType void_type = new VoidType ();
     136         1538 :         public DataType bool_type;
     137         1538 :         public DataType char_type;
     138         1538 :         public DataType uchar_type;
     139         1538 :         public DataType short_type;
     140         1538 :         public DataType ushort_type;
     141         1538 :         public DataType int_type;
     142         1538 :         public DataType uint_type;
     143         1538 :         public DataType long_type;
     144         1538 :         public DataType ulong_type;
     145         1538 :         public DataType int8_type;
     146         1538 :         public DataType uint8_type;
     147         1538 :         public DataType int16_type;
     148         1538 :         public DataType uint16_type;
     149         1538 :         public DataType int32_type;
     150         1538 :         public DataType uint32_type;
     151         1538 :         public DataType size_t_type;
     152         1538 :         public DataType ssize_t_type;
     153         1538 :         public DataType unichar_type;
     154         1538 :         public DataType double_type;
     155         1538 :         public DataType string_type;
     156         1538 :         public DataType regex_type;
     157         1538 :         public DataType type_type;
     158         1538 :         public DataType va_list_type;
     159         1538 :         public Class object_type;
     160         1538 :         public StructValueType gvalue_type;
     161         1538 :         public ObjectType gvariant_type;
     162         1538 :         public DataType glist_type;
     163         1538 :         public DataType gslist_type;
     164         1538 :         public DataType garray_type;
     165         1538 :         public DataType gvaluearray_type;
     166         1538 :         public DataType genericarray_type;
     167         1538 :         public DataType gsequence_type;
     168         1538 :         public Class gerror_type;
     169         1538 :         public DataType list_type;
     170         1538 :         public DataType tuple_type;
     171         1538 :         public Class gsource_type;
     172         1538 :         public DataType delegate_target_type;
     173         1538 :         public DelegateType delegate_target_destroy_type;
     174         1538 :         public DelegateType generics_dup_func_type;
     175              : 
     176         1538 :         Delegate destroy_notify;
     177              : 
     178              :         // keep replaced alive to make sure they remain valid
     179              :         // for the whole execution of CodeNode.accept
     180         3076 :         public List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
     181              : 
     182         3076 :         public SemanticAnalyzer () {
     183              :         }
     184              : 
     185              :         /**
     186              :          * Analyze and check code in the specified context.
     187              :          *
     188              :          * @param context a code context
     189              :          */
     190         2846 :         public void analyze (CodeContext context) {
     191         1423 :                 this.context = context;
     192              : 
     193         1423 :                 var root_symbol = context.root;
     194              : 
     195         1423 :                 bool_type = new BooleanType ((Struct) root_symbol.scope.lookup ("bool"));
     196         1423 :                 char_type = new IntegerType ((Struct) root_symbol.scope.lookup ("char"));
     197         1423 :                 uchar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uchar"));
     198         1423 :                 short_type = new IntegerType ((Struct) root_symbol.scope.lookup ("short"));
     199         1423 :                 ushort_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ushort"));
     200         1423 :                 int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int"));
     201         1423 :                 uint_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint"));
     202         1423 :                 long_type = new IntegerType ((Struct) root_symbol.scope.lookup ("long"));
     203         1423 :                 ulong_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ulong"));
     204         1423 :                 int8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int8"));
     205         1423 :                 uint8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint8"));
     206         1423 :                 int16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int16"));
     207         1423 :                 uint16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint16"));
     208         1423 :                 int32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int32"));
     209         1423 :                 uint32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint32"));
     210         1423 :                 size_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("size_t"));
     211         1423 :                 ssize_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ssize_t"));
     212         1423 :                 double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
     213         1423 :                 string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
     214         1423 :                 va_list_type = new StructValueType ((Struct) root_symbol.scope.lookup ("va_list"));
     215              : 
     216         1423 :                 var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar");
     217         1423 :                 if (unichar_struct != null) {
     218         1415 :                         unichar_type = new IntegerType (unichar_struct);
     219              :                 }
     220              : 
     221         2838 :                 if (context.profile == Profile.GOBJECT) {
     222         1415 :                         var glib_ns = root_symbol.scope.lookup ("GLib");
     223              : 
     224         1415 :                         object_type = (Class) glib_ns.scope.lookup ("Object");
     225         1415 :                         type_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Type"));
     226         1415 :                         gvalue_type = new StructValueType ((Struct) glib_ns.scope.lookup ("Value"));
     227         1415 :                         gvariant_type = new ObjectType ((Class) glib_ns.scope.lookup ("Variant"));
     228              : 
     229         1415 :                         glist_type = new ObjectType ((Class) glib_ns.scope.lookup ("List"));
     230         1415 :                         gslist_type = new ObjectType ((Class) glib_ns.scope.lookup ("SList"));
     231         1415 :                         garray_type = new ObjectType ((Class) glib_ns.scope.lookup ("Array"));
     232         1415 :                         gvaluearray_type = new ObjectType ((Class) glib_ns.scope.lookup ("ValueArray"));
     233         1415 :                         genericarray_type = new ObjectType ((Class) glib_ns.scope.lookup ("GenericArray"));
     234         1415 :                         gsequence_type = new ObjectType ((Class) glib_ns.scope.lookup ("Sequence"));
     235              : 
     236         1415 :                         gerror_type = (Class) glib_ns.scope.lookup ("Error");
     237         1415 :                         regex_type = new ObjectType ((Class) glib_ns.scope.lookup ("Regex"));
     238              : 
     239         1415 :                         gsource_type = (Class) glib_ns.scope.lookup ("Source");
     240              : 
     241         1415 :                         delegate_target_type = new StructValueType ((Struct) glib_ns.scope.lookup ("pointer"));
     242         1415 :                         destroy_notify = (Delegate) glib_ns.scope.lookup ("DestroyNotify");
     243         1415 :                         delegate_target_destroy_type = new DelegateType (destroy_notify);
     244              : 
     245         1415 :                         generics_dup_func_type = new DelegateType ((Delegate) glib_ns.scope.lookup ("BoxedCopyFunc"));
     246              :                 } else {
     247            8 :                         delegate_target_type = new PointerType (new VoidType ());
     248            8 :                         destroy_notify = new Delegate ("ValaDestroyNotify", new VoidType ());
     249            8 :                         destroy_notify.add_parameter (new Parameter ("data", new PointerType (new VoidType ())));
     250            8 :                         destroy_notify.has_target = false;
     251            8 :                         destroy_notify.owner = context.root.scope;
     252            8 :                         delegate_target_destroy_type = new DelegateType (destroy_notify);
     253              :                 }
     254              : 
     255         1423 :                 current_symbol = root_symbol;
     256         1423 :                 context.root.check (context);
     257         1423 :                 context.accept (this);
     258              : 
     259         1423 :                 current_symbol = null;
     260         1423 :                 this.context = null;
     261              :         }
     262              : 
     263         6429 :         public override void visit_source_file (SourceFile file) {
     264         6429 :                 current_source_file = file;
     265              : 
     266         6429 :                 file.check (context);
     267              : 
     268         6429 :                 current_source_file = null;
     269              :         }
     270              : 
     271      1696067 :         public DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
     272      1696067 :                 if (sym is Field) {
     273       119505 :                         unowned Field f = (Field) sym;
     274       119505 :                         var type = f.variable_type.copy ();
     275       119505 :                         if (!lvalue) {
     276        98367 :                                 type.value_owned = false;
     277              :                         }
     278       119505 :                         return type;
     279      1576562 :                 } else if (sym is EnumValue) {
     280         8745 :                         return new EnumValueType ((Enum) sym.parent_symbol);
     281      1567817 :                 } else if (sym is Constant) {
     282       135245 :                         unowned Constant c = (Constant) sym;
     283       135245 :                         return c.type_reference.copy ();
     284      1432572 :                 } else if (sym is Property) {
     285        36351 :                         unowned Property prop = (Property) sym;
     286        36351 :                         if (lvalue) {
     287         1532 :                                 if (prop.set_accessor != null && prop.set_accessor.value_type != null) {
     288         1528 :                                         return prop.set_accessor.value_type.copy ();
     289              :                                 }
     290              :                         } else {
     291        34819 :                                 if (prop.get_accessor != null && prop.get_accessor.value_type != null) {
     292        34819 :                                         return prop.get_accessor.value_type.copy ();
     293              :                                 }
     294              :                         }
     295      1396221 :                 } else if (sym is Parameter) {
     296       485822 :                         unowned Parameter p = (Parameter) sym;
     297       485822 :                         var type = p.variable_type.copy ();
     298       485822 :                         if (!lvalue) {
     299       417646 :                                 type.value_owned = false;
     300              :                         }
     301       485822 :                         return type;
     302       910399 :                 } else if (sym is LocalVariable) {
     303       441844 :                         unowned LocalVariable local = (LocalVariable) sym;
     304       441844 :                         var type = local.variable_type.copy ();
     305       441844 :                         if (!lvalue) {
     306       285683 :                                 type.value_owned = false;
     307              :                         }
     308       441844 :                         return type;
     309       468555 :                 } else if (sym is Method) {
     310       184144 :                         return new MethodType ((Method) sym);
     311       284411 :                 } else if (sym is Signal) {
     312          206 :                         return new SignalType ((Signal) sym);
     313              :                 }
     314      1696067 :                 return null;
     315              :         }
     316              : 
     317      4451587 :         public static Symbol? symbol_lookup_inherited (Symbol sym, string name) {
     318      4451587 :                 var result = sym.scope.lookup (name);
     319      4451587 :                 if (result != null) {
     320      4451587 :                         return result;
     321              :                 }
     322              : 
     323      3047350 :                 if (sym is Class) {
     324       847594 :                         unowned Class cl = (Class) sym;
     325              :                         // first check interfaces without prerequisites
     326              :                         // (prerequisites can be assumed to be met already)
     327      1878178 :                         foreach (DataType base_type in cl.get_base_types ()) {
     328       515866 :                                 if (base_type.type_symbol is Interface) {
     329       108307 :                                         result = base_type.type_symbol.scope.lookup (name);
     330       108307 :                                         if (result != null) {
     331          574 :                                                 return result;
     332              :                                         }
     333              :                                 }
     334              :                         }
     335              :                         // then check base class recursively
     336       847020 :                         if (cl.base_class != null) {
     337       406880 :                                 return symbol_lookup_inherited (cl.base_class, name);
     338              :                         }
     339      2199756 :                 } else if (sym is Struct) {
     340        65371 :                         unowned Struct st = (Struct) sym;
     341        65371 :                         if (st.base_type != null) {
     342           31 :                                 result = symbol_lookup_inherited (st.base_type.type_symbol, name);
     343           31 :                                 if (result != null) {
     344      4451587 :                                         return result;
     345              :                                 }
     346              :                         }
     347      2134385 :                 } else if (sym is Interface) {
     348       151382 :                         unowned Interface iface = (Interface) sym;
     349              :                         // first check interface prerequisites recursively
     350       473588 :                         foreach (DataType prerequisite in iface.get_prerequisites ()) {
     351       161103 :                                 if (prerequisite.type_symbol is Interface) {
     352         9751 :                                         result = symbol_lookup_inherited (prerequisite.type_symbol, name);
     353         9751 :                                         if (result != null) {
     354            0 :                                                 return result;
     355              :                                         }
     356              :                                 }
     357              :                         }
     358              :                         // then check class prerequisite recursively
     359       473320 :                         foreach (DataType prerequisite in iface.get_prerequisites ()) {
     360       161103 :                                 if (prerequisite.type_symbol is Class) {
     361       150857 :                                         result = symbol_lookup_inherited (prerequisite.type_symbol, name);
     362       150857 :                                         if (result != null) {
     363          134 :                                                 return result;
     364              :                                         }
     365              :                                 }
     366              :                         }
     367              :                 }
     368              : 
     369      2639731 :                 return null;
     370              :         }
     371              : 
     372       194142 :         public static DataType get_data_type_for_symbol (Symbol sym) {
     373              :                 DataType type;
     374              : 
     375       194142 :                 List<TypeParameter> type_parameters = null;
     376       194142 :                 if (sym is ObjectTypeSymbol) {
     377       177787 :                         unowned Class cl = sym as Class;
     378       177787 :                         if (cl != null && cl.is_error_base) {
     379          102 :                                 type = new ErrorType (null, null);
     380              :                         } else {
     381       177685 :                                 type = new ObjectType ((ObjectTypeSymbol) sym);
     382      5759356 :                                 type_parameters = ((ObjectTypeSymbol) sym).get_type_parameters ();
     383              :                         }
     384        16355 :                 } else if (sym is Struct) {
     385        16308 :                         unowned Struct st = (Struct) sym;
     386        16308 :                         if (st.is_boolean_type ()) {
     387            7 :                                 type = new BooleanType (st);
     388        16301 :                         } else if (st.is_integer_type ()) {
     389         1557 :                                 type = new IntegerType (st);
     390        14744 :                         } else if (st.is_floating_type ()) {
     391         1419 :                                 type = new FloatingType (st);
     392              :                         } else {
     393        13325 :                                 type = new StructValueType (st);
     394              :                         }
     395        16308 :                         type_parameters = st.get_type_parameters ();
     396           47 :                 } else if (sym is Enum) {
     397           47 :                         type = new EnumValueType ((Enum) sym);
     398            0 :                 } else if (sym is ErrorDomain) {
     399            0 :                         type = new ErrorType ((ErrorDomain) sym, null);
     400            0 :                 } else if (sym is ErrorCode) {
     401            0 :                         type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym);
     402              :                 } else {
     403            0 :                         Report.error (null, "internal error: `%s' is not a supported type", sym.get_full_name ());
     404            0 :                         return new InvalidType ();
     405              :                 }
     406              : 
     407       194142 :                 if (type_parameters != null) {
     408       345773 :                         foreach (var type_param in type_parameters) {
     409        75890 :                                 var type_arg = new GenericType (type_param);
     410        75890 :                                 type_arg.value_owned = true;
     411        75890 :                                 type.add_type_argument (type_arg);
     412              :                         }
     413              :                 }
     414              : 
     415       193993 :                 return type;
     416              :         }
     417              : 
     418            1 :         public static unowned Symbol? get_symbol_for_data_type (DataType type) {
     419            1 :                 unowned Symbol? sym = null;
     420              : 
     421            1 :                 if (type is ObjectType) {
     422            1 :                         sym = ((ObjectType) type).type_symbol;
     423            0 :                 } else if (type is ClassType) {
     424            0 :                         sym = ((ClassType) type).class_symbol;
     425            0 :                 } else if (type is InterfaceType) {
     426            0 :                         sym = ((InterfaceType) type).interface_symbol;
     427            0 :                 } else if (type is MethodType) {
     428            0 :                         sym = ((MethodType) type).method_symbol;
     429            0 :                 } else if (type is SignalType) {
     430            0 :                         sym = ((SignalType) type).signal_symbol;
     431            0 :                 } else if (type is DelegateType) {
     432            0 :                         sym = ((DelegateType) type).delegate_symbol;
     433            0 :                 } else if (type is ValueType) {
     434            0 :                         sym = ((ValueType) type).type_symbol;
     435              :                 }
     436              : 
     437              :                 return sym;
     438              :         }
     439              : 
     440       207664 :         public bool is_gobject_property (Property prop) {
     441       207664 :                 unowned ObjectTypeSymbol? type_sym = prop.parent_symbol as ObjectTypeSymbol;
     442       207638 :                 if (type_sym == null || !type_sym.is_subtype_of (object_type)) {
     443          732 :                         return false;
     444              :                 }
     445              : 
     446       206932 :                 if (prop.binding != MemberBinding.INSTANCE) {
     447          813 :                         return false;
     448              :                 }
     449              : 
     450       206932 :                 if (prop.access == SymbolAccessibility.PRIVATE) {
     451          813 :                         return false;
     452              :                 }
     453              : 
     454       206916 :                 if (!is_gobject_property_type (prop.property_type)) {
     455           74 :                         if (prop.property_type is ArrayType && (!prop.get_attribute_bool ("CCode", "array_length", true)
     456           12 :                             && prop.get_attribute_bool ("CCode", "array_null_terminated", false))) {
     457              :                                 // null-terminated arrays without length are allowed
     458           50 :                         } else if (prop.property_type is DelegateType && !prop.get_attribute_bool ("CCode", "delegate_target", true)) {
     459              :                                 // delegates omitting their target are allowed
     460              :                         } else {
     461           38 :                                 return false;
     462              :                         }
     463              :                 }
     464              : 
     465       206878 :                 if (type_sym is Class && prop.base_interface_property != null &&
     466          153 :                     !is_gobject_property (prop.base_interface_property)) {
     467          813 :                         return false;
     468              :                 }
     469              : 
     470       206872 :                 if (type_sym is Interface && !prop.is_abstract && !prop.external && !prop.external_package) {
     471              :                         // GObject does not support non-abstract interface properties,
     472              :                         // however we assume external properties always are GObject properties
     473          813 :                         return false;
     474              :                 }
     475              : 
     476       206863 :                 if (type_sym is Interface && type_sym.has_attribute ("DBus")) {
     477              :                         // GObject properties not currently supported in D-Bus interfaces
     478          813 :                         return false;
     479              :                 }
     480              : 
     481       207664 :                 return true;
     482              :         }
     483              : 
     484       206926 :         public bool is_gobject_property_type (DataType property_type) {
     485       206926 :                 unowned Struct? st = property_type.type_symbol as Struct;
     486        42282 :                 if (st != null) {
     487        42282 :                         if (!st.is_simple_type () && st.get_attribute_bool ("CCode", "has_type_id", true)) {
     488              :                                 // Allow GType-based struct types
     489        42150 :                         } else if (property_type.nullable) {
     490           61 :                                 return false;
     491        42143 :                         } else if (!st.get_attribute_bool ("CCode", "has_type_id", true)) {
     492           61 :                                 return false;
     493              :                         }
     494              :                 }
     495              : 
     496       206891 :                 if (property_type is EnumValueType) {
     497        35366 :                         return !property_type.nullable;
     498              :                 }
     499              : 
     500       171525 :                 if (property_type is ArrayType && ((ArrayType) property_type).element_type.type_symbol != string_type.type_symbol) {
     501           61 :                         return false;
     502              :                 }
     503              : 
     504       171512 :                 unowned DelegateType? d = property_type as DelegateType;
     505         2809 :                 if (d != null && d.delegate_symbol.has_target) {
     506           61 :                         return false;
     507              :                 }
     508              : 
     509       206926 :                 return true;
     510              :         }
     511              : 
     512       208296 :         public bool check_arguments (Expression expr, DataType mtype, List<Parameter> params, List<Expression> args) {
     513       208296 :                 bool error = false;
     514              : 
     515       208296 :                 Expression prev_arg = null;
     516       208296 :                 Iterator<Expression> arg_it = args.iterator ();
     517              : 
     518       208296 :                 bool diag = (mtype is MethodType && ((MethodType) mtype).method_symbol.has_attribute ("Diagnostics"));
     519              : 
     520       208296 :                 bool ellipsis = false;
     521       208296 :                 int i = 0;
     522       814604 :                 foreach (Parameter param in params) {
     523       322546 :                         if (param.ellipsis) {
     524        19370 :                                 ellipsis = true;
     525        19370 :                                 break;
     526              :                         }
     527              : 
     528       303176 :                         if (param.params_array) {
     529          154 :                                 while (arg_it.next ()) {
     530           66 :                                         var arg = arg_it.get ();
     531           66 :                                         if (!check_argument (arg, i, param.direction)) {
     532            0 :                                                 expr.error = true;
     533            0 :                                                 error = true;
     534              :                                         }
     535              : 
     536           66 :                                         i++;
     537              :                                 }
     538              : 
     539           22 :                                 break;
     540              :                         }
     541              : 
     542       592357 :                         if (arg_it == null || !arg_it.next ()) {
     543        13951 :                                 if (param.initializer == null) {
     544            2 :                                         expr.error = true;
     545            2 :                                         unowned MethodType? m = mtype as MethodType;
     546            2 :                                         if (m != null) {
     547            2 :                                                 Report.error (expr.source_reference, "%d missing arguments for `%s'", m.get_parameters ().size - args.size, m.to_prototype_string ());
     548              :                                         } else {
     549            0 :                                                 Report.error (expr.source_reference, "Too few arguments, method `%s' does not take %d arguments", mtype.to_string (), args.size);
     550              :                                         }
     551              :                                         error = true;
     552              :                                 } else {
     553        13949 :                                         unowned MethodCall? invocation_expr = expr as MethodCall;
     554        13949 :                                         unowned ObjectCreationExpression? object_creation_expr = expr as ObjectCreationExpression;
     555        13949 :                                         if (invocation_expr != null) {
     556        11078 :                                                 invocation_expr.add_argument (param.initializer);
     557         2871 :                                         } else if (object_creation_expr != null) {
     558         2871 :                                                 object_creation_expr.add_argument (param.initializer);
     559              :                                         } else {
     560            0 :                                                 assert_not_reached ();
     561              :                                         }
     562        13949 :                                         arg_it = null;
     563              :                                 }
     564              :                         } else {
     565       289203 :                                 var arg = arg_it.get ();
     566       289203 :                                 if (!check_argument (arg, i, param.direction)) {
     567           25 :                                         expr.error = true;
     568           25 :                                         error = true;
     569              :                                 }
     570              : 
     571       578406 :                                 prev_arg = arg;
     572              : 
     573       289203 :                                 i++;
     574              :                         }
     575              :                 }
     576              : 
     577       208296 :                 if (ellipsis && !check_variadic_arguments (arg_it, i, expr.source_reference)) {
     578            4 :                         expr.error = true;
     579            4 :                         error = true;
     580       208292 :                 } else if (!ellipsis && arg_it != null && arg_it.next ()) {
     581            1 :                         expr.error = true;
     582            1 :                         unowned MethodType? m = mtype as MethodType;
     583            1 :                         if (m != null) {
     584            1 :                                 Report.error (expr.source_reference, "%d extra arguments for `%s'", args.size - m.get_parameters ().size, m.to_prototype_string ());
     585              :                         } else {
     586            0 :                                 Report.error (expr.source_reference, "Too many arguments, method `%s' does not take %d arguments", mtype.to_string (), args.size);
     587              :                         }
     588              :                         error = true;
     589              :                 }
     590              : 
     591       208296 :                 if (diag && prev_arg != null) {
     592           12 :                         unowned StringLiteral? format_arg = prev_arg as StringLiteral;
     593           12 :                         if (format_arg != null) {
     594           12 :                                 format_arg.value = "\"%s:%d: %s".printf (Path.get_basename (expr.source_reference.file.filename), expr.source_reference.begin.line, format_arg.value.substring (1));
     595              :                         }
     596              :                 }
     597              : 
     598       208296 :                 return !error;
     599              :         }
     600              : 
     601       289269 :         bool check_argument (Expression arg, int i, ParameterDirection direction) {
     602       289269 :                 if (arg.error) {
     603              :                         // ignore inner error
     604           25 :                         return false;
     605       289259 :                 } else if (arg is NamedArgument) {
     606            1 :                         Report.error (arg.source_reference, "Named arguments are not supported yet");
     607            1 :                         return false;
     608       289258 :                 } else if (arg.value_type == null) {
     609              :                         // disallow untyped arguments except for type inference of callbacks
     610            0 :                         if (!(arg.target_type is DelegateType) || !(arg.symbol_reference is Method)) {
     611            0 :                                 Report.error (arg.source_reference, "Invalid type for argument %d", i + 1);
     612            0 :                                 return false;
     613              :                         }
     614              :                 } else {
     615              :                         // 0 => null, 1 => in, 2 => ref, 3 => out
     616       289258 :                         int arg_type = 1;
     617       289258 :                         if (arg.value_type is NullType) {
     618              :                                 arg_type = 0;
     619       293352 :                         } else if (arg is UnaryExpression) {
     620        18795 :                                 var unary = (UnaryExpression) arg;
     621        18795 :                                 if (unary.operator == UnaryOperator.REF) {
     622              :                                         arg_type = 2;
     623        15867 :                                 } else if (unary.operator == UnaryOperator.OUT) {
     624        15767 :                                         arg_type = 3;
     625              :                                 }
     626              :                         }
     627              : 
     628        18795 :                         if (arg_type == 0) {
     629        14701 :                                 if (direction == ParameterDirection.REF) {
     630            1 :                                         Report.error (arg.source_reference, "Argument %d: Cannot pass null to reference parameter", i + 1);
     631            1 :                                         return false;
     632        14700 :                                 } else if (direction != ParameterDirection.OUT && !arg.target_type.nullable) {
     633            0 :                                         Report.warning (arg.source_reference, "Argument %d: Cannot pass null to non-null parameter type", i + 1);
     634              :                                 }
     635       274557 :                         } else if (arg_type == 1) {
     636       255862 :                                 if (direction != ParameterDirection.IN) {
     637            2 :                                         Report.error (arg.source_reference, "Argument %d: Cannot pass value to reference or output parameter", i + 1);
     638            2 :                                         return false;
     639              :                                 }
     640        18695 :                         } else if (arg_type == 2) {
     641         2928 :                                 if (direction != ParameterDirection.REF) {
     642            1 :                                         Report.error (arg.source_reference, "Argument %d: Cannot pass ref argument to non-reference parameter", i + 1);
     643            1 :                                         return false;
     644              :                                 }
     645              : 
     646              :                                 // weak variables can only be used with weak ref parameters
     647         2927 :                                 if (arg.target_type.is_disposable ()) {
     648           39 :                                         if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
     649              :                                                 /* variable doesn't own the value */
     650            1 :                                                 Report.error (arg.source_reference, "Argument %d: Cannot pass unowned ref argument to owned reference parameter", i + 1);
     651            1 :                                                 return false;
     652              :                                         }
     653              :                                 }
     654              : 
     655              :                                 // owned variables can only be used with owned ref parameters
     656         2926 :                                 if (arg.value_type.is_disposable ()) {
     657           39 :                                         if (!arg.target_type.value_owned) {
     658              :                                                 /* parameter doesn't own the value */
     659            0 :                                                 Report.error (arg.source_reference, "Argument %d: Cannot pass owned ref argument to unowned reference parameter", i + 1);
     660            0 :                                                 return false;
     661              :                                         }
     662              :                                 }
     663        15767 :                         } else if (arg_type == 3) {
     664        15767 :                                 if (direction != ParameterDirection.OUT) {
     665            1 :                                         Report.error (arg.source_reference, "Argument %d: Cannot pass out argument to non-output parameter", i + 1);
     666            1 :                                         return false;
     667              :                                 }
     668              : 
     669              :                                 // weak variables can only be used with weak out parameters
     670        15766 :                                 if (arg.target_type.is_disposable ()) {
     671           86 :                                         if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
     672              :                                                 /* variable doesn't own the value */
     673            1 :                                                 Report.error (arg.source_reference, "Invalid assignment from owned expression to unowned variable");
     674            1 :                                                 return false;
     675              :                                         }
     676              :                                 }
     677              :                         }
     678              :                 }
     679              : 
     680       289251 :                 if (arg.target_type != null) {
     681       289247 :                         if ((direction == ParameterDirection.IN || direction == ParameterDirection.REF)
     682       262123 :                             && !arg.value_type.compatible (arg.target_type)) {
     683            6 :                                 Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'", i + 1, arg.value_type.to_prototype_string (), arg.target_type.to_prototype_string ());
     684            6 :                                 return false;
     685       289241 :                         } else if ((direction == ParameterDirection.REF || direction == ParameterDirection.OUT)
     686        30049 :                                 && !arg.target_type.compatible (arg.value_type)
     687        11360 :                                 && !(arg is NullLiteral)) {
     688            1 :                                 Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'", i + 1, arg.target_type.to_prototype_string (), arg.value_type.to_prototype_string ());
     689            1 :                                 return false;
     690              :                         }
     691              :                 }
     692              : 
     693       289244 :                 unowned MemberAccess? ma = arg as MemberAccess;
     694       133204 :                 if (ma != null && ma.prototype_access) {
     695              :                         // allow prototype access if target type is delegate without target
     696            2 :                         unowned DelegateType? deleg_type = arg.target_type as DelegateType;
     697            2 :                         if (deleg_type == null || deleg_type.delegate_symbol.has_target) {
     698            0 :                                 Report.error (arg.source_reference, "Access to instance member `%s' denied", arg.symbol_reference.get_full_name ());
     699            0 :                                 return false;
     700              :                         }
     701              :                 }
     702       289269 :                 return true;
     703              :         }
     704              : 
     705        20862 :         public bool check_variadic_arguments (Iterator<Expression>? arg_it, int i, SourceReference? source_reference = null) {
     706        73266 :                 while (arg_it != null && arg_it.next ()) {
     707        26206 :                         var arg = arg_it.get ();
     708        26206 :                         if (arg.error) {
     709              :                                 // ignore inner error
     710            2 :                                 return false;
     711        26204 :                         } else if (arg.value_type is SignalType) {
     712            0 :                                 arg.error = true;
     713            0 :                                 Report.error (arg.source_reference, "Cannot pass signals as arguments");
     714            0 :                                 return false;
     715        26204 :                         } else if (arg.value_type == null) {
     716              :                                 // disallow untyped arguments except for type inference of callbacks
     717            0 :                                 if (!(arg.symbol_reference is Method)) {
     718            0 :                                         Report.error (source_reference, "Invalid type for argument %d", i + 1);
     719            0 :                                         return false;
     720              :                                 }
     721        26204 :                         } else if (arg.target_type != null && !arg.value_type.compatible (arg.target_type)) {
     722              :                                 // target_type known for printf arguments
     723            2 :                                 Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'", i + 1, arg.value_type.to_string (), arg.target_type.to_string ());
     724            2 :                                 return false;
     725              :                         }
     726              : 
     727        26202 :                         i++;
     728              :                 }
     729              : 
     730        20862 :                 return true;
     731              :         }
     732              : 
     733         7480 :         public bool check_print_format (string format, Iterator<Expression> arg_it, SourceReference? source_reference = null) {
     734         7480 :                 bool unsupported_format = false;
     735              : 
     736         7480 :                 weak string format_it = format;
     737         7480 :                 unichar c = format_it.get_char ();
     738       109218 :                 while (c != '\0') {
     739        88624 :                         if (c != '%') {
     740        75508 :                                 format_it = format_it.next_char ();
     741        75508 :                                 c = format_it.get_char ();
     742        75508 :                                 continue;
     743              :                         }
     744              : 
     745        13116 :                         format_it = format_it.next_char ();
     746        13116 :                         c = format_it.get_char ();
     747              :                         // flags
     748        21614 :                         while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
     749         8498 :                                 format_it = format_it.next_char ();
     750         8498 :                                 c = format_it.get_char ();
     751              :                         }
     752              :                         // field width
     753        21622 :                         while (c >= '0' && c <= '9') {
     754         8506 :                                 format_it = format_it.next_char ();
     755         8506 :                                 c = format_it.get_char ();
     756              :                         }
     757              :                         // precision
     758        13116 :                         if (c == '.') {
     759           19 :                                 format_it = format_it.next_char ();
     760           19 :                                 c = format_it.get_char ();
     761           46 :                                 while (c >= '0' && c <= '9') {
     762           27 :                                         format_it = format_it.next_char ();
     763           27 :                                         c = format_it.get_char ();
     764              :                                 }
     765              :                         }
     766              :                         // length modifier
     767        13116 :                         int length = 0;
     768        13116 :                         if (c == 'h') {
     769           24 :                                 length = -1;
     770           24 :                                 format_it = format_it.next_char ();
     771           24 :                                 c = format_it.get_char ();
     772           24 :                                 if (c == 'h') {
     773            8 :                                         length = -2;
     774            8 :                                         format_it = format_it.next_char ();
     775            8 :                                         c = format_it.get_char ();
     776              :                                 }
     777        13092 :                         } else if (c == 'l') {
     778           24 :                                 length = 1;
     779           24 :                                 format_it = format_it.next_char ();
     780           24 :                                 c = format_it.get_char ();
     781        13068 :                         } else if (c == 'z') {
     782           16 :                                 length = 2;
     783           16 :                                 format_it = format_it.next_char ();
     784           16 :                                 c = format_it.get_char ();
     785              :                         }
     786              :                         // conversion specifier
     787        13116 :                         DataType param_type = null;
     788        13116 :                         if (c == 'd' || c == 'i' || c == 'c') {
     789              :                                 // integer
     790         8821 :                                 if (length == -2) {
     791            0 :                                         param_type = int8_type;
     792         8821 :                                 } else if (length == -1) {
     793            8 :                                         param_type = short_type;
     794         8813 :                                 } else if (length == 0) {
     795         8795 :                                         param_type = int_type;
     796           18 :                                 } else if (length == 1) {
     797           10 :                                         param_type = long_type;
     798            8 :                                 } else if (length == 2) {
     799            8 :                                         param_type = ssize_t_type;
     800              :                                 }
     801              :                         } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
     802              :                                 // unsigned integer
     803           53 :                                 if (length == -2) {
     804            8 :                                         param_type = uchar_type;
     805           45 :                                 } else if (length == -1) {
     806            8 :                                         param_type = ushort_type;
     807           37 :                                 } else if (length == 0) {
     808           15 :                                         param_type = uint_type;
     809           22 :                                 } else if (length == 1) {
     810           14 :                                         param_type = ulong_type;
     811            8 :                                 } else if (length == 2) {
     812            8 :                                         param_type = size_t_type;
     813              :                                 }
     814              :                         } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
     815              :                                            || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
     816              :                                 // double
     817           19 :                                 param_type = double_type;
     818              :                         } else if (c == 's') {
     819              :                                 // string
     820         4217 :                                 param_type = string_type;
     821              :                         } else if (c == 'p') {
     822              :                                 // pointer
     823            0 :                                 param_type = new PointerType (new VoidType ());
     824              :                         } else if (c == '%') {
     825              :                                 // literal %
     826              :                         } else {
     827              :                                 unsupported_format = true;
     828              :                                 break;
     829              :                         }
     830        13110 :                         if (c != '\0') {
     831        13116 :                                 format_it = format_it.next_char ();
     832        13116 :                                 c = format_it.get_char ();
     833              :                         }
     834        13116 :                         if (param_type != null) {
     835        26219 :                                 if (arg_it.next ()) {
     836        13109 :                                         Expression arg = arg_it.get ();
     837              : 
     838        13109 :                                         arg.target_type = param_type;
     839              :                                 } else {
     840            1 :                                         Report.error (source_reference, "Too few arguments for specified format");
     841            1 :                                         return false;
     842              :                                 }
     843              :                         }
     844              :                 }
     845         7479 :                 if (!unsupported_format && arg_it.next ()) {
     846            1 :                         Report.error (source_reference, "Too many arguments for specified format");
     847            1 :                         return false;
     848              :                 }
     849              : 
     850         7480 :                 return true;
     851              :         }
     852              : 
     853        16365 :         private static DataType get_instance_base_type (DataType instance_type, DataType base_type, CodeNode? node_reference) {
     854              :                 // construct a new type reference for the base type with correctly linked type arguments
     855              :                 DataType instance_base_type;
     856        16365 :                 if (base_type.type_symbol is ObjectTypeSymbol) {
     857        16359 :                         instance_base_type = new ObjectType ((ObjectTypeSymbol) base_type.type_symbol);
     858            6 :                 } else if (base_type.type_symbol is Struct) {
     859            6 :                         instance_base_type = new StructValueType ((Struct) base_type.type_symbol);
     860              :                 } else {
     861        16365 :                         assert_not_reached ();
     862              :                 }
     863        22287 :                 foreach (DataType type_arg in base_type.get_type_arguments ()) {
     864              :                         // resolve type argument specified in base type (possibly recursively for nested generic types)
     865         2961 :                         type_arg = type_arg.get_actual_type (instance_type, null, node_reference);
     866         2961 :                         instance_base_type.add_type_argument (type_arg);
     867              :                 }
     868              :                 return instance_base_type;
     869              :         }
     870              : 
     871      1182007 :         internal static DataType? get_instance_base_type_for_member (DataType derived_instance_type, TypeSymbol type_symbol, CodeNode? node_reference) {
     872      1182007 :                 DataType instance_type = derived_instance_type;
     873              : 
     874      1182007 :                 while (instance_type is PointerType) {
     875            0 :                         unowned PointerType instance_pointer_type = (PointerType) instance_type;
     876            0 :                         instance_type = instance_pointer_type.base_type;
     877              :                 }
     878              : 
     879      1182007 :                 if (instance_type is DelegateType && ((DelegateType) instance_type).delegate_symbol == type_symbol) {
     880      1165641 :                         return instance_type;
     881      1149414 :                 } else if (instance_type.type_symbol == type_symbol) {
     882      1165641 :                         return instance_type;
     883              :                 }
     884              : 
     885        16366 :                 DataType? instance_base_type = null;
     886              : 
     887              :                 // use same algorithm as symbol_lookup_inherited
     888        16366 :                 if (instance_type.type_symbol is Class) {
     889        14747 :                         unowned Class cl = (Class) instance_type.type_symbol;
     890              :                         // first check interfaces without prerequisites
     891              :                         // (prerequisites can be assumed to be met already)
     892        44643 :                         foreach (DataType base_type in cl.get_base_types ()) {
     893        16382 :                                 if (base_type.type_symbol is Interface) {
     894         1933 :                                         instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, base_type, node_reference), type_symbol, node_reference);
     895         1933 :                                         if (instance_base_type != null) {
     896         1434 :                                                 return instance_base_type;
     897              :                                         }
     898              :                                 }
     899              :                         }
     900              :                         // then check base class recursively
     901        13313 :                         if (instance_base_type == null) {
     902        13711 :                                 foreach (DataType base_type in cl.get_base_types ()) {
     903        13018 :                                         if (base_type.type_symbol is Class) {
     904        13018 :                                                 instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, base_type, node_reference), type_symbol, node_reference);
     905        13018 :                                                 if (instance_base_type != null) {
     906        12819 :                                                         return instance_base_type;
     907              :                                                 }
     908              :                                         }
     909              :                                 }
     910              :                         }
     911         1619 :                 } else if (instance_type.type_symbol is Struct) {
     912            6 :                         unowned Struct st = (Struct) instance_type.type_symbol;
     913            6 :                         if (st.base_type != null) {
     914            6 :                                 instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, st.base_type, node_reference), type_symbol, node_reference);
     915            6 :                                 if (instance_base_type != null) {
     916            6 :                                         return instance_base_type;
     917              :                                 }
     918              :                         }
     919         1613 :                 } else if (instance_type.type_symbol is Interface) {
     920         1613 :                         unowned Interface iface = (Interface) instance_type.type_symbol;
     921              :                         // first check interface prerequisites recursively
     922         4429 :                         foreach (DataType prerequisite in iface.get_prerequisites ()) {
     923         1411 :                                 if (prerequisite.type_symbol is Interface) {
     924            3 :                                         instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, prerequisite, node_reference), type_symbol, node_reference);
     925            3 :                                         if (instance_base_type != null) {
     926            3 :                                                 return instance_base_type;
     927              :                                         }
     928              :                                 }
     929              :                         }
     930         1610 :                         if (instance_base_type == null) {
     931              :                                 // then check class prerequisite recursively
     932         2198 :                                 foreach (DataType prerequisite in iface.get_prerequisites ()) {
     933         1405 :                                         if (prerequisite.type_symbol is Class) {
     934         1405 :                                                 instance_base_type = get_instance_base_type_for_member (get_instance_base_type (instance_type, prerequisite, node_reference), type_symbol, node_reference);
     935         1405 :                                                 if (instance_base_type != null) {
     936         1111 :                                                         return instance_base_type;
     937              :                                                 }
     938              :                                         }
     939              :                                 }
     940              :                         }
     941              :                 }
     942              : 
     943          993 :                 return null;
     944              :         }
     945              : 
     946       132514 :         public static DataType get_actual_type (DataType? derived_instance_type, List<DataType>? method_type_arguments, GenericType generic_type, CodeNode? node_reference) {
     947       132514 :                 DataType actual_type = null;
     948       132514 :                 if (generic_type.type_parameter.parent_symbol is TypeSymbol) {
     949       258771 :                         if (derived_instance_type != null) {
     950              :                                 // trace type arguments back to the datatype where the method has been declared
     951       129386 :                                 var instance_type = get_instance_base_type_for_member (derived_instance_type, (TypeSymbol) generic_type.type_parameter.parent_symbol, node_reference);
     952              : 
     953       129386 :                                 if (instance_type == null) {
     954            2 :                                         if (node_reference != null) {
     955            1 :                                                 CodeNode? reference = get_symbol_for_data_type (derived_instance_type);
     956            1 :                                                 Report.error ((reference ?? node_reference).source_reference, "The type-parameter `%s' is missing", generic_type.to_string ());
     957            1 :                                                 node_reference.error = true;
     958              :                                         }
     959            1 :                                         return new InvalidType ();
     960              :                                 }
     961              : 
     962              :                                 int param_index;
     963       129385 :                                 if (instance_type is DelegateType) {
     964        32593 :                                         param_index = ((DelegateType) instance_type).delegate_symbol.get_type_parameter_index (generic_type.type_parameter.name);
     965              :                                 } else {
     966        96792 :                                         param_index = instance_type.type_symbol.get_type_parameter_index (generic_type.type_parameter.name);
     967              :                                 }
     968       129385 :                                 if (param_index == -1) {
     969            0 :                                         if (node_reference != null) {
     970            0 :                                                 Report.error (node_reference.source_reference, "internal error: unknown type parameter %s", generic_type.type_parameter.name);
     971            0 :                                                 node_reference.error = true;
     972              :                                         }
     973            0 :                                         return new InvalidType ();
     974              :                                 }
     975              : 
     976       129385 :                                 if (param_index < instance_type.get_type_arguments ().size) {
     977       129382 :                                         actual_type = (DataType) instance_type.get_type_arguments ().get (param_index);
     978              :                                 }
     979              :                         }
     980              :                 } else {
     981              :                         // generic method
     982         3128 :                         unowned Method m = (Method) generic_type.type_parameter.parent_symbol;
     983              : 
     984         3128 :                         int param_index = m.get_type_parameter_index (generic_type.type_parameter.name);
     985         3128 :                         if (param_index == -1) {
     986            0 :                                 if (node_reference != null) {
     987            0 :                                         Report.error (node_reference.source_reference, "internal error: unknown type parameter %s", generic_type.type_parameter.name);
     988            0 :                                         node_reference.error = true;
     989              :                                 }
     990            0 :                                 return new InvalidType ();
     991              :                         }
     992              : 
     993         3128 :                         if (method_type_arguments != null) {
     994         3128 :                                 if (param_index < method_type_arguments.size) {
     995         3027 :                                         actual_type = (DataType) method_type_arguments.get (param_index);
     996              :                                 }
     997              :                         }
     998              :                 }
     999              : 
    1000       132513 :                 if (actual_type == null) {
    1001              :                         // no actual type available
    1002          104 :                         return generic_type;
    1003              :                 }
    1004       132409 :                 actual_type = actual_type.copy ();
    1005       132409 :                 actual_type.source_reference = generic_type.source_reference;
    1006       132409 :                 actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
    1007       132409 :                 return actual_type;
    1008              :         }
    1009              : 
    1010       122941 :         public bool is_in_instance_method () {
    1011       122941 :                 unowned Symbol? sym = current_symbol;
    1012       282587 :                 while (sym != null) {
    1013       282587 :                         if (sym is CreationMethod) {
    1014       122941 :                                 return true;
    1015       278832 :                         } else if (sym is Method) {
    1016       110673 :                                 unowned Method m = (Method) sym;
    1017       110673 :                                 return m.binding == MemberBinding.INSTANCE;
    1018       168159 :                         } else if (sym is Constructor) {
    1019            1 :                                 unowned Constructor c = (Constructor) sym;
    1020            1 :                                 return c.binding == MemberBinding.INSTANCE;
    1021       168158 :                         } else if (sym is Destructor) {
    1022            1 :                                 unowned Destructor d = (Destructor) sym;
    1023            1 :                                 return d.binding == MemberBinding.INSTANCE;
    1024       168157 :                         } else if (sym is Property) {
    1025         8511 :                                 unowned Property p = (Property) sym;
    1026         8511 :                                 return p.binding == MemberBinding.INSTANCE;
    1027              :                         }
    1028       159646 :                         sym = sym.parent_symbol;
    1029              :                 }
    1030              : 
    1031       122941 :                 return false;
    1032              :         }
    1033              : 
    1034              :         // Create an access to a temporary variable, with proper reference transfer if needed
    1035         3013 :         public static Expression create_temp_access (LocalVariable local, DataType? target_type) {
    1036         3013 :                 Expression temp_access = new MemberAccess.simple (local.name, local.source_reference);
    1037              : 
    1038         3090 :                 var target_owned = target_type != null && target_type.value_owned;
    1039         5995 :                 if (target_owned && local.variable_type.is_disposable ()) {
    1040         2905 :                         temp_access = new ReferenceTransferExpression (temp_access, local.source_reference);
    1041         2905 :                         temp_access.target_type = target_type != null ? target_type.copy () : local.variable_type.copy ();
    1042         2905 :                         temp_access.target_type.value_owned = true;
    1043              :                 } else {
    1044          108 :                         temp_access.target_type = target_type != null ? target_type.copy () : null;
    1045              :                 }
    1046              : 
    1047              :                 return temp_access;
    1048              :         }
    1049              : 
    1050       399690 :         unowned Struct? get_arithmetic_struct (DataType type) {
    1051       399690 :                 unowned Struct? result = type.type_symbol as Struct;
    1052       144308 :                 if (result == null && type is EnumValueType) {
    1053         1365 :                         return (Struct) int_type.type_symbol;
    1054              :                 }
    1055       399690 :                 return result;
    1056              :         }
    1057              : 
    1058       199845 :         public unowned DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
    1059       199845 :                 unowned Struct? left = get_arithmetic_struct (left_type);
    1060       199845 :                 unowned Struct? right = get_arithmetic_struct (right_type);
    1061              : 
    1062       199845 :                 if (left == null || right == null) {
    1063              :                         // at least one operand not struct
    1064        72174 :                         return null;
    1065              :                 }
    1066              : 
    1067       128354 :                 if ((!left.is_floating_type () && !left.is_integer_type ()) ||
    1068       127671 :                     (!right.is_floating_type () && !right.is_integer_type ())) {
    1069              :                         // at least one operand not numeric
    1070          683 :                         return null;
    1071              :                 }
    1072              : 
    1073       127671 :                 if (left.is_floating_type () == right.is_floating_type ()) {
    1074              :                         // both operands integer or floating type
    1075       127610 :                         if (left.rank >= right.rank) {
    1076       117711 :                                 return left_type;
    1077              :                         } else {
    1078         9960 :                                 return right_type;
    1079              :                         }
    1080              :                 } else {
    1081              :                         // one integer and one floating type operand
    1082           61 :                         if (left.is_floating_type ()) {
    1083       117711 :                                 return left_type;
    1084              :                         } else {
    1085         9960 :                                 return right_type;
    1086              :                         }
    1087              :                 }
    1088              :         }
    1089              : 
    1090         2095 :         public unowned Method? find_current_method () {
    1091         2095 :                 unowned Symbol? sym = current_symbol;
    1092         4200 :                 while (sym != null) {
    1093         4197 :                         if (sym is Method) {
    1094         2092 :                                 return (Method) sym;
    1095              :                         }
    1096         2105 :                         sym = sym.parent_symbol;
    1097              :                 }
    1098         2095 :                 return null;
    1099              :         }
    1100              : 
    1101         6020 :         public static unowned Method? find_parent_method (Symbol sym) {
    1102        12074 :                 while (sym is Block) {
    1103         6054 :                         sym = sym.parent_symbol;
    1104              :                 }
    1105         6020 :                 return sym as Method;
    1106              :         }
    1107              : 
    1108       441856 :         public static unowned Symbol? find_parent_method_or_property_accessor (Symbol sym) {
    1109      1120777 :                 while (sym is Block) {
    1110       678921 :                         sym = sym.parent_symbol;
    1111              :                 }
    1112       441856 :                 if (sym is Method) {
    1113              :                         return sym;
    1114         5855 :                 } else if (sym is PropertyAccessor) {
    1115              :                         return sym;
    1116              :                 } else {
    1117              :                         return null;
    1118              :                 }
    1119              :         }
    1120              : 
    1121         8936 :         public static unowned TypeSymbol? find_parent_type_symbol (Symbol sym) {
    1122        18606 :                 while (sym != null) {
    1123        18606 :                         if (sym is TypeSymbol) {
    1124         8936 :                                 return (TypeSymbol) sym;
    1125              :                         }
    1126         9670 :                         sym = sym.parent_symbol;
    1127              :                 }
    1128         8936 :                 return null;
    1129              :         }
    1130              : 
    1131      5565861 :         public static DataType? get_this_type (Symbol s, TypeSymbol? parent = null) {
    1132      5565861 :                 unowned TypeSymbol? parent_type = parent ?? find_parent_type_symbol (s);
    1133         8936 :                 if (parent_type == null) {
    1134            0 :                         Report.error (parent_type.source_reference, "internal: Unsupported symbol type");
    1135            0 :                         return new InvalidType ();
    1136              :                 }
    1137              : 
    1138              :                 MemberBinding binding;
    1139      5565861 :                 if (s is Method) {
    1140      5116446 :                         binding = ((Method) s).binding;
    1141       449415 :                 } else if (s is Constructor) {
    1142           38 :                         binding = ((Constructor) s).binding;
    1143       449377 :                 } else if (s is Destructor) {
    1144           23 :                         binding = ((Destructor) s).binding;
    1145       449354 :                 } else if (s is Property) {
    1146       449354 :                         binding = ((Property) s).binding;
    1147              :                 } else {
    1148            0 :                         Report.error (s.source_reference, "internal: Unsupported symbol type");
    1149            0 :                         return new InvalidType ();
    1150              :                 }
    1151              : 
    1152      5565861 :                 DataType? this_type = null;
    1153      5565861 :                 List<TypeParameter>? type_parameters = null;
    1154      5565861 :                 switch (binding) {
    1155              :                 case MemberBinding.INSTANCE:
    1156      5565395 :                         if (parent_type is Class) {
    1157      4381132 :                                 this_type = new ObjectType ((Class) parent_type);
    1158      4381132 :                                 type_parameters = ((Class) parent_type).get_type_parameters ();
    1159      1184263 :                         } else if (parent_type is Interface) {
    1160       596175 :                                 this_type = new ObjectType ((Interface) parent_type);
    1161       596175 :                                 type_parameters = ((Interface) parent_type).get_type_parameters ();
    1162       588088 :                         } else if (parent_type is Struct) {
    1163       588056 :                                 this_type = new StructValueType ((Struct) parent_type);
    1164       588056 :                                 type_parameters = ((Struct) parent_type).get_type_parameters ();
    1165           32 :                         } else if (parent_type is Enum) {
    1166           32 :                                 this_type = new EnumValueType ((Enum) parent_type);
    1167              :                         } else {
    1168            0 :                                 Report.error (parent_type.source_reference, "internal: Unsupported symbol type");
    1169            0 :                                 this_type = new InvalidType ();
    1170              :                         }
    1171              :                         break;
    1172              :                 case MemberBinding.CLASS:
    1173          466 :                         if (parent_type is Class) {
    1174          464 :                                 this_type = new ClassType ((Class) parent_type);
    1175            2 :                         } else if (parent_type is Interface) {
    1176            2 :                                 this_type = new InterfaceType ((Interface) parent_type);
    1177              :                         } else {
    1178            0 :                                 Report.error (parent_type.source_reference, "internal: Unsupported symbol type");
    1179            0 :                                 this_type = new InvalidType ();
    1180              :                         }
    1181              :                         break;
    1182              :                 case MemberBinding.STATIC:
    1183              :                 default:
    1184            0 :                         Report.error (s.source_reference, "internal: Does not support a parent instance");
    1185            0 :                         this_type = new InvalidType ();
    1186            0 :                         break;
    1187              :                 }
    1188              : 
    1189      5565861 :                 if (type_parameters != null) {
    1190      6843873 :                         foreach (var type_param in type_parameters) {
    1191       639255 :                                 var type_arg = new GenericType (type_param);
    1192       639255 :                                 type_arg.value_owned = true;
    1193       639255 :                                 this_type.add_type_argument (type_arg);
    1194              :                         }
    1195              :                 }
    1196              : 
    1197      5565363 :                 return this_type;
    1198              :         }
    1199              : 
    1200           10 :         public bool is_in_constructor () {
    1201           10 :                 unowned Symbol? sym = current_symbol;
    1202           40 :                 while (sym != null) {
    1203           35 :                         if (sym is Constructor) {
    1204              :                                 return true;
    1205              :                         }
    1206           30 :                         sym = sym.parent_symbol;
    1207              :                 }
    1208              :                 return false;
    1209              :         }
    1210              : 
    1211            4 :         public bool is_in_destructor () {
    1212            4 :                 unowned Symbol? sym = current_symbol;
    1213           12 :                 while (sym != null) {
    1214           12 :                         if (sym is Destructor) {
    1215              :                                 return true;
    1216              :                         }
    1217            8 :                         sym = sym.parent_symbol;
    1218              :                 }
    1219              :                 return false;
    1220              :         }
    1221              : 
    1222         2743 :         public bool is_reference_type_argument (DataType type_arg) {
    1223         2743 :                 if (type_arg is ErrorType || (type_arg.type_symbol != null && type_arg.type_symbol.is_reference_type ())) {
    1224         2440 :                         return true;
    1225              :                 } else {
    1226          303 :                         return false;
    1227              :                 }
    1228              :         }
    1229              : 
    1230          303 :         public bool is_nullable_value_type_argument (DataType type_arg) {
    1231          303 :                 if (type_arg is ValueType && type_arg.nullable) {
    1232          303 :                         return true;
    1233              :                 } else {
    1234          229 :                         return false;
    1235              :                 }
    1236              :         }
    1237              : 
    1238         2008 :         public bool is_signed_integer_type_argument (DataType type_arg) {
    1239         2008 :                 unowned Struct? st = type_arg.type_symbol as Struct;
    1240         2008 :                 if (type_arg is EnumValueType) {
    1241              :                         return true;
    1242         1822 :                 } else if (type_arg.nullable) {
    1243              :                         return false;
    1244         1762 :                 } else if (st == null) {
    1245              :                         return false;
    1246          402 :                 } else if (st.is_subtype_of (bool_type.type_symbol)) {
    1247              :                         return true;
    1248          390 :                 } else if (st.is_subtype_of (char_type.type_symbol)) {
    1249              :                         return true;
    1250          388 :                 } else if (unichar_type != null && st.is_subtype_of (unichar_type.type_symbol)) {
    1251              :                         return true;
    1252          388 :                 } else if (st.is_subtype_of (short_type.type_symbol)) {
    1253              :                         return true;
    1254          388 :                 } else if (st.is_subtype_of (int_type.type_symbol)) {
    1255              :                         return true;
    1256           33 :                 } else if (st.is_subtype_of (long_type.type_symbol)) {
    1257              :                         return true;
    1258           33 :                 } else if (st.is_subtype_of (int8_type.type_symbol)) {
    1259              :                         return true;
    1260           33 :                 } else if (st.is_subtype_of (int16_type.type_symbol)) {
    1261              :                         return true;
    1262           32 :                 } else if (st.is_subtype_of (int32_type.type_symbol)) {
    1263              :                         return true;
    1264           32 :                 } else if (st.is_subtype_of (type_type.type_symbol)) {
    1265              :                         return true;
    1266              :                 } else {
    1267              :                         return false;
    1268              :                 }
    1269              :         }
    1270              : 
    1271         1446 :         public bool is_unsigned_integer_type_argument (DataType type_arg) {
    1272         1446 :                 unowned Struct? st = type_arg.type_symbol as Struct;
    1273         1475 :                 if (st == null) {
    1274              :                         return false;
    1275           53 :                 } else if (type_arg.nullable) {
    1276              :                         return false;
    1277           26 :                 } else if (st.is_subtype_of (uchar_type.type_symbol)) {
    1278              :                         return true;
    1279           25 :                 } else if (st.is_subtype_of (ushort_type.type_symbol)) {
    1280              :                         return true;
    1281           25 :                 } else if (st.is_subtype_of (uint_type.type_symbol)) {
    1282              :                         return true;
    1283           16 :                 } else if (st.is_subtype_of (ulong_type.type_symbol)) {
    1284              :                         return true;
    1285           16 :                 } else if (st.is_subtype_of (uint8_type.type_symbol)) {
    1286              :                         return true;
    1287           15 :                 } else if (st.is_subtype_of (uint16_type.type_symbol)) {
    1288              :                         return true;
    1289           15 :                 } else if (st.is_subtype_of (uint32_type.type_symbol)) {
    1290              :                         return true;
    1291              :                 } else {
    1292              :                         return false;
    1293              :                 }
    1294              :         }
    1295              : 
    1296       432812 :         public void check_type (DataType type) {
    1297              :                 // Allow any type-argument for GLib.Array
    1298       432812 :                 if (context != null && context.profile == Profile.GOBJECT
    1299       432562 :                     && type.type_symbol == garray_type.type_symbol) {
    1300              :                         return;
    1301              :                 }
    1302              : 
    1303       439397 :                 foreach (var type_arg in type.get_type_arguments ()) {
    1304         3301 :                         check_type (type_arg);
    1305         3301 :                         check_type_argument (type_arg);
    1306              :                 }
    1307              :         }
    1308              : 
    1309        29114 :         public void check_type_arguments (MemberAccess access) {
    1310        29286 :                 foreach (var type_arg in access.get_type_arguments ()) {
    1311           86 :                         check_type (type_arg);
    1312           86 :                         check_type_argument (type_arg);
    1313              :                 }
    1314              :         }
    1315              : 
    1316         3387 :         void check_type_argument (DataType type_arg) {
    1317         5381 :                 if (type_arg is GenericType
    1318         3016 :                     || type_arg is NullType
    1319         3015 :                     || type_arg is PointerType
    1320         1596 :                     || type_arg is VoidType
    1321         1596 :                     || is_reference_type_argument (type_arg)
    1322          223 :                     || is_nullable_value_type_argument (type_arg)
    1323          159 :                     || is_signed_integer_type_argument (type_arg)
    1324           16 :                     || is_unsigned_integer_type_argument (type_arg)) {
    1325              :                         // no error
    1326            6 :                 } else if (type_arg is DelegateType) {
    1327            1 :                         var delegate_type = (DelegateType) type_arg;
    1328            1 :                         if (delegate_type.delegate_symbol.has_target) {
    1329            1 :                                 Report.error (type_arg.source_reference, "Delegates with target are not supported as generic type arguments");
    1330              :                         }
    1331            4 :                 } else if (type_arg is ArrayType) {
    1332            3 :                         Report.error (type_arg.source_reference, "Arrays are not supported as generic type arguments");
    1333              :                 } else {
    1334            1 :                         Report.error (type_arg.source_reference, "`%s' is not a supported generic type argument, use `?' to box value types", type_arg.to_string ());
    1335              :                 }
    1336              :         }
    1337              : }
        

Generated by: LCOV version 2.0-1