1/* valaccodeattribute.vala
2 *
3 * Copyright (C) 2011  Luca Bruno
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 * 	Luca Bruno <lucabru@src.gnome.org>
21 */
22
23
24/**
25 * Cache for the CCode attribute
26 */
27public class Vala.CCodeAttribute : AttributeCache {
28	private weak CodeNode node;
29	private weak Symbol? sym;
30	private Attribute ccode;
31
32	public string name {
33		get {
34			if (_name == null) {
35				if (ccode != null) {
36					_name = ccode.get_string ("cname");
37				}
38				if (_name == null) {
39					_name = get_default_name ();
40				}
41			}
42			return _name;
43		}
44	}
45
46	public string const_name {
47		get {
48			if (_const_name == null) {
49				if (ccode != null) {
50					_const_name = ccode.get_string ("const_cname");
51				}
52				if (_const_name == null) {
53					_const_name = get_default_const_name ();
54				}
55			}
56			return _const_name;
57		}
58	}
59
60	public string type_name {
61		get {
62			if (_type_name == null) {
63				if (ccode != null) {
64					_type_name = ccode.get_string ("type_cname");
65				}
66				if (_type_name == null) {
67					if (sym is Class) {
68						_type_name = "%sClass".printf (get_ccode_name (sym));
69					} else if (sym is Interface) {
70						_type_name = "%sIface".printf (get_ccode_name (sym));
71					} else {
72						Report.error (sym.source_reference, "`CCode.type_cname' not supported");
73						_type_name = "";
74					}
75				}
76			}
77			return _type_name;
78		}
79	}
80
81	public string feature_test_macros {
82		get {
83			if (_feature_test_macros == null) {
84				if (ccode != null) {
85					_feature_test_macros = ccode.get_string ("feature_test_macro");
86				}
87				if (_feature_test_macros == null) {
88					_feature_test_macros = "";
89				}
90			}
91			return _feature_test_macros;
92		}
93	}
94
95	public string header_filenames {
96		get {
97			if (_header_filenames == null) {
98				if (ccode != null) {
99					_header_filenames = ccode.get_string ("cheader_filename");
100				}
101				if (_header_filenames == null) {
102					_header_filenames = get_default_header_filenames ();
103				}
104			}
105			return _header_filenames;
106		}
107	}
108
109	public string prefix {
110		get {
111			if (_prefix == null) {
112				if (ccode != null) {
113					_prefix = ccode.get_string ("cprefix");
114				}
115				if (_prefix == null) {
116					_prefix = get_default_prefix ();
117				}
118			}
119			return _prefix;
120		}
121	}
122
123	public string lower_case_prefix {
124		get {
125			if (_lower_case_prefix == null) {
126				if (ccode != null) {
127					_lower_case_prefix = ccode.get_string ("lower_case_cprefix");
128					if (_lower_case_prefix == null && (sym is ObjectTypeSymbol || sym is Struct)) {
129						_lower_case_prefix = ccode.get_string ("cprefix");
130					}
131				}
132				if (_lower_case_prefix == null) {
133					_lower_case_prefix = get_default_lower_case_prefix ();
134				}
135			}
136			return _lower_case_prefix;
137		}
138	}
139
140	public string lower_case_suffix {
141		get {
142			if (_lower_case_suffix == null) {
143				if (ccode != null) {
144					_lower_case_suffix = ccode.get_string ("lower_case_csuffix");
145				}
146				if (_lower_case_suffix == null) {
147					_lower_case_suffix = get_default_lower_case_suffix ();
148				}
149			}
150			return _lower_case_suffix;
151		}
152	}
153
154	public string ref_function {
155		get {
156			if (!ref_function_set) {
157				if (ccode != null) {
158					_ref_function = ccode.get_string ("ref_function");
159				}
160				if (_ref_function == null) {
161					_ref_function = get_default_ref_function ();
162				}
163				ref_function_set = true;
164			}
165			return _ref_function;
166		}
167	}
168
169	public bool ref_function_void {
170		get {
171			if (_ref_function_void == null) {
172				if (ccode != null && ccode.has_argument ("ref_function_void")) {
173					_ref_function_void = ccode.get_bool ("ref_function_void");
174				} else {
175					var cl = (Class) sym;
176					if (cl.base_class != null) {
177						_ref_function_void = get_ccode_ref_function_void (cl.base_class);
178					} else {
179						_ref_function_void = false;
180					}
181				}
182			}
183			return _ref_function_void;
184		}
185	}
186
187	public string unref_function {
188		get {
189			if (!unref_function_set) {
190				if (ccode != null) {
191					_unref_function = ccode.get_string ("unref_function");
192				}
193				if (_unref_function == null) {
194					_unref_function = get_default_unref_function ();
195				}
196				unref_function_set = true;
197			}
198			return _unref_function;
199		}
200	}
201
202	public string ref_sink_function {
203		get {
204			if (_ref_sink_function == null) {
205				if (ccode != null) {
206					_ref_sink_function = ccode.get_string ("ref_sink_function");
207				}
208				if (_ref_sink_function == null) {
209					_ref_sink_function = get_default_ref_sink_function ();
210				}
211			}
212			return _ref_sink_function;
213		}
214	}
215
216	public string copy_function {
217		get {
218			if (!copy_function_set) {
219				if (ccode != null) {
220					_copy_function = ccode.get_string ("copy_function");
221				}
222				if (_copy_function == null && sym is Struct) {
223					_copy_function = "%scopy".printf (lower_case_prefix);
224				}
225				copy_function_set = true;
226			}
227			return _copy_function;
228		}
229	}
230
231	public string destroy_function {
232		get {
233			if (!destroy_function_set) {
234				if (ccode != null) {
235					_destroy_function = ccode.get_string ("destroy_function");
236				}
237				if (_destroy_function == null && sym is Struct) {
238					_destroy_function = "%sdestroy".printf (lower_case_prefix);
239				}
240				destroy_function_set = true;
241			}
242			return _destroy_function;
243		}
244	}
245
246	public string dup_function {
247		get {
248			if (!dup_function_set) {
249				if (ccode != null) {
250					_dup_function = ccode.get_string ("dup_function");
251				}
252				if (_dup_function == null && !sym.external_package && sym is Struct) {
253					_dup_function = "%sdup".printf (lower_case_prefix);
254				}
255				dup_function_set = true;
256			}
257			return _dup_function;
258		}
259	}
260
261	public string free_function {
262		get {
263			if (!free_function_set) {
264				if (ccode != null) {
265					_free_function = ccode.get_string ("free_function");
266				}
267				if (_free_function == null) {
268					_free_function = get_default_free_function ();
269				}
270				free_function_set = true;
271			}
272			return _free_function;
273		}
274	}
275
276	public bool free_function_address_of {
277		get {
278			if (_free_function_address_of == null) {
279				if (ccode != null && ccode.has_argument ("free_function_address_of")) {
280					_free_function_address_of = ccode.get_bool ("free_function_address_of");
281				} else {
282					unowned Class cl = (Class) sym;
283					if (cl.base_class != null) {
284						_free_function_address_of = get_ccode_free_function_address_of (cl.base_class);
285					} else {
286						_free_function_address_of = false;
287					}
288				}
289			}
290			return _free_function_address_of;
291		}
292	}
293
294	public string ctype {
295		get {
296			if (!ctype_set) {
297				if (ccode != null) {
298					_ctype = ccode.get_string ("type");
299					if (_ctype == null) {
300						_ctype = ccode.get_string ("ctype");
301						if (_ctype != null) {
302							Report.deprecated (node.source_reference, "[CCode (ctype = \"...\")] is deprecated, use [CCode (type = \"...\")] instead.");
303						}
304					}
305				}
306				ctype_set = true;
307			}
308			return _ctype;
309		}
310	}
311
312	public string type_id {
313		get {
314			if (_type_id == null) {
315				if (ccode != null) {
316					_type_id = ccode.get_string ("type_id");
317				}
318				if (_type_id == null) {
319					_type_id = get_default_type_id ();
320				}
321			}
322			return _type_id;
323		}
324	}
325
326	public string marshaller_type_name {
327		get {
328			if (_marshaller_type_name == null) {
329				if (ccode != null) {
330					_marshaller_type_name = ccode.get_string ("marshaller_type_name");
331				}
332				if (_marshaller_type_name == null) {
333					_marshaller_type_name = get_default_marshaller_type_name ();
334				}
335			}
336			return _marshaller_type_name;
337		}
338	}
339
340	public string get_value_function {
341		get {
342			if (_get_value_function == null) {
343				if (ccode != null) {
344					_get_value_function = ccode.get_string ("get_value_function");
345				}
346				if (_get_value_function == null) {
347					_get_value_function = get_default_get_value_function ();
348				}
349			}
350			return _get_value_function;
351		}
352	}
353
354	public string set_value_function {
355		get {
356			if (_set_value_function == null) {
357				if (ccode != null) {
358					_set_value_function = ccode.get_string ("set_value_function");
359				}
360				if (_set_value_function == null) {
361					_set_value_function = get_default_set_value_function ();
362				}
363			}
364			return _set_value_function;
365		}
366	}
367
368	public string take_value_function {
369		get {
370			if (_take_value_function == null) {
371				if (ccode != null) {
372					_take_value_function = ccode.get_string ("take_value_function");
373				}
374				if (_take_value_function == null) {
375					_take_value_function = get_default_take_value_function ();
376				}
377			}
378			return _take_value_function;
379		}
380	}
381
382	public string param_spec_function {
383		get {
384			if (_param_spec_function == null) {
385				if (ccode != null) {
386					_param_spec_function = ccode.get_string ("param_spec_function");
387				}
388				if (_param_spec_function == null) {
389					_param_spec_function = get_default_param_spec_function ();
390				}
391			}
392			return _param_spec_function;
393		}
394	}
395
396	public string default_value {
397		get {
398			if (_default_value == null) {
399				if (ccode != null) {
400					_default_value = ccode.get_string ("default_value");
401				}
402				if (_default_value == null) {
403					_default_value = get_default_default_value ();
404				}
405			}
406			return _default_value;
407		}
408	}
409
410	public string default_value_on_error {
411		get {
412			if (_default_value_on_error == null) {
413				if (ccode != null) {
414					_default_value_on_error = ccode.get_string ("default_value_on_error");
415				}
416				if (_default_value_on_error == null) {
417					_default_value_on_error = default_value;
418				}
419			}
420			return _default_value_on_error;
421		}
422	}
423
424	public double pos {
425		get {
426			if (_pos == null) {
427				if (ccode != null && ccode.has_argument ("pos")) {
428					_pos = ccode.get_double ("pos");
429				} else {
430					unowned Parameter param = (Parameter) node;
431					unowned Callable? callable = param.parent_symbol as Callable;
432					unowned Method? method = param.parent_symbol as Method;
433					if (method != null && method.coroutine) {
434						int index = method.get_async_begin_parameters ().index_of (param);
435						if (index < 0) {
436							index = method.get_async_end_parameters ().index_of (param);
437						}
438						if (index < 0) {
439							Report.error (param.source_reference, "internal: Parameter `%s' not found in `%s'".printf (param.name, method.get_full_name ()));
440						}
441						_pos = index + 1.0;
442					} else if (callable != null) {
443						_pos = callable.get_parameters ().index_of (param) + 1.0;
444					} else {
445						_pos = 0.0;
446					}
447				}
448			}
449			return _pos;
450		}
451	}
452
453	public string real_name {
454		get {
455			if (_real_name == null) {
456				if (ccode != null && sym is CreationMethod) {
457					_real_name = ccode.get_string ("construct_function");
458				}
459				if (_real_name == null) {
460					_real_name = get_default_real_name ();
461				}
462			}
463			return _real_name;
464		}
465	}
466
467	public string vfunc_name {
468		get {
469			if (_vfunc_name == null) {
470				if (ccode != null) {
471					_vfunc_name = ccode.get_string ("vfunc_name");
472				}
473				if (_vfunc_name == null) {
474					unowned Method? m = node as Method;
475					if (m != null && m.signal_reference != null) {
476						_vfunc_name = get_ccode_lower_case_name (m.signal_reference);
477					} else {
478						_vfunc_name = sym.name;
479					}
480				}
481			}
482			return _vfunc_name;
483		}
484	}
485
486	public string finish_name {
487		get {
488			if (_finish_name == null) {
489				if (ccode != null) {
490					_finish_name = ccode.get_string ("finish_name");
491					if (_finish_name == null) {
492						_finish_name = ccode.get_string ("finish_function");
493						if (_finish_name != null) {
494							Report.deprecated (node.source_reference, "[CCode (finish_function = \"...\")] is deprecated, use [CCode (finish_name = \"...\")] instead.");
495						}
496					}
497				}
498				if (_finish_name == null) {
499					_finish_name = get_finish_name_for_basename (name);
500				}
501			}
502			return _finish_name;
503		}
504	}
505
506	public string finish_vfunc_name {
507		get {
508			if (_finish_vfunc_name == null) {
509				if (ccode != null) {
510					_finish_vfunc_name = ccode.get_string ("finish_vfunc_name");
511				}
512				if (_finish_vfunc_name == null) {
513					_finish_vfunc_name = get_finish_name_for_basename (vfunc_name);
514				}
515			}
516			return _finish_vfunc_name;
517		}
518	}
519
520	public string finish_real_name {
521		get {
522			if (_finish_real_name == null) {
523				unowned Method? m = node as Method;
524				if (m != null && !(m is CreationMethod) && !(m.is_abstract || m.is_virtual)) {
525					_finish_real_name = finish_name;
526				} else {
527					_finish_real_name = get_finish_name_for_basename (real_name);
528				}
529			}
530			return _finish_real_name;
531		}
532	}
533
534	public bool finish_instance {
535		get {
536			if (_finish_instance == null) {
537				unowned Method? m = node as Method;
538				bool is_creation_method = m is CreationMethod;
539				if (ccode == null || m == null || m.is_abstract || m.is_virtual) {
540					_finish_instance = !is_creation_method;
541				} else {
542					_finish_instance = ccode.get_bool ("finish_instance", !is_creation_method);
543				}
544			}
545			return _finish_instance;
546		}
547	}
548
549	public bool delegate_target {
550		get {
551			if (_delegate_target == null) {
552				if (ccode != null) {
553					_delegate_target = ccode.get_bool ("delegate_target", get_default_delegate_target ());
554				} else {
555					_delegate_target = get_default_delegate_target ();
556				}
557			}
558			return _delegate_target;
559		}
560	}
561
562	public string delegate_target_name {
563		get {
564			if (_delegate_target_name == null) {
565				if (ccode != null) {
566					_delegate_target_name = ccode.get_string ("delegate_target_cname");
567				}
568				if (_delegate_target_name == null) {
569					_delegate_target_name = "%s_target".printf (name);
570				}
571			}
572			return _delegate_target_name;
573		}
574	}
575
576	public string delegate_target_destroy_notify_name {
577		get {
578			if (_delegate_target_destroy_notify_name == null) {
579				if (ccode != null) {
580					_delegate_target_destroy_notify_name = ccode.get_string ("destroy_notify_cname");
581				}
582				if (_delegate_target_destroy_notify_name == null) {
583					_delegate_target_destroy_notify_name = "%s_destroy_notify".printf (delegate_target_name);
584				}
585			}
586			return _delegate_target_destroy_notify_name;
587		}
588	}
589
590	public bool array_length {
591		get {
592			if (_array_length == null) {
593				if (node.get_attribute ("NoArrayLength") != null) {
594					Report.deprecated (node.source_reference, "[NoArrayLength] is deprecated, use [CCode (array_length = false)] instead.");
595					_array_length = false;
596				} else if (ccode != null && ccode.has_argument ("array_length")) {
597					_array_length = ccode.get_bool ("array_length");
598				} else {
599					_array_length = get_default_array_length ();
600				}
601			}
602			return _array_length;
603		}
604	}
605
606	public bool array_null_terminated {
607		get {
608			if (_array_null_terminated == null) {
609				// If arrays claim to have an array-length and also are null-terminated then rely on the given length
610				if (ccode != null && ccode.has_argument ("array_length") && ccode.get_bool ("array_length")) {
611					_array_null_terminated = false;
612				} else if (ccode != null && ccode.has_argument ("array_null_terminated")) {
613					_array_null_terminated = ccode.get_bool ("array_null_terminated");
614				} else {
615					_array_null_terminated = get_default_array_null_terminated ();
616				}
617			}
618			return _array_null_terminated;
619		}
620	}
621
622	public string array_length_type {
623		get {
624			if (_array_length_type == null) {
625				if (ccode != null && ccode.has_argument ("array_length_type")) {
626					_array_length_type = ccode.get_string ("array_length_type");
627				} else {
628					_array_length_type = get_default_array_length_type ();
629				}
630			}
631			return _array_length_type;
632		}
633	}
634
635	public string sentinel {
636		get {
637			if (_sentinel == null) {
638				if (ccode != null) {
639					_sentinel = ccode.get_string ("sentinel", "NULL");
640				} else {
641					_sentinel = "NULL";
642				}
643			}
644			return _sentinel;
645		}
646	}
647
648	public string? array_length_name { get; private set; }
649	public string? array_length_expr { get; private set; }
650
651	private string _name;
652	private string _const_name;
653	private string _type_name;
654	private string _feature_test_macros;
655	private string _header_filenames;
656	private string _prefix;
657	private string _lower_case_prefix;
658	private string _lower_case_suffix;
659	private string? _ref_function;
660	private bool ref_function_set;
661	private bool? _ref_function_void;
662	private string? _unref_function;
663	private bool unref_function_set;
664	private string _ref_sink_function;
665	private string? _copy_function;
666	private bool copy_function_set;
667	private string? _destroy_function;
668	private bool destroy_function_set;
669	private string? _dup_function;
670	private bool dup_function_set;
671	private string? _free_function;
672	private bool free_function_set;
673	private bool? _free_function_address_of;
674	private string _type_id;
675	private string _marshaller_type_name;
676	private string _get_value_function;
677	private string _set_value_function;
678	private string _take_value_function;
679	private string _param_spec_function;
680	private string _default_value;
681	private string _default_value_on_error;
682	private double? _pos;
683	private string _vfunc_name;
684	private string _finish_name;
685	private string _finish_vfunc_name;
686	private string _finish_real_name;
687	private bool? _finish_instance;
688	private string _real_name;
689	private bool? _delegate_target;
690	private string _delegate_target_name;
691	private string _delegate_target_destroy_notify_name;
692	private string _ctype;
693	private bool ctype_set = false;
694	private bool? _array_length;
695	private string _array_length_type;
696	private bool? _array_null_terminated;
697	private string _sentinel;
698
699	private static int dynamic_method_id;
700
701	public CCodeAttribute (CodeNode node) {
702		this.node = node;
703		this.sym = node as Symbol;
704
705		ccode = node.get_attribute ("CCode");
706		if (ccode != null) {
707			array_length_name = ccode.get_string ("array_length_cname");
708			array_length_expr = ccode.get_string ("array_length_cexpr");
709		}
710	}
711
712	private string get_default_name () {
713		if (sym != null) {
714			if (sym is Constant && !(sym is EnumValue)) {
715				if (sym.parent_symbol is Block) {
716					// local constant
717					return sym.name;
718				}
719				return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol).ascii_up (), sym.name);
720			} else if (sym is Field) {
721				var cname = sym.name;
722				if (((Field) sym).binding == MemberBinding.STATIC) {
723					cname = "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name);
724				}
725				if (cname[0].isdigit ()) {
726					Report.error (node.source_reference, "Field name starts with a digit. Use the `cname' attribute to provide a valid C name if intended");
727					return "";
728				}
729				return cname;
730			} else if (sym is CreationMethod) {
731				unowned CreationMethod m = (CreationMethod) sym;
732				string infix;
733				if (m.parent_symbol is Struct) {
734					infix = "init";
735				} else {
736					infix = "new";
737				}
738				if (m.name == ".new") {
739					return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix);
740				} else {
741					return "%s%s_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix, m.name);
742				}
743			} else if (sym is DynamicMethod) {
744				return "_dynamic_%s%d".printf (sym.name, dynamic_method_id++);
745			} else if (sym is Method) {
746				unowned Method m = (Method) sym;
747				if (m.is_async_callback) {
748					return "%s_co".printf (get_ccode_real_name ((Method) m.parent_symbol));
749				}
750				if (m.signal_reference != null) {
751					return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), get_ccode_lower_case_name (m.signal_reference));
752				}
753				if (sym.name == "main" && sym.parent_symbol.name == null) {
754					// avoid conflict with generated main function
755					return "_vala_main";
756				} else if (sym.name.has_prefix ("_")) {
757					return "_%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name.substring (1));
758				} else {
759					return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name);
760				}
761			} else if (sym is Property) {
762				return sym.name.replace ("_", "-");
763			} else if (sym is PropertyAccessor) {
764				unowned PropertyAccessor acc = (PropertyAccessor) sym;
765				var t = (TypeSymbol) acc.prop.parent_symbol;
766
767				if (acc.readable) {
768					return "%sget_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name);
769				} else {
770					return "%sset_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name);
771				}
772			} else if (sym is Signal) {
773				return Symbol.camel_case_to_lower_case (sym.name).replace ("_", "-");;
774			} else if (sym is LocalVariable) {
775				unowned string name = sym.name;
776				if (CCodeBaseModule.reserved_identifiers.contains (name)) {
777					return "_%s_".printf (name);
778				} else {
779					return name;
780				}
781			} else if (sym is Parameter) {
782				unowned Parameter param = (Parameter) sym;
783				if (param.ellipsis) {
784					return "...";
785				}
786				unowned string name = sym.name;
787				if (CCodeBaseModule.reserved_identifiers.contains (name)) {
788					return "_%s_".printf (name);
789				} else {
790					return name;
791				}
792			} else {
793				return "%s%s".printf (get_ccode_prefix (sym.parent_symbol), sym.name);
794			}
795		} else if (node is ObjectType) {
796			var type = (ObjectType) node;
797
798			string cname;
799			if (!type.value_owned) {
800				cname = get_ccode_const_name (type.type_symbol);
801			} else {
802				cname = get_ccode_name (type.type_symbol);
803			}
804			return "%s*".printf (cname);
805		} else if (node is ArrayType) {
806			var type = (ArrayType) node;
807			var cname = get_ccode_name (type.element_type);
808			if (type.inline_allocated) {
809				return cname;
810			} else {
811				return "%s*".printf (cname);
812			}
813		} else if (node is DelegateType) {
814			var type = (DelegateType) node;
815			return get_ccode_name (type.delegate_symbol);
816		} else if (node is ErrorType) {
817			return "GError*";
818		} else if (node is GenericType) {
819			var type = (GenericType) node;
820			if (type.value_owned) {
821				if (CodeContext.get ().profile == Profile.GOBJECT) {
822					return "gpointer";
823				} else {
824					return "void *";
825				}
826			} else {
827				if (CodeContext.get ().profile == Profile.GOBJECT) {
828					return "gconstpointer";
829				} else {
830					return "const void *";
831				}
832			}
833		} else if (node is MethodType) {
834			if (CodeContext.get ().profile == Profile.GOBJECT) {
835				return "gpointer";
836			} else {
837				return "void *";
838			}
839		} else if (node is NullType) {
840			if (CodeContext.get ().profile == Profile.GOBJECT) {
841				return "gpointer";
842			} else {
843				return "void *";
844			}
845		} else if (node is PointerType) {
846			var type = (PointerType) node;
847			if (type.base_type.type_symbol != null && type.base_type.type_symbol.is_reference_type ()) {
848				return get_ccode_name (type.base_type);
849			} else {
850				return "%s*".printf (get_ccode_name (type.base_type));
851			}
852		} else if (node is VoidType) {
853			return "void";
854		} else if (node is ClassType) {
855			var type = (ClassType) node;
856			return "%s*".printf (get_ccode_type_name (type.class_symbol));
857		} else if (node is InterfaceType) {
858			var type = (InterfaceType) node;
859			return "%s*".printf (get_ccode_type_name (type.interface_symbol));
860		} else if (node is ValueType) {
861			var type = (ValueType) node;
862			var cname = get_ccode_name (type.type_symbol);
863			if (type.nullable) {
864				return "%s*".printf (cname);
865			} else {
866				return cname;
867			}
868		} else if (node is CType) {
869			return ((CType) node).ctype_name;
870		} else {
871			Report.error (node.source_reference, "Unresolved type reference");
872			return "";
873		}
874	}
875
876	private string get_default_header_filenames () {
877		if (sym is DynamicProperty || sym is DynamicMethod) {
878			return "";
879		}
880		if (sym.parent_symbol != null && !sym.is_extern) {
881			var parent_headers = get_ccode_header_filenames (sym.parent_symbol);
882			if (parent_headers.length > 0) {
883				return parent_headers;
884			}
885		}
886		if (sym.source_reference != null && !sym.external_package && !sym.is_extern) {
887			// don't add default include directives for VAPI files
888			return sym.source_reference.file.get_cinclude_filename ();
889		}
890		return "";
891	}
892
893	private string get_default_prefix () {
894		if (sym is ObjectTypeSymbol) {
895			return name;
896		} else if (sym is Enum || sym is ErrorDomain) {
897			return "%s_".printf (get_ccode_upper_case_name (sym));
898		} else if (sym is Namespace) {
899			if (sym.name != null) {
900				var parent_prefix = "";
901				if (sym.parent_symbol != null) {
902					parent_prefix = get_ccode_prefix (sym.parent_symbol);
903				}
904				return "%s%s".printf (parent_prefix, sym.name);
905			} else {
906				return "";
907			}
908		} else if (sym.name != null) {
909			return sym.name;
910		}
911		return "";
912	}
913
914	private string get_default_lower_case_prefix () {
915		if (sym is Namespace) {
916			if (sym.name == null) {
917				return "";
918			} else {
919				return "%s%s_".printf (get_ccode_lower_case_prefix (sym.parent_symbol), Symbol.camel_case_to_lower_case (sym.name));
920			}
921		} else if (sym is Method) {
922			// for lambda expressions
923			return "";
924		} else {
925			return "%s_".printf (get_ccode_lower_case_name (sym));
926		}
927	}
928
929	private string get_default_lower_case_suffix () {
930		if (sym is ObjectTypeSymbol) {
931			var csuffix = Symbol.camel_case_to_lower_case (sym.name);
932
933			// FIXME Code duplication with GirParser.Node.get_default_lower_case_suffix()
934			// remove underscores in some cases to avoid conflicts of type macros
935			if (csuffix.has_prefix ("type_")) {
936				csuffix = "type" + csuffix.substring ("type_".length);
937			} else if (csuffix.has_prefix ("is_")) {
938				csuffix = "is" + csuffix.substring ("is_".length);
939			}
940			if (csuffix.has_suffix ("_class")) {
941				csuffix = csuffix.substring (0, csuffix.length - "_class".length) + "class";
942			}
943			return csuffix;
944		} else if (sym is Signal) {
945			return get_ccode_attribute (sym).name.replace ("-", "_");
946		} else if (sym.name != null) {
947			return Symbol.camel_case_to_lower_case (sym.name);
948		}
949		return "";
950	}
951
952	private string? get_default_ref_function () {
953		if (sym is Class) {
954			unowned Class cl = (Class) sym;
955			if (cl.is_fundamental ()) {
956				return "%sref".printf (lower_case_prefix);
957			} else if (cl.base_class != null) {
958				return get_ccode_ref_function (cl.base_class);
959			}
960		} else if (sym is Interface) {
961			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
962				string ref_func = get_ccode_ref_function ((ObjectTypeSymbol) prereq.type_symbol);
963				if (ref_func != null) {
964					return ref_func;
965				}
966			}
967		}
968		return null;
969	}
970
971	private string? get_default_unref_function () {
972		if (sym is Class) {
973			unowned Class cl = (Class) sym;
974			if (cl.is_fundamental ()) {
975				return "%sunref".printf (lower_case_prefix);
976			} else if (cl.base_class != null) {
977				return get_ccode_unref_function (cl.base_class);
978			}
979		} else if (sym is Interface) {
980			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
981				string unref_func = get_ccode_unref_function ((ObjectTypeSymbol) prereq.type_symbol);
982				if (unref_func != null) {
983					return unref_func;
984				}
985			}
986		}
987		return null;
988	}
989
990	private string get_default_ref_sink_function () {
991		if (sym is Class) {
992			unowned Class? base_class = ((Class) sym).base_class;
993			if (base_class != null) {
994				return get_ccode_ref_sink_function (base_class);
995			}
996		} else if (sym is Interface) {
997			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
998				string ref_sink_func = get_ccode_ref_sink_function ((ObjectTypeSymbol) prereq.type_symbol);
999				if (ref_sink_func != "") {
1000					return ref_sink_func;
1001				}
1002			}
1003		}
1004		return "";
1005	}
1006
1007	private string? get_default_free_function () {
1008		if (sym is Class) {
1009			unowned Class cl = (Class) sym;
1010			if (cl.base_class != null) {
1011				return get_ccode_free_function (cl.base_class);
1012			}
1013			return "%sfree".printf (lower_case_prefix);
1014		} else if (sym is Struct) {
1015			if (!sym.external_package) {
1016				return "%sfree".printf (lower_case_prefix);
1017			}
1018		}
1019		return null;
1020	}
1021
1022	private string get_default_type_id () {
1023		if (sym != null) {
1024			if (sym is Class && !((Class) sym).is_compact || sym is Interface) {
1025				return get_ccode_upper_case_name (sym, "TYPE_");
1026			} else if (sym is Struct) {
1027				unowned Struct st = (Struct) sym;
1028				unowned Struct? base_struct = st.base_struct;
1029				if (!get_ccode_has_type_id (st) || (base_struct != null && base_struct.is_simple_type ())) {
1030					if (base_struct != null) {
1031						return get_ccode_type_id (base_struct);
1032					}
1033					if (!st.is_simple_type ()) {
1034						return "G_TYPE_POINTER";
1035					}
1036				} else {
1037					return get_ccode_upper_case_name (st, "TYPE_");
1038				}
1039			} else if (sym is Enum) {
1040				unowned Enum en = (Enum) sym;
1041				if (get_ccode_has_type_id (en)) {
1042					return get_ccode_upper_case_name (en, "TYPE_");
1043				} else {
1044					return en.is_flags ? "G_TYPE_UINT" : "G_TYPE_INT";
1045				}
1046			} else {
1047				return "G_TYPE_POINTER";
1048			}
1049		} else if (node is ArrayType && ((ArrayType) node).element_type.type_symbol.get_full_name () == "string") {
1050			return "G_TYPE_STRV";
1051		} else if (node is PointerType || node is DelegateType) {
1052			return "G_TYPE_POINTER";
1053		} else if (node is ErrorType) {
1054			return "G_TYPE_ERROR";
1055		} else if (node is VoidType) {
1056			return "G_TYPE_NONE";
1057		} else {
1058			var type = (DataType) node;
1059			if (type.type_symbol != null) {
1060				return get_ccode_type_id (type.type_symbol);
1061			}
1062		}
1063		return "";
1064	}
1065
1066	private string get_default_marshaller_type_name () {
1067		if (sym != null) {
1068			if (sym is Class) {
1069				unowned Class cl = (Class) sym;
1070				if (cl.base_class != null) {
1071					return get_ccode_marshaller_type_name (cl.base_class);
1072				} else if (!cl.is_compact) {
1073					return get_ccode_upper_case_name (cl);
1074				} else if (type_id == "G_TYPE_POINTER") {
1075					return "POINTER";
1076				} else {
1077					return "BOXED";
1078				}
1079			} else if (sym is Enum) {
1080				unowned Enum en = (Enum) sym;
1081				if (get_ccode_has_type_id (en)) {
1082					if (en.is_flags) {
1083						return "FLAGS";
1084					} else {
1085						return "ENUM";
1086					}
1087				} else {
1088					if (en.is_flags) {
1089						return "UINT";
1090					} else {
1091						return "INT";
1092					}
1093				}
1094			} else if (sym is Interface) {
1095				foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1096					var type_name = get_ccode_marshaller_type_name (prereq.type_symbol);
1097					if (type_name != "") {
1098						return type_name;
1099					}
1100				}
1101				return "POINTER";
1102			} else if (sym is Struct) {
1103				unowned Struct st = (Struct) sym;
1104				unowned Struct? base_st = st.base_struct;
1105				while (base_st != null) {
1106					if (get_ccode_has_type_id (base_st)) {
1107						return get_ccode_marshaller_type_name (base_st);
1108					} else {
1109						base_st = base_st.base_struct;
1110					}
1111				}
1112				if (st.is_simple_type ()) {
1113					Report.error (st.source_reference, "The type `%s' doesn't declare a marshaller type name".printf (st.get_full_name ()));
1114				} else if (get_ccode_has_type_id (st)) {
1115					return "BOXED";
1116				} else {
1117					return "POINTER";
1118				}
1119			} else if (sym is Parameter) {
1120				unowned Parameter param = (Parameter) sym;
1121				if (param.direction != ParameterDirection.IN) {
1122					return "POINTER";
1123				} else {
1124					return get_ccode_marshaller_type_name (param.variable_type);
1125				}
1126			} else {
1127				return "POINTER";
1128			}
1129		} else if (node is ValueType && ((ValueType) node).nullable) {
1130			return "POINTER";
1131		} else if (node is PointerType || node is GenericType) {
1132			return "POINTER";
1133		} else if (node is ErrorType) {
1134			return "POINTER";
1135		} else if (node is ArrayType) {
1136			unowned ArrayType array_type = (ArrayType) node;
1137			if (array_type.element_type.type_symbol.get_full_name () == "string") {
1138				return "BOXED,%s".printf (get_ccode_marshaller_type_name (array_type.length_type.type_symbol));
1139			} else {
1140				var ret = "POINTER";
1141				var length_marshaller_type_name = get_ccode_marshaller_type_name (array_type.length_type.type_symbol);
1142				for (var i = 0; i < array_type.rank; i++) {
1143					ret = "%s,%s".printf (ret, length_marshaller_type_name);
1144				}
1145				return ret;
1146			}
1147		} else if (node is DelegateType) {
1148			unowned DelegateType delegate_type = (DelegateType) node;
1149			var ret = "POINTER";
1150			if (delegate_type.delegate_symbol.has_target) {
1151				ret = "%s,POINTER".printf (ret);
1152				if (delegate_type.is_disposable ()) {
1153					ret = "%s,POINTER".printf (ret);
1154				}
1155			}
1156			return ret;
1157		} else if (node is VoidType) {
1158			return "VOID";
1159		} else {
1160			return get_ccode_marshaller_type_name (((DataType) node).type_symbol);
1161		}
1162		return "";
1163	}
1164
1165	private string get_default_get_value_function () {
1166		if (sym is Class) {
1167			unowned Class cl = (Class) sym;
1168			if (cl.is_fundamental ()) {
1169				return get_ccode_lower_case_name (cl, "value_get_");
1170			} else if (cl.base_class != null) {
1171				return get_ccode_get_value_function (cl.base_class);
1172			} else if (type_id == "G_TYPE_POINTER") {
1173				return "g_value_get_pointer";
1174			} else {
1175				return "g_value_get_boxed";
1176			}
1177		} else if (sym is Enum) {
1178			unowned Enum en = (Enum) sym;
1179			if (get_ccode_has_type_id (en)) {
1180				if (en.is_flags) {
1181					return "g_value_get_flags";
1182				} else {
1183					return "g_value_get_enum";
1184				}
1185			} else {
1186				if (en.is_flags) {
1187					return "g_value_get_uint";
1188				} else {
1189					return "g_value_get_int";
1190				}
1191			}
1192		} else if (sym is Interface) {
1193			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1194				var type_name = get_ccode_get_value_function (prereq.type_symbol);
1195				if (type_name != "") {
1196					return type_name;
1197				}
1198			}
1199			return "g_value_get_pointer";
1200		} else if (sym is Struct) {
1201			unowned Struct st = (Struct) sym;
1202			unowned Struct? base_st = st.base_struct;
1203			while (base_st != null) {
1204				if (get_ccode_has_type_id (base_st)) {
1205					return get_ccode_get_value_function (base_st);
1206				} else {
1207					base_st = base_st.base_struct;
1208				}
1209			}
1210			if (st.is_simple_type ()) {
1211				Report.error (st.source_reference, "The type `%s' doesn't declare a GValue get function".printf (st.get_full_name ()));
1212			} else if (get_ccode_has_type_id (st)) {
1213				return "g_value_get_boxed";
1214			} else {
1215				return "g_value_get_pointer";
1216			}
1217		} else {
1218			return "g_value_get_pointer";
1219		}
1220		return "";
1221	}
1222
1223	private string get_default_set_value_function () {
1224		if (sym is Class) {
1225			unowned Class cl = (Class) sym;
1226			if (cl.is_fundamental ()) {
1227				return get_ccode_lower_case_name (cl, "value_set_");
1228			} else if (cl.base_class != null) {
1229				return get_ccode_set_value_function (cl.base_class);
1230			} else if (type_id == "G_TYPE_POINTER") {
1231				return "g_value_set_pointer";
1232			} else {
1233				return "g_value_set_boxed";
1234			}
1235		} else if (sym is Enum) {
1236			unowned Enum en = (Enum) sym;
1237			if (get_ccode_has_type_id (en)) {
1238				if (en.is_flags) {
1239					return "g_value_set_flags";
1240				} else {
1241					return "g_value_set_enum";
1242				}
1243			} else {
1244				if (en.is_flags) {
1245					return "g_value_set_uint";
1246				} else {
1247					return "g_value_set_int";
1248				}
1249			}
1250		} else if (sym is Interface) {
1251			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1252				var type_name = get_ccode_set_value_function (prereq.type_symbol);
1253				if (type_name != "") {
1254					return type_name;
1255				}
1256			}
1257			return "g_value_set_pointer";
1258		} else if (sym is Struct) {
1259			unowned Struct st = (Struct) sym;
1260			unowned Struct? base_st = st.base_struct;
1261			while (base_st != null) {
1262				if (get_ccode_has_type_id (base_st)) {
1263					return get_ccode_set_value_function (base_st);
1264				} else {
1265					base_st = base_st.base_struct;
1266				}
1267			}
1268			if (st.is_simple_type ()) {
1269				Report.error (st.source_reference, "The type `%s' doesn't declare a GValue set function".printf (st.get_full_name ()));
1270			} else if (get_ccode_has_type_id (st)) {
1271				return "g_value_set_boxed";
1272			} else {
1273				return "g_value_set_pointer";
1274			}
1275		} else {
1276			return "g_value_set_pointer";
1277		}
1278		return "";
1279	}
1280
1281	private string get_default_take_value_function () {
1282		if (sym is Class) {
1283			unowned Class cl = (Class) sym;
1284			if (cl.is_fundamental ()) {
1285				return get_ccode_lower_case_name (cl, "value_take_");
1286			} else if (cl.base_class != null) {
1287				return get_ccode_take_value_function (cl.base_class);
1288			} else if (type_id == "G_TYPE_POINTER") {
1289				return "g_value_set_pointer";
1290			} else {
1291				return "g_value_take_boxed";
1292			}
1293		} else if (sym is Enum) {
1294			unowned Enum en = (Enum) sym;
1295			if (get_ccode_has_type_id (en)) {
1296				if (en.is_flags) {
1297					return "g_value_take_flags";
1298				} else {
1299					return "g_value_take_enum";
1300				}
1301			} else {
1302				if (en.is_flags) {
1303					return "g_value_take_uint";
1304				} else {
1305					return "g_value_take_int";
1306				}
1307			}
1308		} else if (sym is Interface) {
1309			foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1310				var func = get_ccode_take_value_function (prereq.type_symbol);
1311				if (func != "") {
1312					return func;
1313				}
1314			}
1315			return "g_value_set_pointer";
1316		} else if (sym is Struct) {
1317			unowned Struct st = (Struct) sym;
1318			unowned Struct? base_st = st.base_struct;
1319			while (base_st != null) {
1320				if (get_ccode_has_type_id (base_st)) {
1321					return get_ccode_take_value_function (base_st);
1322				} else {
1323					base_st = base_st.base_struct;
1324				}
1325			}
1326			if (st.is_simple_type ()) {
1327				Report.error (st.source_reference, "The type `%s' doesn't declare a GValue take function".printf (st.get_full_name ()));
1328			} else if (get_ccode_has_type_id (st)) {
1329				return "g_value_take_boxed";
1330			} else {
1331				return "g_value_set_pointer";
1332			}
1333		} else {
1334			return "g_value_set_pointer";
1335		}
1336		return "";
1337	}
1338
1339	private string get_default_param_spec_function () {
1340		if (node is Symbol) {
1341			if (sym is Class) {
1342				unowned Class cl = (Class) sym;
1343				if (cl.is_fundamental ()) {
1344					return get_ccode_lower_case_name (cl, "param_spec_");
1345				} else if (cl.base_class != null) {
1346					return get_ccode_param_spec_function (cl.base_class);
1347				} else if (type_id == "G_TYPE_POINTER") {
1348					return "g_param_spec_pointer";
1349				} else {
1350					return "g_param_spec_boxed";
1351				}
1352			} else if (sym is Interface) {
1353				foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1354					var func = get_ccode_param_spec_function (prereq.type_symbol);
1355					if (func != "") {
1356						return func;
1357					}
1358				}
1359				return "g_param_spec_pointer";
1360			} else if (sym is Enum) {
1361				unowned Enum e = (Enum) sym;
1362				if (get_ccode_has_type_id (e)) {
1363					if (e.is_flags) {
1364						return "g_param_spec_flags";
1365					} else {
1366						return "g_param_spec_enum";
1367					}
1368				} else {
1369					if (e.is_flags) {
1370						return "g_param_spec_uint";
1371					} else {
1372						return "g_param_spec_int";
1373					}
1374				}
1375			} else if (sym is Struct) {
1376				var type_id = get_ccode_type_id (sym);
1377				if (type_id == "G_TYPE_INT") {
1378					return "g_param_spec_int";
1379				} else if (type_id == "G_TYPE_UINT") {
1380					return "g_param_spec_uint";
1381				} else if (type_id == "G_TYPE_INT64") {
1382					return "g_param_spec_int64";
1383				} else if (type_id == "G_TYPE_UINT64") {
1384					return "g_param_spec_uint64";
1385				} else if (type_id == "G_TYPE_LONG") {
1386					return "g_param_spec_long";
1387				} else if (type_id == "G_TYPE_ULONG") {
1388					return "g_param_spec_ulong";
1389				} else if (type_id == "G_TYPE_BOOLEAN") {
1390					return "g_param_spec_boolean";
1391				} else if (type_id == "G_TYPE_CHAR") {
1392					return "g_param_spec_char";
1393				} else if (type_id == "G_TYPE_UCHAR") {
1394					return "g_param_spec_uchar";
1395				}else if (type_id == "G_TYPE_FLOAT") {
1396					return "g_param_spec_float";
1397				} else if (type_id == "G_TYPE_DOUBLE") {
1398					return "g_param_spec_double";
1399				} else if (type_id == "G_TYPE_GTYPE") {
1400					return "g_param_spec_gtype";
1401				} else {
1402					return "g_param_spec_boxed";
1403				}
1404			}
1405		} else if (node is ArrayType && ((ArrayType)node).element_type.type_symbol == CodeContext.get().analyzer.string_type.type_symbol) {
1406			return "g_param_spec_boxed";
1407		} else if (node is DataType && ((DataType) node).type_symbol != null) {
1408			return get_ccode_param_spec_function (((DataType) node).type_symbol);
1409		}
1410
1411		return "g_param_spec_pointer";
1412	}
1413
1414	private string get_default_default_value () {
1415		if (sym is Enum) {
1416			unowned Enum en = (Enum) sym;
1417			if (en.is_flags) {
1418				return "0U";
1419			} else {
1420				return "0";
1421			}
1422		} else if (sym is Struct) {
1423			unowned Struct st = (Struct) sym;
1424			unowned Struct? base_st = st.base_struct;
1425			if (base_st != null) {
1426				return get_ccode_default_value (base_st);
1427			}
1428		}
1429		return "";
1430	}
1431
1432	private string get_finish_name_for_basename (string basename) {
1433		string result = basename;
1434		if (result.has_suffix ("_async")) {
1435			result = result.substring (0, result.length - "_async".length);
1436		}
1437		return "%s_finish".printf (result);
1438	}
1439
1440	private string get_default_real_name () {
1441		if (sym is CreationMethod) {
1442			unowned CreationMethod m = (CreationMethod) sym;
1443			unowned Class? parent = m.parent_symbol as Class;
1444
1445			if (parent == null || parent.is_compact) {
1446				return name;
1447			}
1448
1449			string infix = "construct";
1450
1451			if (m.name == ".new") {
1452				return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
1453			} else {
1454				return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
1455			}
1456		} else if (sym is Method) {
1457			unowned Method m = (Method) sym;
1458			if (m.base_method != null || m.base_interface_method != null) {
1459				string m_name;
1460				if (m.signal_reference != null) {
1461					m_name = get_ccode_lower_case_name (m.signal_reference);
1462				} else {
1463					m_name = m.name;
1464				}
1465				if (m.base_interface_type != null) {
1466					return "%sreal_%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol),
1467												 get_ccode_lower_case_prefix (m.base_interface_type.type_symbol),
1468												 m_name);
1469				} else {
1470					return "%sreal_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), m_name);
1471				}
1472			} else {
1473				return name;
1474			}
1475		} else if (sym is PropertyAccessor) {
1476			unowned PropertyAccessor acc = (PropertyAccessor) sym;
1477			unowned Property prop = (Property) acc.prop;
1478			if (prop.base_property != null || prop.base_interface_property != null) {
1479				if (acc.readable) {
1480					return "%sreal_get_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name);
1481				} else {
1482					return "%sreal_set_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name);
1483				}
1484			} else {
1485				return name;
1486			}
1487		}
1488		assert_not_reached ();
1489	}
1490
1491	private string get_default_const_name () {
1492		if (node is DataType) {
1493			unowned DataType type = (DataType) node;
1494			string ptr;
1495			TypeSymbol t;
1496			// FIXME: workaround to make constant arrays possible
1497			if (type is ArrayType) {
1498				t = ((ArrayType) type).element_type.type_symbol;
1499			} else {
1500				t = type.type_symbol;
1501			}
1502			if (!t.is_reference_type ()) {
1503				ptr = "";
1504			} else {
1505				ptr = "*";
1506			}
1507
1508			return "const %s%s".printf (get_ccode_name (t), ptr);
1509		} else {
1510			if (node is Class && ((Class) node).is_immutable) {
1511				return "const %s".printf (name);
1512			} else {
1513				return name;
1514			}
1515		}
1516	}
1517
1518	private bool get_default_delegate_target () {
1519		if (node is Field || node is Parameter || node is LocalVariable) {
1520			if (node is Parameter) {
1521				unowned Parameter param = (Parameter) node;
1522				if (param.base_parameter != null) {
1523					return get_ccode_delegate_target (param.base_parameter);
1524				}
1525			}
1526			unowned DelegateType? delegate_type = ((Variable) node).variable_type as DelegateType;
1527			return delegate_type != null && delegate_type.delegate_symbol.has_target;
1528		} else if (node is Callable) {
1529			if (node is Method) {
1530				unowned Method method = (Method) node;
1531				if (method.base_method != null && method.base_method != method) {
1532					return get_ccode_delegate_target (method.base_method);
1533				} else if (method.base_interface_method != null && method.base_interface_method != method) {
1534					return get_ccode_delegate_target (method.base_interface_method);
1535				}
1536			}
1537			unowned DelegateType? delegate_type = ((Callable) node).return_type as DelegateType;
1538			return delegate_type != null && delegate_type.delegate_symbol.has_target;
1539		} else if (node is Property) {
1540			unowned Property prop = (Property) node;
1541			if (prop.base_property != null && prop.base_property != prop) {
1542				return get_ccode_delegate_target (prop.base_property);
1543			} else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1544				return get_ccode_delegate_target (prop.base_interface_property);
1545			}
1546			unowned DelegateType? delegate_type = prop.property_type as DelegateType;
1547			return delegate_type != null && delegate_type.delegate_symbol.has_target;
1548		} else if (node is PropertyAccessor) {
1549			return get_ccode_delegate_target (((PropertyAccessor) node).prop);
1550		} else if (node is Expression) {
1551			unowned Symbol? symbol = ((Expression) node).symbol_reference;
1552			if (symbol != null) {
1553				return get_ccode_delegate_target (symbol);
1554			}
1555		}
1556		return false;
1557	}
1558
1559	private bool get_default_array_length () {
1560		if (node is Parameter) {
1561			unowned Parameter param = (Parameter) node;
1562			if (param.base_parameter != null) {
1563				return get_ccode_array_length (param.base_parameter);
1564			}
1565		} else if (node is Method) {
1566			unowned Method method = (Method) node;
1567			if (method.base_method != null && method.base_method != method) {
1568				return get_ccode_array_length (method.base_method);
1569			} else if (method.base_interface_method != null && method.base_interface_method != method) {
1570				return get_ccode_array_length (method.base_interface_method);
1571			}
1572		} else if (node is Property) {
1573			unowned Property prop = (Property) node;
1574			if (prop.base_property != null && prop.base_property != prop) {
1575				return get_ccode_array_length (prop.base_property);
1576			} else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1577				return get_ccode_array_length (prop.base_interface_property);
1578			}
1579		} else if (node is PropertyAccessor) {
1580			return get_ccode_array_length (((PropertyAccessor) node).prop);
1581		}
1582		return true;
1583	}
1584
1585	private bool get_default_array_null_terminated () {
1586		if (node is Parameter) {
1587			unowned Parameter param = (Parameter) node;
1588			if (param.base_parameter != null) {
1589				return get_ccode_array_null_terminated (param.base_parameter);
1590			}
1591		} else if (node is Method) {
1592			unowned Method method = (Method) node;
1593			if (method.base_method != null && method.base_method != method) {
1594				return get_ccode_array_null_terminated (method.base_method);
1595			} else if (method.base_interface_method != null && method.base_interface_method != method) {
1596				return get_ccode_array_null_terminated (method.base_interface_method);
1597			}
1598		} else if (node is Property) {
1599			unowned Property prop = (Property) node;
1600			if (prop.base_property != null && prop.base_property != prop) {
1601				return get_ccode_array_null_terminated (prop.base_property);
1602			} else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1603				return get_ccode_array_null_terminated (prop.base_interface_property);
1604			}
1605		} else if (node is PropertyAccessor) {
1606			return get_ccode_array_null_terminated (((PropertyAccessor) node).prop);
1607		}
1608		return false;
1609	}
1610
1611	private string get_default_array_length_type () {
1612		if (node is Field || node is Parameter) {
1613			if (node is Parameter) {
1614				unowned Parameter param = (Parameter) node;
1615				if (param.base_parameter != null) {
1616					return get_ccode_array_length_type (param.base_parameter);
1617				}
1618			}
1619			return get_ccode_array_length_type (((Variable) node).variable_type);
1620		} else if (node is Method || node is Delegate) {
1621			if (node is Method) {
1622				unowned Method method = (Method) node;
1623				if (method.base_method != null && method.base_method != method) {
1624					return get_ccode_array_length_type (method.base_method);
1625				} else if (method.base_interface_method != null && method.base_interface_method != method) {
1626					return get_ccode_array_length_type (method.base_interface_method);
1627				}
1628			}
1629			return get_ccode_array_length_type (((Callable) node).return_type);
1630		} else if (node is Property) {
1631			unowned Property prop = (Property) node;
1632			if (prop.base_property != null && prop.base_property != prop) {
1633				return get_ccode_array_length_type (prop.base_property);
1634			} else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1635				return get_ccode_array_length_type (prop.base_interface_property);
1636			} else {
1637				return get_ccode_array_length_type (prop.property_type);
1638			}
1639		} else if (node is PropertyAccessor) {
1640			return get_ccode_array_length_type (((PropertyAccessor) node).prop);
1641		} else {
1642			Report.error (node.source_reference, "`CCode.array_length_type' not supported");
1643			return "";
1644		}
1645	}
1646}
1647