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 : }
|