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

            Line data    Source code
       1              : /* valalocalvariable.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  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 a local variable declaration in the source code.
      27              :  */
      28       673449 : public class Vala.LocalVariable : Variable {
      29       138357 :         public bool is_result { get; set; }
      30              : 
      31       170869 :         public bool captured { get; set; }
      32              : 
      33       187025 :         public bool init { get; set; }
      34              : 
      35              :         /**
      36              :          * Creates a new local variable.
      37              :          *
      38              :          * @param name              name of the variable
      39              :          * @param initializer       optional initializer expression
      40              :          * @param source_reference  reference to source code
      41              :          * @return                  newly created variable declarator
      42              :          */
      43      2015736 :         public LocalVariable (DataType? variable_type, string name, Expression? initializer = null, SourceReference? source_reference = null) {
      44       671912 :                 base (variable_type, name, initializer, source_reference);
      45              :         }
      46              : 
      47       212180 :         public override void accept (CodeVisitor visitor) {
      48       212180 :                 visitor.visit_local_variable (this);
      49              :         }
      50              : 
      51        94788 :         public override void accept_children (CodeVisitor visitor) {
      52        94788 :                 if (initializer != null) {
      53        72915 :                         initializer.accept (visitor);
      54              : 
      55        72915 :                         visitor.visit_end_full_expression (initializer);
      56              :                 }
      57              : 
      58        94788 :                 if (variable_type != null) {
      59        94747 :                         variable_type.accept (visitor);
      60              :                 }
      61              :         }
      62              : 
      63          376 :         public override void replace_expression (Expression old_node, Expression new_node) {
      64          376 :                 if (initializer == old_node) {
      65          376 :                         initializer = new_node;
      66              :                 }
      67              :         }
      68              : 
      69        47828 :         public override void replace_type (DataType old_type, DataType new_type) {
      70        47828 :                 if (variable_type == old_type) {
      71        47828 :                         variable_type = new_type;
      72              :                 }
      73              :         }
      74              : 
      75       601906 :         public override bool check (CodeContext context) {
      76       601906 :                 if (checked) {
      77       441835 :                         return !error;
      78              :                 }
      79              : 
      80       160071 :                 checked = true;
      81              : 
      82       160071 :                 if (variable_type == null) {
      83        12626 :                         variable_type = new VarType ();
      84              :                 }
      85              : 
      86       160071 :                 if (!context.experimental_non_null) {
      87              :                         // local reference variables are considered nullable
      88              :                         // except when using experimental non-null enhancements
      89       158690 :                         if (variable_type is ReferenceType) {
      90        36059 :                                 unowned ArrayType? array_type = variable_type as ArrayType;
      91        36059 :                                 if (array_type != null && array_type.fixed_length) {
      92              :                                         // local fixed length arrays are not nullable
      93              :                                 } else {
      94        36020 :                                         variable_type.nullable = true;
      95              :                                 }
      96              :                         }
      97              :                 }
      98              : 
      99       160071 :                 if (!(variable_type is VarType)) {
     100       139633 :                         if (variable_type is VoidType) {
     101            1 :                                 error = true;
     102            1 :                                 Report.error (source_reference, "'void' not supported as variable type");
     103       139632 :                         } else if (!variable_type.check (context)) {
     104           10 :                                 error = true;
     105              :                         }
     106       139633 :                         if (!external_package) {
     107         7950 :                                 context.analyzer.check_type (variable_type);
     108         7950 :                                 variable_type.check_type_arguments (context, true);
     109              :                         }
     110              :                 }
     111              : 
     112              :                 // Catch initializer list transformation:
     113       160071 :                 bool is_initializer_list = false;
     114       160071 :                 int initializer_size = -1;
     115              : 
     116       160071 :                 if (initializer != null && !error) {
     117        93249 :                         initializer.target_type = variable_type;
     118              : 
     119        93249 :                         if (initializer is InitializerList) {
     120          185 :                                 initializer_size = ((InitializerList) initializer).size;
     121          185 :                                 is_initializer_list = true;
     122              :                         }
     123              : 
     124        93249 :                         if (!initializer.check (context)) {
     125           66 :                                 error = true;
     126        93183 :                         } else if (initializer.value_type is VoidType) {
     127            0 :                                 error = true;
     128            0 :                                 Report.error (initializer.source_reference, "'void' not supported as initializer type");
     129              :                         }
     130              :                 }
     131              : 
     132              :                 // local variables are defined even on errors
     133       160071 :                 context.analyzer.current_symbol.scope.add (name, this);
     134              : 
     135       160071 :                 if (error) {
     136          102 :                         return false;
     137              :                 }
     138              : 
     139       159994 :                 if (variable_type is VarType) {
     140              :                         /* var type */
     141              : 
     142        20400 :                         if (initializer == null) {
     143            1 :                                 error = true;
     144            1 :                                 Report.error (source_reference, "var declaration not allowed without initializer");
     145            1 :                                 return false;
     146              :                         }
     147        20399 :                         if (initializer.value_type == null) {
     148            0 :                                 error = true;
     149            0 :                                 Report.error (source_reference, "var declaration not allowed with non-typed initializer");
     150            0 :                                 return false;
     151              :                         }
     152        20399 :                         if (initializer.value_type is FieldPrototype || initializer.value_type is PropertyPrototype) {
     153            2 :                                 error = true;
     154            2 :                                 Report.error (initializer.source_reference, "Access to instance member `%s' denied", initializer.symbol_reference.get_full_name ());
     155            2 :                                 return false;
     156              :                         }
     157              : 
     158        20397 :                         bool nullable = variable_type.nullable;
     159        20397 :                         bool value_owned = variable_type.value_owned;
     160        20397 :                         bool is_dynamic = variable_type.is_dynamic;
     161        20397 :                         variable_type = initializer.value_type.copy ();
     162        20397 :                         variable_type.value_owned = value_owned;
     163        20397 :                         variable_type.floating_reference = false;
     164        20397 :                         if (nullable) {
     165           10 :                                 variable_type.nullable = true;
     166              :                         }
     167        20397 :                         if (is_dynamic) {
     168            8 :                                 variable_type.is_dynamic = true;
     169              :                         }
     170              : 
     171        20397 :                         initializer.target_type = variable_type;
     172        20397 :                         variable_type.check (context);
     173              :                 }
     174              : 
     175       159991 :                 if (!external_package) {
     176              :                         // check symbol availability
     177        12719 :                         if (variable_type.type_symbol != null) {
     178        12150 :                                 variable_type.type_symbol.version.check (context, source_reference);
     179              :                         }
     180              :                 }
     181              : 
     182       159991 :                 unowned ArrayType? variable_array_type = variable_type as ArrayType;
     183         9004 :                 if (variable_array_type != null && variable_array_type.inline_allocated
     184           44 :                     && initializer is ArrayCreationExpression && ((ArrayCreationExpression) initializer).initializer_list == null) {
     185            2 :                         Report.warning (source_reference, "Inline allocated arrays don't require an explicit instantiation");
     186            2 :                         initializer = null;
     187              :                 }
     188              : 
     189       159991 :                 if (variable_array_type != null && variable_array_type.inline_allocated
     190           44 :                     && variable_array_type.length == null && !(initializer is ArrayCreationExpression)) {
     191            2 :                         error = true;
     192            2 :                         Report.error (source_reference, "Inline allocated array requires either a given length or an initializer");
     193              :                 }
     194              : 
     195       159991 :                 if (initializer != null && !initializer.error) {
     196        93179 :                         if (initializer.value_type is MethodType) {
     197           92 :                                 if (!(initializer is MemberAccess) && !(initializer is LambdaExpression)) {
     198            0 :                                         error = true;
     199            0 :                                         Report.error (initializer.source_reference, "expression type not allowed as initializer");
     200            0 :                                         return false;
     201              :                                 }
     202              : 
     203           92 :                                 if (variable_type is DelegateType) {
     204              :                                         /* check whether method matches callback type */
     205           91 :                                         if (!initializer.value_type.compatible (variable_type)) {
     206            5 :                                                 unowned Method m = (Method) initializer.symbol_reference;
     207            5 :                                                 unowned Delegate cb = ((DelegateType) variable_type).delegate_symbol;
     208            5 :                                                 error = true;
     209            5 :                                                 Report.error (source_reference, "Declaration of method `%s' is not compatible with delegate `%s'", m.get_full_name (), cb.get_full_name ());
     210            5 :                                                 return false;
     211              :                                         }
     212              :                                 } else {
     213            1 :                                         error = true;
     214            1 :                                         Report.error (initializer.source_reference, "expression type not allowed as initializer");
     215            1 :                                         return false;
     216              :                                 }
     217        93087 :                         } else if (initializer.value_type == null) {
     218            1 :                                 error = true;
     219            1 :                                 Report.error (initializer.source_reference, "expression type not allowed as initializer");
     220            1 :                                 return false;
     221              :                         }
     222              : 
     223        93172 :                         if (!initializer.value_type.compatible (variable_type)) {
     224           14 :                                 error = true;
     225           14 :                                 Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'", initializer.value_type.to_string (), variable_type.to_string ());
     226           14 :                                 return false;
     227        93158 :                         } else if (variable_type is EnumValueType && initializer.value_type is IntegerType
     228            3 :                             && (!(initializer is IntegerLiteral) || ((IntegerLiteral) initializer).value != "0")) {
     229              :                                 //FIXME This will have to be an error in the future?
     230            1 :                                 Report.notice (source_reference, "Assignment: Unsafe conversion from `%s' to `%s'", initializer.value_type.to_string (), variable_type.to_string ());
     231              :                         }
     232              : 
     233        93158 :                         if (variable_array_type != null && variable_array_type.inline_allocated && !variable_array_type.fixed_length && is_initializer_list) {
     234            4 :                                 variable_array_type.length = new IntegerLiteral (initializer_size.to_string ());
     235            4 :                                 variable_array_type.fixed_length = true;
     236            4 :                                 variable_array_type.nullable = false;
     237              :                         }
     238              : 
     239        93158 :                         if (variable_array_type != null && variable_array_type.inline_allocated && initializer.value_type is ArrayType == false) {
     240            0 :                                 error = true;
     241            0 :                                 Report.error (source_reference, "only arrays are allowed as initializer for arrays with fixed length");
     242            0 :                                 return false;
     243              :                         }
     244              : 
     245        93158 :                         if (initializer.value_type.is_disposable ()) {
     246              :                                 /* rhs transfers ownership of the expression */
     247        23165 :                                 if (!(variable_type is PointerType) && !variable_type.value_owned) {
     248              :                                         /* lhs doesn't own the value */
     249            1 :                                         error = true;
     250            1 :                                         Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
     251            1 :                                         return false;
     252              :                                 }
     253              :                         }
     254              :                 }
     255              : 
     256              :                 // current_symbol is a Method if this is the `result'
     257              :                 // variable used for postconditions
     258       159969 :                 unowned Block? block = context.analyzer.current_symbol as Block;
     259       159955 :                 if (block != null) {
     260       159955 :                         block.add_local_variable (this);
     261              :                 }
     262              : 
     263       159969 :                 active = true;
     264              : 
     265       159969 :                 return !error;
     266              :         }
     267              : }
        

Generated by: LCOV version 2.0-1