Line data Source code
1 : /* valareturnstatement.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 :
24 : /**
25 : * Represents a return statement in the source code.
26 : */
27 175532 : public class Vala.ReturnStatement : CodeNode, Statement {
28 : /**
29 : * The optional expression to return.
30 : */
31 : public Expression? return_expression {
32 3535073 : get { return _return_expression; }
33 185286 : private set {
34 185286 : _return_expression = value;
35 185286 : if (_return_expression != null) {
36 184962 : _return_expression.parent_node = this;
37 : }
38 : }
39 : }
40 :
41 172458 : private Expression _return_expression;
42 :
43 : /**
44 : * Creates a new return statement.
45 : *
46 : * @param return_expression the return expression
47 : * @param source_reference reference to source code
48 : * @return newly created return statement
49 : */
50 344916 : public ReturnStatement (Expression? return_expression = null, SourceReference? source_reference = null) {
51 172458 : this.source_reference = source_reference;
52 172458 : this.return_expression = return_expression;
53 : }
54 :
55 274757 : public override void accept (CodeVisitor visitor) {
56 274757 : visitor.visit_return_statement (this);
57 : }
58 :
59 274757 : public override void accept_children (CodeVisitor visitor) {
60 274757 : if (return_expression != null) {
61 274119 : return_expression.accept (visitor);
62 :
63 274119 : visitor.visit_end_full_expression (return_expression);
64 : }
65 : }
66 :
67 12828 : public override void replace_expression (Expression old_node, Expression new_node) {
68 12828 : if (return_expression == old_node) {
69 12828 : return_expression = new_node;
70 : }
71 : }
72 :
73 158458 : public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
74 158458 : if (return_expression != null) {
75 158123 : return_expression.get_error_types (collection, source_reference);
76 : }
77 : }
78 :
79 158428 : public override bool check (CodeContext context) {
80 158428 : if (checked) {
81 0 : return !error;
82 : }
83 :
84 158428 : checked = true;
85 :
86 158428 : if (context.analyzer.current_return_type == null) {
87 0 : error = true;
88 0 : Report.error (source_reference, "Return not allowed in this context");
89 0 : return false;
90 : }
91 :
92 158428 : if (return_expression == null) {
93 323 : if (!(context.analyzer.current_return_type is VoidType)) {
94 1 : error = true;
95 1 : Report.error (source_reference, "Return without value in non-void function");
96 : }
97 323 : return !error;
98 : }
99 :
100 158105 : if (context.analyzer.current_return_type is VoidType) {
101 1 : error = true;
102 1 : Report.error (source_reference, "Return with value in void function");
103 1 : return false;
104 : }
105 :
106 158104 : return_expression.target_type = context.analyzer.current_return_type.copy ();
107 :
108 158104 : if (!return_expression.check (context)) {
109 : // ignore inner error
110 3 : error = true;
111 3 : return false;
112 : }
113 :
114 158101 : if (return_expression.value_type == null) {
115 0 : error = true;
116 0 : Report.error (source_reference, "Invalid expression in return value");
117 0 : return false;
118 : }
119 :
120 158101 : if (!return_expression.value_type.compatible (context.analyzer.current_return_type)) {
121 2 : error = true;
122 2 : Report.error (source_reference, "Return: Cannot convert from `%s' to `%s'", return_expression.value_type.to_string (), context.analyzer.current_return_type.to_string ());
123 2 : return false;
124 : }
125 :
126 158099 : if (return_expression.value_type.is_disposable () &&
127 20613 : !context.analyzer.current_return_type.value_owned) {
128 1 : error = true;
129 1 : Report.error (source_reference, "Return value transfers ownership but method return type hasn't been declared to transfer ownership");
130 1 : return false;
131 : }
132 :
133 158098 : unowned LocalVariable? local = return_expression.symbol_reference as LocalVariable;
134 30221 : if (local != null && local.variable_type.is_disposable () &&
135 14585 : !context.analyzer.current_return_type.value_owned) {
136 1 : error = true;
137 1 : Report.error (source_reference, "Local variable with strong reference used as return value and method return type has not been declared to transfer ownership");
138 1 : return false;
139 : }
140 :
141 158097 : if (return_expression is NullLiteral
142 4522 : && !context.analyzer.current_return_type.nullable) {
143 11 : Report.warning (source_reference, "`null' incompatible with return type `%s'", context.analyzer.current_return_type.to_string ());
144 : }
145 :
146 158097 : return !error;
147 : }
148 :
149 4212 : public override void emit (CodeGenerator codegen) {
150 4212 : if (return_expression != null) {
151 3895 : return_expression.emit (codegen);
152 :
153 3895 : codegen.visit_end_full_expression (return_expression);
154 : }
155 :
156 4212 : codegen.visit_return_statement (this);
157 : }
158 :
159 327174 : public override void get_defined_variables (Collection<Variable> collection) {
160 327174 : if (return_expression != null) {
161 326232 : return_expression.get_defined_variables (collection);
162 : }
163 : }
164 :
165 109058 : public override void get_used_variables (Collection<Variable> collection) {
166 109058 : if (return_expression != null) {
167 108744 : return_expression.get_used_variables (collection);
168 : }
169 : }
170 : }
|