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

            Line data    Source code
       1              : /* valamethodcall.vala
       2              :  *
       3              :  * Copyright (C) 2006-2012  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : /**
      26              :  * Represents an invocation expression in the source code.
      27              :  */
      28       449498 : public class Vala.MethodCall : Expression, CallableExpression {
      29              :         /**
      30              :          * The method to call.
      31              :          */
      32              :         public Expression call {
      33      5468889 :                 get { return _call; }
      34              :         }
      35              : 
      36       222677 :         public bool is_yield_expression { get; set; }
      37              : 
      38        40135 :         public bool is_assert { get; private set; }
      39              : 
      40              :         /**
      41              :          * Whether this chain up uses the constructv function with va_list.
      42              :          */
      43        30212 :         public bool is_constructv_chainup { get; private set; }
      44              : 
      45       767803 :         public bool is_chainup { get; set; }
      46              : 
      47       223212 :         private Expression _call;
      48              : 
      49       446424 :         private List<Expression> argument_list = new ArrayList<Expression> ();
      50              : 
      51              :         /**
      52              :          * Creates a new invocation expression.
      53              :          *
      54              :          * @param call             method to call
      55              :          * @param source_reference reference to source code
      56              :          * @return                 newly created invocation expression
      57              :          */
      58       669636 :         public MethodCall (Expression call, SourceReference? source_reference = null) {
      59       223212 :                 this.source_reference = source_reference;
      60      1005798 :                 this._call = call;
      61       223212 :                 this._call.parent_node = this;
      62              :         }
      63              : 
      64              :         /**
      65              :          * Appends the specified expression to the list of arguments.
      66              :          *
      67              :          * @param arg an argument
      68              :          */
      69       337898 :         public void add_argument (Expression arg) {
      70       337898 :                 argument_list.add (arg);
      71       337898 :                 arg.parent_node = this;
      72              :         }
      73              : 
      74              :         /**
      75              :          * Returns the argument list.
      76              :          *
      77              :          * @return argument list
      78              :          */
      79        73414 :         public unowned List<Expression> get_argument_list () {
      80        73414 :                 return argument_list;
      81              :         }
      82              : 
      83       869040 :         public override void accept (CodeVisitor visitor) {
      84       869040 :                 visitor.visit_method_call (this);
      85              : 
      86       869040 :                 visitor.visit_expression (this);
      87              :         }
      88              : 
      89       869039 :         public override void accept_children (CodeVisitor visitor) {
      90       869039 :                 call.accept (visitor);
      91              : 
      92      3736699 :                 foreach (Expression expr in argument_list) {
      93      1433830 :                         expr.accept (visitor);
      94              :                 }
      95              :         }
      96              : 
      97        10450 :         public override void replace_expression (Expression old_node, Expression new_node) {
      98        10450 :                 if (call == old_node) {
      99            5 :                         _call = new_node;
     100              :                 }
     101              : 
     102        10450 :                 int index = argument_list.index_of (old_node);
     103        10450 :                 if (index >= 0) {
     104        10445 :                         argument_list[index] = new_node;
     105        10445 :                         new_node.parent_node = this;
     106              :                 }
     107              :         }
     108              : 
     109          546 :         public override bool is_constant () {
     110          546 :                 unowned MethodType? method_type = call.value_type as MethodType;
     111              : 
     112          546 :                 if (method_type != null) {
     113              :                         // N_ and NC_ do not have any effect on the C code,
     114              :                         // they are only interpreted by xgettext
     115              :                         // this means that it is ok to use them in constant initializers
     116          546 :                         if (method_type.method_symbol.get_full_name () == "GLib.N_") {
     117              :                                 // first argument is string
     118            7 :                                 return argument_list[0].is_constant ();
     119          539 :                         } else if (method_type.method_symbol.get_full_name () == "GLib.NC_") {
     120              :                                 // first and second argument is string
     121            2 :                                 return argument_list[0].is_constant () && argument_list[1].is_constant ();
     122              :                         }
     123              :                 }
     124              : 
     125          546 :                 return false;
     126              :         }
     127              : 
     128            0 :         public override bool is_pure () {
     129            0 :                 return false;
     130              :         }
     131              : 
     132            8 :         public override bool is_accessible (Symbol sym) {
     133           26 :                 foreach (var arg in argument_list) {
     134            9 :                         if (!arg.is_accessible (sym)) {
     135            0 :                                 return false;
     136              :                         }
     137              :                 }
     138              : 
     139            8 :                 return call.is_accessible (sym);
     140              :         }
     141              : 
     142       752571 :         public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
     143       752571 :                 if (source_reference == null) {
     144       695060 :                         source_reference = this.source_reference;
     145              :                 }
     146       752571 :                 unowned DataType? mtype = call.value_type;
     147       752571 :                 if (mtype is MethodType) {
     148       709996 :                         unowned Method m = ((MethodType) mtype).method_symbol;
     149       709996 :                         if (!(m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end")) {
     150       709662 :                                 m.get_error_types (collection, source_reference);
     151              :                         }
     152        42575 :                 } else if (mtype is ObjectType && mtype.type_symbol is Class) {
     153              :                         // constructor
     154         3132 :                         unowned Class cl = (Class) ((ObjectType) mtype).type_symbol;
     155         3132 :                         unowned Method m = cl.default_construction_method;
     156         3132 :                         m.get_error_types (collection, source_reference);
     157        39443 :                 } else if (mtype is DelegateType) {
     158        38908 :                         unowned Delegate d = ((DelegateType) mtype).delegate_symbol;
     159        38908 :                         d.get_error_types (collection, source_reference);
     160              :                 }
     161              : 
     162      3013353 :                 foreach (Expression expr in argument_list) {
     163      1130391 :                         expr.get_error_types (collection, source_reference);
     164              :                 }
     165              :         }
     166              : 
     167       201891 :         public override bool check (CodeContext context) {
     168       201891 :                 if (checked) {
     169        10314 :                         return !error;
     170              :                 }
     171              : 
     172       191577 :                 checked = true;
     173              : 
     174       191577 :                 if ((call is MemberAccess) && ((MemberAccess) call).null_safe_access) {
     175            7 :                         error = !base.check (context);
     176            7 :                         return !error;
     177              :                 }
     178              : 
     179       191570 :                 if (!call.check (context)) {
     180              :                         /* if method resolving didn't succeed, skip this check */
     181           23 :                         error = true;
     182           23 :                         return false;
     183              :                 }
     184              : 
     185              :                 // type of target object
     186       191547 :                 DataType target_object_type = null;
     187              : 
     188       191547 :                 List<DataType> method_type_args = null;
     189              : 
     190       191547 :                 if (call.value_type is DelegateType) {
     191              :                         // delegate invocation, resolve generic types relative to delegate
     192        14311 :                         target_object_type = call.value_type;
     193       177236 :                 } else if (call is MemberAccess) {
     194       176601 :                         unowned MemberAccess ma = (MemberAccess) call;
     195       176601 :                         if (ma.prototype_access) {
     196            0 :                                 error = true;
     197            0 :                                 Report.error (source_reference, "Access to instance member `%s' denied", call.symbol_reference.get_full_name ());
     198            0 :                                 return false;
     199              :                         }
     200              : 
     201       368104 :                         method_type_args = ma.get_type_arguments ();
     202              : 
     203       176601 :                         if (ma.inner != null) {
     204       122424 :                                 target_object_type = ma.inner.value_type;
     205              : 
     206              :                                 // foo is relevant instance in foo.bar.connect (on_bar)
     207       122424 :                                 if (ma.inner.symbol_reference is Signal) {
     208          103 :                                         unowned MemberAccess? sig = ma.inner as MemberAccess;
     209           90 :                                         if (sig != null) {
     210          180 :                                                 target_object_type = sig.inner.value_type;
     211              :                                         }
     212              :                                 }
     213              : 
     214              :                                 // foo is relevant instance in foo.bar.begin (bar_ready) and foo.bar.end (result)
     215       122424 :                                 unowned Method? m = ma.symbol_reference as Method;
     216       122279 :                                 if (m != null && m.coroutine) {
     217              :                                         // begin or end call of async method
     218          107 :                                         if (ma.member_name == "begin" || ma.member_name == "end") {
     219           74 :                                                 unowned MemberAccess? method_access = ma.inner as MemberAccess;
     220           74 :                                                 if (method_access != null && method_access.inner != null) {
     221           68 :                                                         target_object_type = method_access.inner.value_type;
     222              :                                                 } else {
     223              :                                                         // static method
     224           38 :                                                         target_object_type = null;
     225              :                                                 }
     226              :                                         }
     227              :                                 }
     228              :                         }
     229              : 
     230       176601 :                         if (ma.symbol_reference != null && ma.symbol_reference.has_attribute ("Assert")) {
     231        10123 :                                 this.is_assert = true;
     232              : 
     233        10123 :                                 if (argument_list.size == 1) {
     234        10123 :                                         this.source_reference = argument_list[0].source_reference;
     235              :                                 }
     236              :                         }
     237              :                 }
     238              : 
     239       191547 :                 var mtype = call.value_type;
     240       191547 :                 var gobject_chainup = (context.profile == Profile.GOBJECT && call.symbol_reference == context.analyzer.object_type);
     241       191547 :                 is_chainup = gobject_chainup;
     242              : 
     243       191547 :                 if (!gobject_chainup) {
     244       191194 :                         unowned Expression expr = call;
     245       191194 :                         unowned MemberAccess? ma = expr as MemberAccess;
     246       190881 :                         if (ma != null && ma.symbol_reference is CreationMethod) {
     247         1425 :                                 expr = ma.inner;
     248         1425 :                                 ma = expr as MemberAccess;
     249              :                         }
     250       380960 :                         if (ma != null && ma.member_name == "this") {
     251              :                                 // this[.with_foo] ()
     252         1423 :                                 is_chainup = true;
     253       189771 :                         } else if (expr is BaseAccess) {
     254              :                                 // base[.with_foo] ()
     255          313 :                                 is_chainup = true;
     256              :                         }
     257              :                 }
     258              : 
     259       191547 :                 unowned CreationMethod? base_cm = null;
     260              : 
     261       191547 :                 if (is_chainup) {
     262         2089 :                         unowned CreationMethod? cm = context.analyzer.find_current_method () as CreationMethod;
     263         2089 :                         if (cm == null) {
     264            0 :                                 error = true;
     265            0 :                                 Report.error (source_reference, "invocation not supported in this context");
     266            0 :                                 return false;
     267         2089 :                         } else if (cm.chain_up) {
     268            0 :                                 error = true;
     269            0 :                                 Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted");
     270            0 :                                 return false;
     271              :                         }
     272         2089 :                         cm.chain_up = true;
     273              : 
     274         2089 :                         if (mtype is ObjectType) {
     275          635 :                                 unowned Class cl = (Class) ((ObjectType) mtype).type_symbol;
     276          635 :                                 base_cm = cl.default_construction_method;
     277          635 :                                 if (base_cm == null) {
     278            0 :                                         error = true;
     279            0 :                                         Report.error (source_reference, "chain up to `%s' not supported", cl.get_full_name ());
     280            0 :                                         return false;
     281          635 :                                 } else if (!base_cm.has_construct_function) {
     282            0 :                                         error = true;
     283            0 :                                         Report.error (source_reference, "chain up to `%s' not supported", base_cm.get_full_name ());
     284            0 :                                         return false;
     285              :                                 }
     286         1454 :                         } else if (call.symbol_reference is CreationMethod && call.symbol_reference.parent_symbol is Class) {
     287         1421 :                                 base_cm = (CreationMethod) call.symbol_reference;
     288         1421 :                                 if (!base_cm.has_construct_function) {
     289            0 :                                         error = true;
     290            0 :                                         Report.error (source_reference, "chain up to `%s' not supported", base_cm.get_full_name ());
     291            0 :                                         return false;
     292              :                                 }
     293           33 :                         } else if (gobject_chainup) {
     294           29 :                                 unowned Class? cl = cm.parent_symbol as Class;
     295           29 :                                 if (cl == null || !cl.is_subtype_of (context.analyzer.object_type)) {
     296            0 :                                         error = true;
     297            0 :                                         Report.error (source_reference, "chain up to `GLib.Object' not supported");
     298            0 :                                         return false;
     299              :                                 }
     300           29 :                                 call.value_type = new ObjectType (context.analyzer.object_type, source_reference);
     301           58 :                                 mtype = call.value_type;
     302              :                         }
     303              : 
     304         2056 :                         if (base_cm != null && source_reference.file != base_cm.source_reference.file && base_cm.access == SymbolAccessibility.PRIVATE) {
     305            0 :                                 error = true;
     306            0 :                                 Report.error (source_reference, "chain up to private `%s' not possible", base_cm.get_full_name ());
     307            0 :                                 return false;
     308              :                         }
     309              :                 }
     310              : 
     311              :                 // check for struct construction
     312       191547 :                 if (call is MemberAccess &&
     313       190910 :                     ((call.symbol_reference is CreationMethod
     314         1425 :                       && call.symbol_reference.parent_symbol is Struct)
     315       190906 :                      || call.symbol_reference is Struct)) {
     316          121 :                         unowned Struct? st = call.symbol_reference as Struct;
     317          117 :                         if (st != null && st.default_construction_method == null && (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ())) {
     318            0 :                                 error = true;
     319            0 :                                 Report.error (source_reference, "invocation not supported in this context");
     320            0 :                                 return false;
     321              :                         }
     322              : 
     323          121 :                         var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) call, source_reference);
     324          121 :                         struct_creation_expression.struct_creation = true;
     325          121 :                         struct_creation_expression.is_chainup = is_chainup;
     326          281 :                         foreach (Expression arg in argument_list) {
     327           80 :                                 struct_creation_expression.add_argument (arg);
     328              :                         }
     329          121 :                         struct_creation_expression.target_type = target_type;
     330          121 :                         context.analyzer.replaced_nodes.add (this);
     331          121 :                         parent_node.replace_expression (this, struct_creation_expression);
     332          121 :                         struct_creation_expression.check (context);
     333          121 :                         return true;
     334       191426 :                 } else if (!is_chainup && call is MemberAccess && call.symbol_reference is CreationMethod) {
     335            0 :                         error = true;
     336            0 :                         Report.error (source_reference, "use `new' operator to create new objects");
     337            0 :                         return false;
     338              :                 }
     339              : 
     340       191426 :                 if (!is_chainup && mtype is ObjectType) {
     341              :                         // prevent funny stuff like (new Object ()) ()
     342            1 :                         error = true;
     343            1 :                         Report.error (source_reference, "invocation not supported in this context");
     344            1 :                         return false;
     345       191425 :                 } else if (mtype != null && mtype.is_invokable ()) {
     346              :                         // call ok, expression is invokable
     347            0 :                 } else if (call.symbol_reference is Class) {
     348            0 :                         error = true;
     349            0 :                         Report.error (source_reference, "use `new' operator to create new objects");
     350            0 :                         return false;
     351              :                 } else {
     352            0 :                         error = true;
     353            0 :                         Report.error (source_reference, "invocation not supported in this context");
     354            0 :                         return false;
     355              :                 }
     356              : 
     357       191425 :                 var ret_type = mtype.get_return_type ();
     358       191425 :                 var params = mtype.get_parameters ();
     359              : 
     360       191425 :                 if (mtype is MethodType) {
     361       176351 :                         unowned MemberAccess ma = (MemberAccess) call;
     362       176351 :                         unowned Method m = ((MethodType) mtype).method_symbol;
     363              : 
     364       176351 :                         if (m.coroutine) {
     365          124 :                                 if (!is_yield_expression) {
     366              :                                         // begin or end call of async method
     367           78 :                                         if (ma.member_name != "end") {
     368              :                                                 // begin (possibly implicit)
     369           56 :                                                 if (ma.member_name != "begin") {
     370            5 :                                                         Report.deprecated (ma.source_reference, "implicit .begin is deprecated");
     371              :                                                 }
     372          112 :                                                 params = m.get_async_begin_parameters ();
     373           56 :                                                 ret_type = new VoidType ();
     374              :                                         } else {
     375              :                                                 // end
     376           44 :                                                 params = m.get_async_end_parameters ();
     377              :                                         }
     378           46 :                                 } else if (ma.member_name == "begin" || ma.member_name == "end") {
     379            1 :                                         error = true;
     380            1 :                                         Report.error (ma.source_reference, "use of `%s' not allowed in yield statement", ma.member_name);
     381              :                                 }
     382              :                         }
     383              : 
     384       176351 :                         int n_type_params = m.get_type_parameters ().size;
     385       176351 :                         int n_type_args = ma.get_type_arguments ().size;
     386       176351 :                         if (n_type_args > 0 && n_type_args < n_type_params) {
     387            1 :                                 error = true;
     388            1 :                                 Report.error (ma.source_reference, "too few type arguments for `%s'", m.to_string ());
     389            1 :                                 return false;
     390       176350 :                         } else if (n_type_args > 0 && n_type_args > n_type_params) {
     391            1 :                                 error = true;
     392            1 :                                 Report.error (ma.source_reference, "too many type arguments for `%s'", m.to_string ());
     393            1 :                                 return false;
     394              :                         }
     395              :                 }
     396              : 
     397              :                 // FIXME partial code duplication in ObjectCreationExpression.check
     398              : 
     399       191423 :                 Expression last_arg = null;
     400              : 
     401       191423 :                 Iterator<Expression> arg_it = argument_list.iterator ();
     402       727421 :                 foreach (Parameter param in params) {
     403       284551 :                         if (!param.check (context)) {
     404            0 :                                 error = true;
     405              :                         }
     406              : 
     407       284551 :                         if (param.ellipsis) {
     408        16536 :                                 break;
     409              :                         }
     410              : 
     411       268015 :                         if (param.params_array) {
     412           32 :                                 var array_type = (ArrayType) param.variable_type;
     413          112 :                                 while (arg_it.next ()) {
     414           48 :                                         Expression arg = arg_it.get ();
     415              : 
     416              :                                         /* store expected type for callback parameters */
     417           48 :                                         arg.target_type = array_type.element_type;
     418           48 :                                         arg.target_type.value_owned = array_type.value_owned;
     419              :                                 }
     420           16 :                                 break;
     421              :                         }
     422              : 
     423       524918 :                         if (arg_it.next ()) {
     424       256919 :                                 Expression arg = arg_it.get ();
     425              : 
     426              :                                 /* store expected type for callback parameters */
     427       256919 :                                 arg.formal_target_type = param.variable_type;
     428       256919 :                                 arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, method_type_args, this);
     429              : 
     430       513838 :                                 last_arg = arg;
     431              :                         }
     432              :                 }
     433              : 
     434              :                 // concatenate stringified arguments for methods with attribute [Print]
     435       191426 :                 if (mtype is MethodType && ((MethodType) mtype).method_symbol.has_attribute ("Print")) {
     436            3 :                         var template = new Template (source_reference);
     437           25 :                         foreach (Expression arg in argument_list) {
     438           11 :                                 arg.parent_node = null;
     439           11 :                                 template.add_expression (arg);
     440              :                         }
     441            3 :                         argument_list.clear ();
     442            3 :                         add_argument (template);
     443              :                 }
     444              : 
     445              :                 // printf arguments
     446       191423 :                 if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
     447         3289 :                         StringLiteral format_literal = null;
     448         3289 :                         if (last_arg is NullLiteral) {
     449              :                                 // do not replace explicit null
     450         3288 :                         } else if (last_arg != null) {
     451              :                                 // use last argument as format string
     452          777 :                                 format_literal = StringLiteral.get_format_literal (last_arg);
     453          777 :                                 if (format_literal == null && argument_list.size == params.size - 1) {
     454              :                                         // insert "%s" to avoid issues with embedded %
     455           14 :                                         format_literal = new StringLiteral ("\"%s\"");
     456           14 :                                         format_literal.target_type = context.analyzer.string_type.copy ();
     457           14 :                                         argument_list.insert (argument_list.size - 1, format_literal);
     458              : 
     459              :                                         // recreate iterator and skip to right position
     460           14 :                                         arg_it = argument_list.iterator ();
     461           84 :                                         foreach (Parameter param in params) {
     462           49 :                                                 if (param.ellipsis || param.params_array) {
     463           14 :                                                         break;
     464              :                                                 }
     465           35 :                                                 arg_it.next ();
     466              :                                         }
     467              :                                 }
     468              :                         } else {
     469              :                                 // use instance as format string for string.printf (...)
     470         2511 :                                 unowned MemberAccess? ma = call as MemberAccess;
     471         2511 :                                 if (ma != null) {
     472         2511 :                                         format_literal = StringLiteral.get_format_literal (ma.inner);
     473              :                                 }
     474              :                         }
     475         6489 :                         if (format_literal != null) {
     476         3203 :                                 string format = format_literal.eval ();
     477         3203 :                                 if (!context.analyzer.check_print_format (format, arg_it, source_reference)) {
     478            2 :                                         error = true;
     479            2 :                                         return false;
     480              :                                 }
     481              :                         }
     482              :                 }
     483              : 
     484       191421 :                 bool force_lambda_method_closure = false;
     485       752043 :                 foreach (Expression arg in argument_list) {
     486       280317 :                         if (!arg.check (context)) {
     487           12 :                                 error = true;
     488           12 :                                 continue;
     489              :                         }
     490              : 
     491       280305 :                         if (arg is LambdaExpression && ((LambdaExpression) arg).method.closure) {
     492       280305 :                                 force_lambda_method_closure = true;
     493              :                         }
     494              :                 }
     495              :                 // force all lambda arguments using the same closure scope
     496              :                 // TODO https://gitlab.gnome.org/GNOME/vala/issues/59
     497       191421 :                 if (!error && force_lambda_method_closure) {
     498        22835 :                         foreach (Expression arg in argument_list) {
     499         8562 :                                 unowned LambdaExpression? lambda = arg as LambdaExpression;
     500        12822 :                                 if (lambda != null && lambda.method.binding != MemberBinding.STATIC) {
     501         4260 :                                         lambda.method.closure = true;
     502              :                                 }
     503              :                         }
     504              :                 }
     505              : 
     506       191421 :                 if (ret_type is VoidType) {
     507              :                         // void return type
     508        71941 :                         if (!(parent_node is ExpressionStatement)
     509            1 :                             && !(parent_node is ForStatement)
     510            1 :                             && !(parent_node is YieldStatement)) {
     511              :                                 // A void method invocation can be in the initializer or
     512              :                                 // iterator of a for statement
     513            1 :                                 error = true;
     514            1 :                                 Report.error (source_reference, "invocation of void method not allowed as expression");
     515            1 :                                 return false;
     516              :                         }
     517              :                 }
     518              : 
     519       191420 :                 formal_value_type = ret_type.copy ();
     520       191420 :                 value_type = formal_value_type.get_actual_type (target_object_type, method_type_args, this);
     521              : 
     522       191420 :                 if (is_yield_expression) {
     523           48 :                         if (!(mtype is MethodType) || !((MethodType) mtype).method_symbol.coroutine) {
     524            2 :                                 error = true;
     525            2 :                                 Report.error (source_reference, "yield expression requires async method");
     526              :                         }
     527           48 :                         if (context.analyzer.current_method == null || !context.analyzer.current_method.coroutine) {
     528            2 :                                 error = true;
     529            2 :                                 Report.error (source_reference, "yield expression not available outside async method");
     530              :                         }
     531              :                 }
     532              : 
     533       191420 :                 if (mtype is MethodType) {
     534       176346 :                         unowned Method m = ((MethodType) mtype).method_symbol;
     535       176346 :                         if (m.returns_floating_reference) {
     536           10 :                                 value_type.floating_reference = true;
     537              :                         }
     538       176346 :                         if (m.returns_modified_pointer) {
     539         5711 :                                 unowned Expression inner = ((MemberAccess) call).inner;
     540         5711 :                                 inner.lvalue = true;
     541         5711 :                                 unowned Property? prop = inner.symbol_reference as Property;
     542            2 :                                 if (prop != null && (prop.set_accessor == null || !prop.set_accessor.writable)) {
     543            1 :                                         error = true;
     544            1 :                                         Report.error (inner.source_reference, "Property `%s' is read-only", prop.get_full_name ());
     545              :                                 }
     546              :                         }
     547              :                         // avoid passing possible null to ref_sink_function without checking
     548       176346 :                         if (tree_can_fail && !value_type.nullable && value_type.floating_reference && ret_type is ObjectType) {
     549            0 :                                 value_type.nullable = true;
     550              :                         }
     551              : 
     552       176346 :                         unowned Signal? sig = m.parent_symbol as Signal;
     553          103 :                         if (sig != null && m.name == "disconnect") {
     554           13 :                                 if (!argument_list.is_empty && argument_list[0] is LambdaExpression) {
     555            1 :                                         error = true;
     556            1 :                                         Report.error (source_reference, "Cannot disconnect lambda expression from signal");
     557            1 :                                         return false;
     558              :                                 }
     559              :                         }
     560              : 
     561       176345 :                         unowned DynamicSignal? dynamic_sig = m.parent_symbol as DynamicSignal;
     562            6 :                         if (dynamic_sig != null && dynamic_sig.handler != null) {
     563            6 :                                 dynamic_sig.return_type = dynamic_sig.handler.value_type.get_return_type ().copy ();
     564            6 :                                 bool first = true;
     565           18 :                                 foreach (Parameter param in dynamic_sig.handler.value_type.get_parameters ()) {
     566            6 :                                         if (first) {
     567              :                                                 // skip sender parameter
     568              :                                                 first = false;
     569              :                                         } else {
     570            4 :                                                 dynamic_sig.add_parameter (param.copy ());
     571              :                                         }
     572              :                                 }
     573            6 :                                 dynamic_sig.handler.target_type = new DelegateType (dynamic_sig.get_delegate (new ObjectType ((ObjectTypeSymbol) dynamic_sig.parent_symbol), this), source_reference);
     574              :                         }
     575              : 
     576       176345 :                         if (m != null && m.has_type_parameters ()) {
     577         1594 :                                 unowned MemberAccess ma = (MemberAccess) call;
     578         1594 :                                 if (ma.get_type_arguments ().size == 0) {
     579              :                                         // infer type arguments
     580          296 :                                         foreach (var type_param in m.get_type_parameters ()) {
     581          100 :                                                 DataType type_arg = null;
     582              : 
     583              :                                                 // infer type arguments from arguments
     584          100 :                                                 arg_it = argument_list.iterator ();
     585          370 :                                                 foreach (Parameter param in params) {
     586          186 :                                                         if (param.ellipsis || param.params_array) {
     587            0 :                                                                 break;
     588              :                                                         }
     589              : 
     590          285 :                                                         if (arg_it.next ()) {
     591          150 :                                                                 Expression arg = arg_it.get ();
     592              : 
     593          150 :                                                                 if (param.initializer is SizeofExpression && arg is SizeofExpression
     594            2 :                                                                     && ((SizeofExpression) param.initializer).type_reference.type_symbol == type_param) {
     595            2 :                                                                         type_arg = ((SizeofExpression) arg).type_reference.copy ();
     596          148 :                                                                 } else if (param.initializer is TypeofExpression && arg is TypeofExpression
     597            2 :                                                                     && ((TypeofExpression) param.initializer).type_reference.type_symbol == type_param) {
     598            2 :                                                                         type_arg = ((TypeofExpression) arg).type_reference.copy ();
     599              :                                                                 } else {
     600          146 :                                                                         type_arg = param.variable_type.infer_type_argument (type_param, arg.value_type);
     601              :                                                                 }
     602              : 
     603          150 :                                                                 if (type_arg != null) {
     604           51 :                                                                         break;
     605              :                                                                 }
     606              : 
     607           99 :                                                                 arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, method_type_args, this);
     608              :                                                         }
     609              :                                                 }
     610              : 
     611              :                                                 // infer type arguments from expected return type
     612          100 :                                                 if (type_arg == null && target_type != null) {
     613           49 :                                                         type_arg = m.return_type.infer_type_argument (type_param, target_type);
     614              :                                                 }
     615              : 
     616          100 :                                                 if (type_arg == null) {
     617            0 :                                                         error = true;
     618            0 :                                                         Report.error (ma.source_reference, "cannot infer generic type argument for type parameter `%s'", type_param.get_full_name ());
     619            0 :                                                         return false;
     620              :                                                 }
     621              : 
     622          100 :                                                 ma.add_type_argument (type_arg);
     623              :                                         }
     624              : 
     625              :                                         // recalculate argument target types with new information
     626           96 :                                         arg_it = argument_list.iterator ();
     627          464 :                                         foreach (Parameter param in params) {
     628          184 :                                                 if (param.ellipsis || param.params_array) {
     629            0 :                                                         break;
     630              :                                                 }
     631              : 
     632          331 :                                                 if (arg_it.next ()) {
     633          147 :                                                         Expression arg = arg_it.get ();
     634              : 
     635          147 :                                                         arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, method_type_args, this);
     636              :                                                 }
     637              :                                         }
     638              : 
     639              :                                         // recalculate return value type with new information
     640           96 :                                         value_type = formal_value_type.get_actual_type (target_object_type, method_type_args, this);
     641              :                                 }
     642              :                         }
     643              :                         // replace method-type if needed for proper argument-check in semantic-analyser
     644       176345 :                         if (m != null && m.coroutine) {
     645          124 :                                 unowned MemberAccess ma = (MemberAccess) call;
     646          124 :                                 if (ma.member_name == "end") {
     647           22 :                                         mtype = new MethodType (m.get_end_method (), source_reference);
     648              :                                 }
     649              :                         }
     650              :                 }
     651              : 
     652       191419 :                 if (!context.analyzer.check_arguments (this, mtype, params, argument_list)) {
     653           31 :                         error = true;
     654           31 :                         return false;
     655              :                 }
     656              : 
     657              :                 //Resolve possible generic-type in certain Expressions used as parameter default-value
     658       191388 :                 arg_it = argument_list.iterator ();
     659       470433 :                 foreach (Parameter param in params) {
     660       284514 :                         if (param.ellipsis || param.params_array) {
     661        16547 :                                 break;
     662              :                         }
     663       279045 :                         if (arg_it.next ()) {
     664       267967 :                                 Expression arg = arg_it.get ();
     665       267967 :                                 if (param.initializer != arg) {
     666       256889 :                                         continue;
     667              :                                 }
     668        11078 :                                 unowned SizeofExpression? sizeof_expr = arg as SizeofExpression;
     669           12 :                                 if (sizeof_expr != null && sizeof_expr.type_reference is GenericType) {
     670            6 :                                         var sizeof_type = sizeof_expr.type_reference.get_actual_type (target_object_type, method_type_args, this);
     671            6 :                                         replace_expression (arg, new SizeofExpression (sizeof_type, source_reference));
     672              :                                 }
     673        11078 :                                 unowned TypeofExpression? typeof_expr = arg as TypeofExpression;
     674        11081 :                                 if (typeof_expr != null && typeof_expr.type_reference is GenericType) {
     675            3 :                                         var typeof_type = typeof_expr.type_reference.get_actual_type (target_object_type, method_type_args, this);
     676            3 :                                         replace_expression (arg, new TypeofExpression (typeof_type, source_reference));
     677              :                                 }
     678              :                         }
     679              :                 }
     680              : 
     681              :                 /* Check for constructv chain up */
     682       191393 :                 if (base_cm != null && base_cm.is_variadic () && argument_list.size == base_cm.get_parameters ().size) {
     683            5 :                         var this_last_arg = argument_list[argument_list.size - 1];
     684            5 :                         if (this_last_arg.value_type is StructValueType && this_last_arg.value_type.type_symbol == context.analyzer.va_list_type.type_symbol) {
     685            4 :                                 is_constructv_chainup = true;
     686              :                         }
     687              :                 }
     688              : 
     689       191388 :                 value_type.check (context);
     690              : 
     691              :                 // FIXME code duplication in ObjectCreationExpression.check
     692       191388 :                 if (tree_can_fail) {
     693         3313 :                         if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
     694              :                                 // simple statements, no side effects after method call
     695         5785 :                         } else if (!(context.analyzer.current_symbol is Block)) {
     696              :                                 // can't handle errors in field initializers
     697            1 :                                 error = true;
     698            1 :                                 Report.error (source_reference, "Field initializers must not throw errors");
     699              :                         } else {
     700              :                                 // store parent_node as we need to replace the expression in the old parent node later on
     701         2892 :                                 var old_parent_node = parent_node;
     702              : 
     703         2892 :                                 var local = new LocalVariable (value_type.copy (), get_temp_name (), null, source_reference);
     704         2892 :                                 var decl = new DeclarationStatement (local, source_reference);
     705              : 
     706              :                                 // don't carry floating reference any further if the target-type is unknown
     707         2892 :                                 if (target_type == null) {
     708           26 :                                         local.variable_type.floating_reference = false;
     709              :                                 }
     710              : 
     711         2892 :                                 insert_statement (context.analyzer.insert_block, decl);
     712              : 
     713         2892 :                                 var temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
     714         2892 :                                 temp_access.formal_target_type = formal_target_type;
     715         2892 :                                 formal_target_type = null;
     716              : 
     717              :                                 // don't set initializer earlier as this changes parent_node and parent_statement
     718         2892 :                                 local.initializer = this;
     719         2892 :                                 decl.check (context);
     720              : 
     721              :                                 // move temp variable to insert block to ensure the
     722              :                                 // variable is in the same block as the declaration
     723              :                                 // otherwise there will be scoping issues in the generated code
     724         2892 :                                 var block = (Block) context.analyzer.current_symbol;
     725         2892 :                                 block.remove_local_variable (local);
     726         2892 :                                 context.analyzer.insert_block.add_local_variable (local);
     727              : 
     728         2892 :                                 old_parent_node.replace_expression (this, temp_access);
     729         2892 :                                 temp_access.check (context);
     730              :                         }
     731              :                 }
     732              : 
     733       191388 :                 return !error;
     734              :         }
     735              : 
     736        30176 :         public override void emit (CodeGenerator codegen) {
     737        30176 :                 unowned MethodType? method_type = call.value_type as MethodType;
     738        30176 :                 if (method_type != null && method_type.method_symbol.parent_symbol is Signal) {
     739          101 :                         ((MemberAccess) call).inner.emit (codegen);
     740              :                 } else {
     741        30075 :                         call.emit (codegen);
     742              :                 }
     743              : 
     744       101494 :                 foreach (Expression expr in argument_list) {
     745        35659 :                         expr.emit (codegen);
     746              :                 }
     747              : 
     748        30176 :                 codegen.visit_method_call (this);
     749              : 
     750        30176 :                 codegen.visit_expression (this);
     751              :         }
     752              : 
     753       417987 :         public override void get_defined_variables (Collection<Variable> collection) {
     754       417987 :                 call.get_defined_variables (collection);
     755              : 
     756      1672893 :                 foreach (Expression arg in argument_list) {
     757       627453 :                         arg.get_defined_variables (collection);
     758              :                 }
     759              :         }
     760              : 
     761       139630 :         public override void get_used_variables (Collection<Variable> collection) {
     762       139630 :                 call.get_used_variables (collection);
     763              : 
     764       558520 :                 foreach (Expression arg in argument_list) {
     765       209445 :                         arg.get_used_variables (collection);
     766              :                 }
     767              :         }
     768              : 
     769           11 :         public StringLiteral? get_format_literal () {
     770           11 :                 unowned MethodType? mtype = this.call.value_type as MethodType;
     771            1 :                 if (mtype != null) {
     772            1 :                         int format_arg = mtype.method_symbol.get_format_arg_index ();
     773            1 :                         if (format_arg >= 0 && format_arg < argument_list.size) {
     774            0 :                                 return StringLiteral.get_format_literal (argument_list[format_arg]);
     775              :                         }
     776              :                 }
     777              : 
     778           11 :                 return null;
     779              :         }
     780              : 
     781            0 :         public override string to_string () {
     782            0 :                 var b = new StringBuilder ();
     783            0 :                 if (is_yield_expression) {
     784            0 :                         b.append ("yield ");
     785              :                 }
     786            0 :                 b.append (call.to_string ());
     787            0 :                 b.append_c ('(');
     788              : 
     789            0 :                 bool first = true;
     790            0 :                 foreach (var expr in argument_list) {
     791            0 :                         if (!first) {
     792            0 :                                 b.append (", ");
     793              :                         }
     794            0 :                         b.append (expr.to_string ());
     795            0 :                         first = false;
     796              :                 }
     797            0 :                 b.append_c (')');
     798              : 
     799            0 :                 return b.str;
     800              :         }
     801              : }
        

Generated by: LCOV version 2.0-1