]> git.ipfire.org Git - people/ms/gcc.git/blob - gcc/d/d-lang.cc
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[people/ms/gcc.git] / gcc / d / d-lang.cc
1 /* d-lang.cc -- Language-dependent hooks for D.
2 Copyright (C) 2006-2023 Free Software Foundation, Inc.
3
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
17
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
21
22 #include "dmd/aggregate.h"
23 #include "dmd/cond.h"
24 #include "dmd/declaration.h"
25 #include "dmd/doc.h"
26 #include "dmd/errors.h"
27 #include "dmd/expression.h"
28 #include "dmd/hdrgen.h"
29 #include "dmd/id.h"
30 #include "dmd/identifier.h"
31 #include "dmd/json.h"
32 #include "dmd/mangle.h"
33 #include "dmd/module.h"
34 #include "dmd/mtype.h"
35 #include "dmd/target.h"
36 #include "dmd/template.h"
37
38 #include "opts.h"
39 #include "alias.h"
40 #include "tree.h"
41 #include "diagnostic.h"
42 #include "fold-const.h"
43 #include "toplev.h"
44 #include "langhooks.h"
45 #include "langhooks-def.h"
46 #include "target.h"
47 #include "function.h"
48 #include "stringpool.h"
49 #include "stor-layout.h"
50 #include "varasm.h"
51 #include "output.h"
52 #include "print-tree.h"
53 #include "debug.h"
54 #include "input.h"
55
56 #include "d-tree.h"
57 #include "d-frontend.h"
58
59
60 /* Array of D frontend type/decl nodes. */
61 tree d_global_trees[DTI_MAX];
62
63 /* True if compilation is currently inside the D frontend semantic passes. */
64 bool doing_semantic_analysis_p = false;
65
66 /* Options handled by the compiler that are separate from the frontend. */
67 struct d_option_data
68 {
69 const char *fonly; /* -fonly=<arg> */
70 const char *multilib; /* -imultilib <dir> */
71 const char *prefix; /* -iprefix <dir> */
72
73 bool deps; /* -M */
74 bool deps_skip_system; /* -MM */
75 const char *deps_filename; /* -M[M]D */
76 const char *deps_filename_user; /* -MF <arg> */
77 vec <const char *> deps_target; /* -M[QT] <arg> */
78 bool deps_phony; /* -MP */
79
80 bool stdinc; /* -nostdinc */
81 }
82 d_option;
83
84 /* List of modules being compiled. */
85 static Modules builtin_modules;
86
87 /* The current and global binding level in effect. */
88 struct binding_level *current_binding_level;
89 struct binding_level *global_binding_level;
90
91 /* The context to be used for global declarations. */
92 static GTY(()) tree global_context;
93
94 /* Array of all global declarations to pass back to the middle-end. */
95 static GTY(()) vec <tree, va_gc> *global_declarations;
96
97 /* Support for GCC-style command-line make dependency generation.
98 Adds TARGET to the make dependencies target buffer.
99 QUOTED is true if the string should be quoted. */
100
101 static void
102 deps_add_target (const char *target, bool quoted)
103 {
104 obstack buffer;
105 gcc_obstack_init (&buffer);
106
107 if (!quoted)
108 {
109 obstack_grow0 (&buffer, target, strlen (target));
110 d_option.deps_target.safe_push ((const char *) obstack_finish (&buffer));
111 return;
112 }
113
114 /* Quote characters in target which are significant to Make. */
115 unsigned slashes = 0;
116
117 for (const char *p = target; *p != '\0'; p++)
118 {
119 switch (*p)
120 {
121 case '\\':
122 slashes++;
123 break;
124
125 case ' ':
126 case '\t':
127 while (slashes--)
128 obstack_1grow (&buffer, '\\');
129 obstack_1grow (&buffer, '\\');
130 goto Ldef;
131
132 case '$':
133 obstack_1grow (&buffer, '$');
134 goto Ldef;
135
136 case '#':
137 case ':':
138 obstack_1grow (&buffer, '\\');
139 goto Ldef;
140
141 default:
142 Ldef:
143 slashes = 0;
144 break;
145 }
146
147 obstack_1grow (&buffer, *p);
148 }
149
150 obstack_1grow (&buffer, '\0');
151 d_option.deps_target.safe_push ((const char *) obstack_finish (&buffer));
152 }
153
154 /* Write STR, with a leading space to BUFFER, updating COLUMN as appropriate.
155 COLMAX is the number of columns to word-wrap at (0 means don't wrap). */
156
157 static void
158 deps_write_string (const char *str, obstack *buffer, unsigned &column,
159 unsigned colmax = 72)
160 {
161 unsigned size = strlen (str);
162
163 if (column != 0)
164 {
165 if (colmax && column + size > colmax)
166 {
167 obstack_grow (buffer, " \\\n ", 4);
168 column = 1;
169 }
170 else
171 {
172 obstack_1grow (buffer, ' ');
173 column++;
174 }
175 }
176
177 column += size;
178 obstack_grow (buffer, str, size);
179 }
180
181 /* Write out all dependencies of a given MODULE to the specified BUFFER. */
182
183 static void
184 deps_write (Module *module, obstack *buffer)
185 {
186 hash_set <const char *> seen_modules;
187 vec <const char *> dependencies = vNULL;
188
189 Modules modlist;
190 modlist.push (module);
191
192 vec <const char *> phonylist = vNULL;
193 unsigned column = 0;
194
195 /* Write out make target module name. */
196 if (d_option.deps_target.length ())
197 {
198 for (unsigned i = 0; i < d_option.deps_target.length (); i++)
199 deps_write_string (d_option.deps_target[i], buffer, column);
200 }
201 else
202 deps_write_string (module->objfile.toChars (), buffer, column);
203
204 obstack_1grow (buffer, ':');
205 column++;
206
207 /* Search all modules for file dependencies. */
208 while (modlist.length > 0)
209 {
210 Module *depmod = modlist.pop ();
211
212 const char *modstr = depmod->srcfile.toChars ();
213
214 /* Skip modules that have already been looked at. */
215 if (seen_modules.add (modstr))
216 continue;
217
218 dependencies.safe_push (modstr);
219
220 /* Add to list of phony targets if is not being compile. */
221 if (d_option.deps_phony && !depmod->isRoot ())
222 phonylist.safe_push (modstr);
223
224 /* Add imported files to dependency list. */
225 for (size_t i = 0; i < depmod->contentImportedFiles.length; i++)
226 {
227 const char *impstr = depmod->contentImportedFiles[i];
228 dependencies.safe_push (impstr);
229 phonylist.safe_push (impstr);
230 }
231
232 /* Search all imports of the module. */
233 for (size_t i = 0; i < depmod->aimports.length; i++)
234 {
235 Module *m = depmod->aimports[i];
236
237 /* Ignore compiler-generated modules. */
238 if (m->ident == Identifier::idPool ("__main") && m->parent == NULL)
239 continue;
240
241 /* Don't search system installed modules, this includes
242 object, core.*, std.*, and gcc.* packages. */
243 if (d_option.deps_skip_system)
244 {
245 if (m->ident == Identifier::idPool ("object")
246 && m->parent == NULL)
247 continue;
248
249 if (m->md && m->md->packages.length)
250 {
251 Identifier *package = m->md->packages.ptr[0];
252
253 if (package == Identifier::idPool ("core")
254 || package == Identifier::idPool ("std")
255 || package == Identifier::idPool ("gcc"))
256 continue;
257 }
258 }
259
260 modlist.push (m);
261 }
262 }
263
264 /* Write out all make dependencies. */
265 for (size_t i = 0; i < dependencies.length (); i++)
266 deps_write_string (dependencies[i], buffer, column);
267
268 obstack_1grow (buffer, '\n');
269
270 /* Write out all phony targets. */
271 for (size_t i = 0; i < phonylist.length (); i++)
272 {
273 const char *str = phonylist[i];
274 obstack_1grow (buffer, '\n');
275 obstack_grow (buffer, str, strlen (str));
276 obstack_grow (buffer, ":\n", 2);
277 }
278
279 obstack_1grow (buffer, '\0');
280 }
281
282 /* Implements the lang_hooks.init_options routine for language D.
283 This initializes the global state for the D frontend before calling
284 the option handlers. */
285
286 static void
287 d_init_options (unsigned int, cl_decoded_option *decoded_options)
288 {
289 /* Initialize the D runtime. */
290 rt_init ();
291 gc_disable ();
292
293 /* Set default values. */
294 global._init ();
295
296 global.vendor = lang_hooks.name;
297 global.params.argv0 = xstrdup (decoded_options[0].arg);
298 global.params.errorLimit = flag_max_errors;
299
300 /* Default extern(C++) mangling to C++17. */
301 global.params.cplusplus = CppStdRevisionCpp17;
302
303 /* Warnings and deprecations are disabled by default. */
304 global.params.useDeprecated = DIAGNOSTICinform;
305 global.params.warnings = DIAGNOSTICoff;
306 global.params.messageStyle = MessageStyle::gnu;
307
308 global.params.imppath = d_gc_malloc<Strings> ();
309 global.params.fileImppath = d_gc_malloc<Strings> ();
310
311 /* Extra GDC-specific options. */
312 d_option.fonly = NULL;
313 d_option.multilib = NULL;
314 d_option.prefix = NULL;
315 d_option.deps = false;
316 d_option.deps_skip_system = false;
317 d_option.deps_filename = NULL;
318 d_option.deps_filename_user = NULL;
319 d_option.deps_target = vNULL;
320 d_option.deps_phony = false;
321 d_option.stdinc = true;
322 }
323
324 /* Implements the lang_hooks.init_options_struct routine for language D.
325 Initializes the options structure OPTS. */
326
327 static void
328 d_init_options_struct (gcc_options *opts)
329 {
330 /* GCC options. */
331 opts->x_flag_exceptions = 1;
332
333 /* Unlike C, there is no global `errno' variable. */
334 opts->x_flag_errno_math = 0;
335 opts->frontend_set_flag_errno_math = true;
336
337 /* D says that signed overflow is precisely defined. */
338 opts->x_flag_wrapv = 1;
339 }
340
341 /* Implements the lang_hooks.lang_mask routine for language D.
342 Returns language mask for option parsing. */
343
344 static unsigned int
345 d_option_lang_mask (void)
346 {
347 return CL_D;
348 }
349
350 /* Implements input charset and BOM skipping configuration for
351 diagnostics. */
352 static const char *d_input_charset_callback (const char * /*filename*/)
353 {
354 /* TODO: The input charset is automatically determined by code in
355 dmd/dmodule.c based on the contents of the file. If this detection
356 logic were factored out and could be reused here, then we would be able
357 to return UTF-16 or UTF-32 as needed here. For now, we return always
358 NULL, which means no conversion is necessary, i.e. the input is assumed
359 to be UTF-8 when diagnostics read this file. */
360 return nullptr;
361 }
362
363 /* Implements the lang_hooks.init routine for language D. */
364
365 static bool
366 d_init (void)
367 {
368 Type::_init ();
369 Id::initialize ();
370 Module::_init ();
371 Expression::_init ();
372 Objc::_init ();
373
374 /* Diagnostics input init, to enable BOM skipping and
375 input charset conversion. */
376 diagnostic_initialize_input_context (global_dc,
377 d_input_charset_callback, true);
378
379 /* Back-end init. */
380 global_binding_level = ggc_cleared_alloc <binding_level> ();
381 current_binding_level = global_binding_level;
382
383 /* This allows the code in d-builtins.cc to not have to worry about
384 converting (C signed char *) to (D char *) for string arguments of
385 built-in functions. The parameter (signed_char = false) specifies
386 whether char is signed. */
387 build_common_tree_nodes (false);
388
389 d_init_builtins ();
390
391 if (flag_exceptions)
392 using_eh_for_cleanups ();
393
394 if (!supports_one_only ())
395 flag_weak_templates = 0;
396
397 /* This is the C main, not the D main. */
398 main_identifier_node = get_identifier ("main");
399
400 target._init (global.params);
401 d_init_versions ();
402
403 /* Insert all library-configured identifiers and import paths. */
404 add_import_paths (d_option.prefix, d_option.multilib, d_option.stdinc);
405
406 return 1;
407 }
408
409 /* Implements the lang_hooks.init_ts routine for language D. */
410
411 static void
412 d_init_ts (void)
413 {
414 MARK_TS_TYPED (FLOAT_MOD_EXPR);
415 MARK_TS_TYPED (UNSIGNED_RSHIFT_EXPR);
416 }
417
418 /* Implements the lang_hooks.handle_option routine for language D.
419 Handles D specific options. Return false if we didn't do anything. */
420
421 static bool
422 d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
423 int kind ATTRIBUTE_UNUSED,
424 location_t loc ATTRIBUTE_UNUSED,
425 const cl_option_handlers *handlers ATTRIBUTE_UNUSED)
426 {
427 opt_code code = (opt_code) scode;
428 bool result = true;
429
430 switch (code)
431 {
432 case OPT_fall_instantiations:
433 global.params.allInst = value;
434 break;
435
436 case OPT_fassert:
437 global.params.useAssert = value ? CHECKENABLEon : CHECKENABLEoff;
438 break;
439
440 case OPT_fbounds_check:
441 global.params.useArrayBounds = value ? CHECKENABLEon : CHECKENABLEoff;
442 break;
443
444 case OPT_fbounds_check_:
445 global.params.useArrayBounds = (value == 2) ? CHECKENABLEon
446 : (value == 1) ? CHECKENABLEsafeonly : CHECKENABLEoff;
447 break;
448
449 case OPT_fcheckaction_:
450 global.params.checkAction = (value == 0) ? CHECKACTION_D
451 : (value == 1) ? CHECKACTION_halt : CHECKACTION_context;
452 break;
453
454 case OPT_fdebug:
455 global.params.debuglevel = value ? 1 : 0;
456 break;
457
458 case OPT_fdebug_:
459 if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
460 {
461 if (!global.params.debugids)
462 global.params.debugids = d_gc_malloc<Strings> ();
463 global.params.debugids->push (arg);
464 break;
465 }
466
467 error ("bad argument for %<-fdebug%>: %qs", arg);
468 break;
469
470 case OPT_fdoc:
471 global.params.ddoc.doOutput = value;
472 break;
473
474 case OPT_fdoc_dir_:
475 global.params.ddoc.doOutput = true;
476 global.params.ddoc.dir = arg;
477 break;
478
479 case OPT_fdoc_file_:
480 global.params.ddoc.doOutput = true;
481 global.params.ddoc.name = arg;
482 break;
483
484 case OPT_fdoc_inc_:
485 global.params.ddoc.files.push (arg);
486 break;
487
488 case OPT_fdruntime:
489 global.params.betterC = !value;
490 break;
491
492 case OPT_fdump_c___spec_:
493 global.params.cxxhdr.doOutput = true;
494 global.params.cxxhdr.name = arg;
495 break;
496
497 case OPT_fdump_c___spec_verbose:
498 global.params.cxxhdr.fullOutput = true;
499 break;
500
501 case OPT_fdump_d_original:
502 global.params.vcg_ast = value;
503 break;
504
505 case OPT_fexceptions:
506 global.params.useExceptions = value;
507 break;
508
509 case OPT_fextern_std_:
510 switch (value)
511 {
512 case CppStdRevisionCpp98:
513 case CppStdRevisionCpp11:
514 case CppStdRevisionCpp14:
515 case CppStdRevisionCpp17:
516 case CppStdRevisionCpp20:
517 global.params.cplusplus = (CppStdRevision) value;
518 break;
519
520 default:
521 error ("bad argument for %<-fextern-std%>: %qs", arg);
522 }
523 break;
524
525 case OPT_fignore_unknown_pragmas:
526 global.params.ignoreUnsupportedPragmas = value;
527 break;
528
529 case OPT_finvariants:
530 global.params.useInvariants = value ? CHECKENABLEon : CHECKENABLEoff;
531 break;
532
533 case OPT_fmain:
534 global.params.addMain = value;
535 break;
536
537 case OPT_fmodule_file_:
538 global.params.modFileAliasStrings.push (arg);
539 if (!strchr (arg, '='))
540 error ("bad argument for %<-fmodule-file%>: %qs", arg);
541 break;
542
543 case OPT_fmoduleinfo:
544 global.params.useModuleInfo = value;
545 break;
546
547 case OPT_fonly_:
548 d_option.fonly = arg;
549 break;
550
551 case OPT_fpostconditions:
552 global.params.useOut = value ? CHECKENABLEon : CHECKENABLEoff;
553 break;
554
555 case OPT_fpreconditions:
556 global.params.useIn = value ? CHECKENABLEon : CHECKENABLEoff;
557 break;
558
559 case OPT_fpreview_all:
560 global.params.ehnogc = value;
561 global.params.useDIP1000 = FeatureState::enabled;
562 global.params.useDIP1021 = value;
563 global.params.bitfields = value;
564 global.params.dtorFields = FeatureState::enabled;
565 global.params.fieldwise = value;
566 global.params.fixAliasThis = value;
567 global.params.previewIn = value;
568 global.params.fix16997 = value;
569 global.params.noSharedAccess = FeatureState::enabled;
570 global.params.rvalueRefParam = FeatureState::enabled;
571 global.params.inclusiveInContracts = value;
572 global.params.systemVariables = FeatureState::enabled;
573 global.params.fixImmutableConv = value;
574 break;
575
576 case OPT_fpreview_bitfields:
577 global.params.bitfields = value;
578 break;
579
580 case OPT_fpreview_dip1000:
581 global.params.useDIP1000 = FeatureState::enabled;
582 break;
583
584 case OPT_fpreview_dip1008:
585 global.params.ehnogc = value;
586 break;
587
588 case OPT_fpreview_dip1021:
589 global.params.useDIP1021 = value;
590 break;
591
592 case OPT_fpreview_dtorfields:
593 global.params.dtorFields = FeatureState::enabled;
594 break;
595
596 case OPT_fpreview_fieldwise:
597 global.params.fieldwise = value;
598 break;
599
600 case OPT_fpreview_fixaliasthis:
601 global.params.fixAliasThis = value;
602 break;
603
604 case OPT_fpreview_fiximmutableconv:
605 global.params.fixImmutableConv = value;
606 break;
607
608 case OPT_fpreview_in:
609 global.params.previewIn = value;
610 break;
611
612 case OPT_fpreview_inclusiveincontracts:
613 global.params.inclusiveInContracts = value;
614 break;
615
616 case OPT_fpreview_nosharedaccess:
617 global.params.noSharedAccess = FeatureState::enabled;
618 break;
619
620 case OPT_fpreview_rvaluerefparam:
621 global.params.rvalueRefParam = FeatureState::enabled;
622 break;
623
624 case OPT_fpreview_systemvariables:
625 global.params.systemVariables = FeatureState::enabled;
626 break;
627
628 case OPT_frelease:
629 global.params.release = value;
630 break;
631
632 case OPT_frevert_all:
633 global.params.useDIP1000 = FeatureState::disabled;
634 global.params.dtorFields = FeatureState::disabled;
635 global.params.fix16997 = !value;
636 break;
637
638 case OPT_frevert_dip1000:
639 global.params.useDIP1000 = FeatureState::disabled;
640 break;
641
642 case OPT_frevert_dtorfields:
643 global.params.dtorFields = FeatureState::disabled;
644 break;
645
646 case OPT_frevert_intpromote:
647 global.params.fix16997 = !value;
648 break;
649
650 case OPT_frtti:
651 global.params.useTypeInfo = value;
652 break;
653
654 case OPT_fsave_mixins_:
655 global.params.mixinOut.doOutput = true;
656 global.params.mixinOut.name = arg;
657 global.params.mixinOut.buffer = d_gc_malloc<OutBuffer> ();
658 break;
659
660 case OPT_fswitch_errors:
661 global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
662 break;
663
664 case OPT_ftransition_all:
665 global.params.vfield = value;
666 global.params.vgc = value;
667 global.params.vin = value;
668 global.params.vtls = value;
669 break;
670
671 case OPT_ftransition_field:
672 global.params.vfield = value;
673 break;
674
675 case OPT_ftransition_in:
676 global.params.vin = value;
677 break;
678
679 case OPT_ftransition_nogc:
680 global.params.vgc = value;
681 break;
682
683 case OPT_ftransition_templates:
684 global.params.vtemplates = value;
685 break;
686
687 case OPT_ftransition_tls:
688 global.params.vtls = value;
689 break;
690
691 case OPT_funittest:
692 global.params.useUnitTests = value;
693 break;
694
695 case OPT_fversion_:
696 if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
697 {
698 if (!global.params.versionids)
699 global.params.versionids = d_gc_malloc<Strings> ();
700 global.params.versionids->push (arg);
701 break;
702 }
703
704 error ("bad argument for %<-fversion%>: %qs", arg);
705 break;
706
707 case OPT_H:
708 global.params.dihdr.doOutput = true;
709 break;
710
711 case OPT_Hd:
712 global.params.dihdr.doOutput = true;
713 global.params.dihdr.dir = arg;
714 break;
715
716 case OPT_Hf:
717 global.params.dihdr.doOutput = true;
718 global.params.dihdr.name = arg;
719 break;
720
721 case OPT_imultilib:
722 d_option.multilib = arg;
723 break;
724
725 case OPT_iprefix:
726 d_option.prefix = arg;
727 break;
728
729 case OPT_I:
730 global.params.imppath->push (arg);
731 break;
732
733 case OPT_J:
734 global.params.fileImppath->push (arg);
735 break;
736
737 case OPT_MM:
738 d_option.deps_skip_system = true;
739 /* Fall through. */
740
741 case OPT_M:
742 d_option.deps = true;
743 break;
744
745 case OPT_MMD:
746 d_option.deps_skip_system = true;
747 /* Fall through. */
748
749 case OPT_MD:
750 d_option.deps = true;
751 d_option.deps_filename = arg;
752 break;
753
754 case OPT_MF:
755 /* If specified multiple times, last one wins. */
756 d_option.deps_filename_user = arg;
757 break;
758
759 case OPT_MP:
760 d_option.deps_phony = true;
761 break;
762
763 case OPT_MQ:
764 deps_add_target (arg, true);
765 break;
766
767 case OPT_MT:
768 deps_add_target (arg, false);
769 break;
770
771 case OPT_nostdinc:
772 d_option.stdinc = false;
773 break;
774
775 case OPT_v:
776 global.params.verbose = value;
777 break;
778
779 case OPT_Wall:
780 if (value)
781 global.params.warnings = DIAGNOSTICinform;
782 break;
783
784 case OPT_Wdeprecated:
785 global.params.useDeprecated = value ? DIAGNOSTICinform : DIAGNOSTICoff;
786 break;
787
788 case OPT_Werror:
789 if (value)
790 global.params.warnings = DIAGNOSTICerror;
791 break;
792
793 case OPT_Wspeculative:
794 if (value)
795 global.params.showGaggedErrors = 1;
796 break;
797
798 case OPT_Xf:
799 global.params.json.name = arg;
800 /* Fall through. */
801
802 case OPT_X:
803 global.params.json.doOutput = true;
804 break;
805
806 default:
807 break;
808 }
809
810 D_handle_option_auto (&global_options, &global_options_set,
811 scode, arg, value,
812 d_option_lang_mask (), kind,
813 loc, handlers, global_dc);
814
815 return result;
816 }
817
818 /* Implements the lang_hooks.post_options routine for language D.
819 Deal with any options that imply the turning on/off of features.
820 FN is the main input filename passed on the command line. */
821
822 static bool
823 d_post_options (const char ** fn)
824 {
825 /* Verify the input file name. */
826 const char *filename = *fn;
827 if (!filename || strcmp (filename, "-") == 0)
828 filename = "";
829
830 /* The front end considers the first input file to be the main one. */
831 *fn = filename;
832
833 /* Release mode doesn't turn off bounds checking for safe functions. */
834 if (global.params.useArrayBounds == CHECKENABLEdefault)
835 {
836 global.params.useArrayBounds = global.params.release
837 ? CHECKENABLEsafeonly : CHECKENABLEon;
838 }
839
840 /* Assert code is generated if unittests are being compiled also, even if
841 release mode is turned on. */
842 if (global.params.useAssert == CHECKENABLEdefault)
843 {
844 if (global.params.useUnitTests || !global.params.release)
845 global.params.useAssert = CHECKENABLEon;
846 else
847 global.params.useAssert = CHECKENABLEoff;
848 }
849
850 /* Checks for switches without a default are turned off in release mode. */
851 if (global.params.useSwitchError == CHECKENABLEdefault)
852 {
853 global.params.useSwitchError = global.params.release
854 ? CHECKENABLEoff : CHECKENABLEon;
855 }
856
857 /* Contracts are turned off in release mode. */
858 if (global.params.useInvariants == CHECKENABLEdefault)
859 {
860 global.params.useInvariants = global.params.release
861 ? CHECKENABLEoff : CHECKENABLEon;
862 }
863
864 if (global.params.useIn == CHECKENABLEdefault)
865 {
866 global.params.useIn = global.params.release
867 ? CHECKENABLEoff : CHECKENABLEon;
868 }
869
870 if (global.params.useOut == CHECKENABLEdefault)
871 {
872 global.params.useOut = global.params.release
873 ? CHECKENABLEoff : CHECKENABLEon;
874 }
875
876 /* When not linking against D runtime, turn off all code generation that
877 would otherwise reference it. */
878 if (global.params.betterC)
879 {
880 if (!OPTION_SET_P (flag_moduleinfo))
881 global.params.useModuleInfo = false;
882
883 /* Ensure that the front-end options are in sync with the `-frtti' and
884 `-fexceptions' flags. */
885 if (!OPTION_SET_P (flag_rtti))
886 {
887 global.params.useTypeInfo = false;
888 flag_rtti = false;
889 }
890
891 if (!OPTION_SET_P (flag_exceptions))
892 {
893 global.params.useExceptions = false;
894 flag_exceptions = false;
895 }
896
897 global.params.checkAction = CHECKACTION_C;
898 }
899
900 /* Enabling DIP1021 implies DIP1000. */
901 if (global.params.useDIP1021)
902 global.params.useDIP1000 = FeatureState::enabled;
903
904 /* Keep in sync with existing -fbounds-check flag. */
905 flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
906
907 /* Turn off partitioning unless it was explicitly requested, as it doesn't
908 work with D exception chaining, where EH handler uses LSDA to determine
909 whether two thrown exception are in the same context. */
910 if (!OPTION_SET_P (flag_reorder_blocks_and_partition))
911 global_options.x_flag_reorder_blocks_and_partition = 0;
912
913 /* Error about use of deprecated features. */
914 if (global.params.useDeprecated == DIAGNOSTICinform
915 && global.params.warnings == DIAGNOSTICerror)
916 global.params.useDeprecated = DIAGNOSTICerror;
917
918 /* Make -fmax-errors visible to frontend's diagnostic machinery. */
919 if (OPTION_SET_P (flag_max_errors))
920 global.params.errorLimit = flag_max_errors;
921
922 if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
923 flag_excess_precision = EXCESS_PRECISION_STANDARD;
924
925 global.params.useInline = flag_inline_functions;
926 global.params.showColumns = flag_show_column;
927 global.params.printErrorContext = flag_diagnostics_show_caret;
928
929 /* Keep the front-end location type in sync with params. */
930 Loc::set (global.params.showColumns, global.params.messageStyle);
931
932 if (global.params.useInline)
933 global.params.dihdr.fullOutput = true;
934
935 global.params.obj = !flag_syntax_only;
936
937 /* Add in versions given on the command line. */
938 if (global.params.versionids)
939 {
940 for (size_t i = 0; i < global.params.versionids->length; i++)
941 {
942 const char *s = (*global.params.versionids)[i];
943 VersionCondition::addGlobalIdent (s);
944 }
945 }
946
947 if (global.params.debugids)
948 {
949 for (size_t i = 0; i < global.params.debugids->length; i++)
950 {
951 const char *s = (*global.params.debugids)[i];
952 DebugCondition::addGlobalIdent (s);
953 }
954 }
955
956 if (warn_return_type == -1)
957 warn_return_type = 0;
958
959 return false;
960 }
961
962 /* Add the module M to the list of modules that may declare GCC builtins.
963 These are scanned after first semantic and before codegen passes.
964 See d_maybe_set_builtin() for the implementation. */
965
966 void
967 d_add_builtin_module (Module *m)
968 {
969 builtin_modules.push (m);
970 }
971
972 /* Implements the lang_hooks.parse_file routine for language D. */
973
974 static void
975 d_parse_file (void)
976 {
977 if (global.params.verbose)
978 {
979 message ("binary %s", global.params.argv0.ptr);
980 message ("version %s", global.versionChars ());
981
982 if (global.versionids)
983 {
984 obstack buffer;
985 gcc_obstack_init (&buffer);
986 obstack_grow (&buffer, "predefs ", 9);
987 for (size_t i = 0; i < global.versionids->length; i++)
988 {
989 Identifier *id = (*global.versionids)[i];
990 const char *str = id->toChars ();
991 obstack_1grow (&buffer, ' ');
992 obstack_grow (&buffer, str, strlen (str));
993 }
994
995 obstack_1grow (&buffer, '\0');
996 message ("%s", (char *) obstack_finish (&buffer));
997 }
998 }
999
1000 /* Start the main input file, if the debug writer wants it. */
1001 if (debug_hooks->start_end_main_source_file)
1002 debug_hooks->start_source_file (0, main_input_filename);
1003
1004 /* Create Module's for all sources we will load. */
1005 Modules modules;
1006 modules.reserve (num_in_fnames);
1007
1008 /* In this mode, the first file name is supposed to be a duplicate
1009 of one of the input files. */
1010 if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
1011 error ("%<-fonly=%> argument is different from first input file name");
1012
1013 for (size_t i = 0; i < num_in_fnames; i++)
1014 {
1015 if (strcmp (in_fnames[i], "-") == 0)
1016 {
1017 /* Load the entire contents of stdin into memory. 8 kilobytes should
1018 be a good enough initial size, but double on each iteration.
1019 16 bytes are added for the final '\n' and 15 bytes of padding. */
1020 ssize_t size = 8 * 1024;
1021 uchar *buffer = XNEWVEC (uchar, size + 16);
1022 ssize_t len = 0;
1023 ssize_t count;
1024
1025 while ((count = read (STDIN_FILENO, buffer + len, size - len)) > 0)
1026 {
1027 len += count;
1028 if (len == size)
1029 {
1030 size *= 2;
1031 buffer = XRESIZEVEC (uchar, buffer, size + 16);
1032 }
1033 }
1034
1035 if (count < 0)
1036 {
1037 error (Loc ("stdin", 0, 0), "%s", xstrerror (errno));
1038 free (buffer);
1039 continue;
1040 }
1041
1042 /* Handling stdin, generate a unique name for the module. */
1043 Module *m = Module::create (in_fnames[i],
1044 Identifier::idPool ("__stdin"),
1045 global.params.ddoc.doOutput,
1046 global.params.dihdr.doOutput);
1047 modules.push (m);
1048
1049 /* Zero the padding past the end of the buffer so the D lexer has a
1050 sentinel. The lexer only reads up to 4 bytes at a time. */
1051 memset (buffer + len, '\0', 16);
1052
1053 /* Overwrite the source file for the module, the one created by
1054 Module::create would have a forced a `.d' suffix. */
1055 m->src.length = len;
1056 m->src.ptr = buffer;
1057 }
1058 else
1059 {
1060 /* Handling a D source file, strip off the path and extension. */
1061 const char *basename = FileName::name (in_fnames[i]);
1062 const char *name = FileName::removeExt (basename);
1063
1064 Module *m = Module::create (in_fnames[i], Identifier::idPool (name),
1065 global.params.ddoc.doOutput,
1066 global.params.dihdr.doOutput);
1067 modules.push (m);
1068 FileName::free (name);
1069 }
1070 }
1071
1072 /* Read all D source files. */
1073 for (size_t i = 0; i < modules.length; i++)
1074 {
1075 Module *m = modules[i];
1076 m->read (Loc ());
1077 }
1078
1079 /* Parse all D source files. */
1080 for (size_t i = 0; i < modules.length; i++)
1081 {
1082 Module *m = modules[i];
1083
1084 if (global.params.verbose)
1085 message ("parse %s", m->toChars ());
1086
1087 if (!Module::rootModule)
1088 Module::rootModule = m;
1089
1090 m->importedFrom = m;
1091 m->parse ();
1092
1093 if (m->filetype == FileType::ddoc)
1094 {
1095 gendocfile (m);
1096 /* Remove M from list of modules. */
1097 modules.remove (i);
1098 i--;
1099 }
1100 }
1101
1102 /* Load the module containing D main. */
1103 Module *main_module = NULL;
1104 if (global.params.addMain)
1105 {
1106 unsigned errors = global.startGagging ();
1107 main_module = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
1108
1109 if (!global.endGagging (errors))
1110 {
1111 main_module->importedFrom = main_module;
1112 modules.push (main_module);
1113 }
1114 }
1115
1116 /* If an error occurs later during compilation, remember that we generated
1117 the headers, so that they can be removed before exit. */
1118 bool dump_headers = false;
1119
1120 if (global.errors)
1121 goto had_errors;
1122
1123 if (global.params.dihdr.doOutput)
1124 {
1125 /* Generate 'header' import files. Since 'header' import files must be
1126 independent of command line switches and what else is imported, they
1127 are generated before any semantic analysis. */
1128 for (size_t i = 0; i < modules.length; i++)
1129 {
1130 Module *m = modules[i];
1131 if (m->filetype == FileType::dhdr
1132 || (d_option.fonly && m != Module::rootModule))
1133 continue;
1134
1135 if (global.params.verbose)
1136 message ("import %s", m->toChars ());
1137
1138 genhdrfile (m);
1139 }
1140
1141 dump_headers = true;
1142 }
1143
1144 if (global.errors)
1145 goto had_errors;
1146
1147 /* Load all unconditional imports for better symbol resolving. */
1148 for (size_t i = 0; i < modules.length; i++)
1149 {
1150 Module *m = modules[i];
1151
1152 if (global.params.verbose)
1153 message ("importall %s", m->toChars ());
1154
1155 m->importAll (NULL);
1156 }
1157
1158 if (global.errors)
1159 goto had_errors;
1160
1161 /* Do semantic analysis. */
1162 doing_semantic_analysis_p = true;
1163
1164 for (size_t i = 0; i < modules.length; i++)
1165 {
1166 Module *m = modules[i];
1167
1168 /* If this is the `__main` module, check that `D main` hasn't already
1169 been declared in user code before running semantic on it. */
1170 if (m == main_module && global.hasMainFunction)
1171 {
1172 modules.remove (i);
1173 continue;
1174 }
1175
1176 if (global.params.verbose)
1177 message ("semantic %s", m->toChars ());
1178
1179 dsymbolSemantic (m, NULL);
1180 }
1181
1182 /* Do deferred semantic analysis. */
1183 Module::runDeferredSemantic ();
1184
1185 if (Module::deferred.length)
1186 {
1187 for (size_t i = 0; i < Module::deferred.length; i++)
1188 {
1189 Dsymbol *sd = Module::deferred[i];
1190 error_at (make_location_t (sd->loc),
1191 "unable to resolve forward reference in definition");
1192 }
1193 }
1194
1195 /* Process all built-in modules or functions now for CTFE. */
1196 while (builtin_modules.length != 0)
1197 {
1198 Module *m = builtin_modules.pop ();
1199 d_maybe_set_builtin (m);
1200 }
1201
1202 /* Do pass 2 semantic analysis. */
1203 for (size_t i = 0; i < modules.length; i++)
1204 {
1205 Module *m = modules[i];
1206
1207 if (global.params.verbose)
1208 message ("semantic2 %s", m->toChars ());
1209
1210 semantic2 (m, NULL);
1211 }
1212
1213 Module::runDeferredSemantic2 ();
1214
1215 if (global.errors)
1216 goto had_errors;
1217
1218 /* Do pass 3 semantic analysis. */
1219 for (size_t i = 0; i < modules.length; i++)
1220 {
1221 Module *m = modules[i];
1222
1223 if (global.params.verbose)
1224 message ("semantic3 %s", m->toChars ());
1225
1226 semantic3 (m, NULL);
1227 }
1228
1229 Module::runDeferredSemantic3 ();
1230
1231 /* Check again, incase semantic3 pass loaded any more modules. */
1232 while (builtin_modules.length != 0)
1233 {
1234 Module *m = builtin_modules.pop ();
1235 d_maybe_set_builtin (m);
1236 }
1237
1238 /* Do not attempt to generate output files if errors or warnings occurred. */
1239 if (global.errors || global.warnings)
1240 goto had_errors;
1241
1242 /* Generate output files. */
1243 doing_semantic_analysis_p = false;
1244
1245 if (Module::rootModule)
1246 {
1247 /* Declare the name of the root module as the first global name in order
1248 to make the middle-end fully deterministic. */
1249 OutBuffer buf;
1250 mangleToBuffer (Module::rootModule, &buf);
1251 first_global_object_name = buf.extractChars ();
1252 }
1253
1254 /* Make dependencies. */
1255 if (d_option.deps)
1256 {
1257 obstack buffer;
1258 FILE *deps_stream;
1259
1260 gcc_obstack_init (&buffer);
1261
1262 for (size_t i = 0; i < modules.length; i++)
1263 deps_write (modules[i], &buffer);
1264
1265 /* -MF <arg> overrides -M[M]D. */
1266 if (d_option.deps_filename_user)
1267 d_option.deps_filename = d_option.deps_filename_user;
1268
1269 if (d_option.deps_filename)
1270 {
1271 deps_stream = fopen (d_option.deps_filename, "w");
1272 if (!deps_stream)
1273 {
1274 fatal_error (input_location, "opening dependency file %s: %m",
1275 d_option.deps_filename);
1276 goto had_errors;
1277 }
1278 }
1279 else
1280 deps_stream = stdout;
1281
1282 fprintf (deps_stream, "%s", (char *) obstack_finish (&buffer));
1283
1284 if (deps_stream != stdout
1285 && (ferror (deps_stream) || fclose (deps_stream)))
1286 {
1287 fatal_error (input_location, "closing dependency file %s: %m",
1288 d_option.deps_filename);
1289 }
1290 }
1291
1292 if (global.params.vtemplates)
1293 printTemplateStats ();
1294
1295 /* Generate JSON files. */
1296 if (global.params.json.doOutput)
1297 {
1298 OutBuffer buf;
1299 json_generate (&buf, &modules);
1300
1301 const char *name = global.params.json.name.ptr;
1302 FILE *json_stream;
1303
1304 if (name && (name[0] != '-' || name[1] != '\0'))
1305 {
1306 const char *nameext
1307 = FileName::defaultExt (name, json_ext.ptr);
1308 json_stream = fopen (nameext, "w");
1309 if (!json_stream)
1310 {
1311 fatal_error (input_location, "opening json file %s: %m", nameext);
1312 goto had_errors;
1313 }
1314 }
1315 else
1316 json_stream = stdout;
1317
1318 fprintf (json_stream, "%s", buf.peekChars ());
1319
1320 if (json_stream != stdout
1321 && (ferror (json_stream) || fclose (json_stream)))
1322 fatal_error (input_location, "closing json file %s: %m", name);
1323 }
1324
1325 /* Generate Ddoc files. */
1326 if (global.params.ddoc.doOutput && !global.errors && !errorcount)
1327 {
1328 for (size_t i = 0; i < modules.length; i++)
1329 {
1330 Module *m = modules[i];
1331 gendocfile (m);
1332 }
1333 }
1334
1335 /* Handle -fdump-d-original. */
1336 if (global.params.vcg_ast)
1337 {
1338 for (size_t i = 0; i < modules.length; i++)
1339 {
1340 Module *m = modules[i];
1341 OutBuffer buf;
1342 buf.doindent = 1;
1343
1344 moduleToBuffer (&buf, m);
1345 message ("%s", buf.peekChars ());
1346 }
1347 }
1348
1349 /* Generate C++ header files. */
1350 if (global.params.cxxhdr.doOutput)
1351 genCppHdrFiles (modules);
1352
1353 if (global.errors)
1354 goto had_errors;
1355
1356 for (size_t i = 0; i < modules.length; i++)
1357 {
1358 Module *m = modules[i];
1359
1360 /* Skip generating code for header files, or when the module wasn't
1361 specified by `-fonly=`. */
1362 if ((m->filetype == FileType::dhdr && m != main_module)
1363 || (d_option.fonly && m != Module::rootModule))
1364 continue;
1365
1366 if (global.params.verbose)
1367 message ("code %s", m->toChars ());
1368
1369 if (!flag_syntax_only)
1370 build_decl_tree (m);
1371 }
1372
1373 /* And end the main input file, if the debug writer wants it. */
1374 if (debug_hooks->start_end_main_source_file)
1375 debug_hooks->end_source_file (0);
1376
1377 had_errors:
1378 /* Add the D frontend error count to the GCC error count to correctly
1379 exit with an error status. */
1380 errorcount += (global.errors + global.warnings);
1381
1382 /* We want to write the mixin expansion file also on error. */
1383 if (global.params.mixinOut.doOutput)
1384 {
1385 FILE *mixin_stream = fopen (global.params.mixinOut.name.ptr, "w");
1386
1387 if (mixin_stream)
1388 {
1389 OutBuffer *buf = global.params.mixinOut.buffer;
1390 fprintf (mixin_stream, "%s", buf->peekChars ());
1391
1392 if (ferror (mixin_stream) || fclose (mixin_stream))
1393 fatal_error (input_location, "closing mixin file %s: %m",
1394 global.params.mixinOut.name.ptr);
1395 }
1396 else
1397 {
1398 fatal_error (input_location, "opening mixin file %s: %m",
1399 global.params.mixinOut.name.ptr);
1400 }
1401 }
1402
1403 /* Remove generated .di files on error. */
1404 if (errorcount && dump_headers)
1405 {
1406 for (size_t i = 0; i < modules.length; i++)
1407 {
1408 Module *m = modules[i];
1409 if (m->filetype == FileType::dhdr
1410 || (d_option.fonly && m != Module::rootModule))
1411 continue;
1412
1413 remove (m->hdrfile.toChars ());
1414 }
1415 }
1416
1417 /* Write out globals. */
1418 d_finish_compilation (vec_safe_address (global_declarations),
1419 vec_safe_length (global_declarations));
1420 }
1421
1422 /* Implements the lang_hooks.types.type_for_mode routine for language D. */
1423
1424 static tree
1425 d_type_for_mode (machine_mode mode, int unsignedp)
1426 {
1427 if (mode == QImode)
1428 return unsignedp ? d_ubyte_type : d_byte_type;
1429
1430 if (mode == HImode)
1431 return unsignedp ? d_ushort_type : d_short_type;
1432
1433 if (mode == SImode)
1434 return unsignedp ? d_uint_type : d_int_type;
1435
1436 if (mode == DImode)
1437 return unsignedp ? d_ulong_type : d_long_type;
1438
1439 if (mode == TYPE_MODE (d_cent_type))
1440 return unsignedp ? d_ucent_type : d_cent_type;
1441
1442 if (mode == TYPE_MODE (float_type_node))
1443 return float_type_node;
1444
1445 if (mode == TYPE_MODE (double_type_node))
1446 return double_type_node;
1447
1448 if (mode == TYPE_MODE (long_double_type_node))
1449 return long_double_type_node;
1450
1451 if (mode == TYPE_MODE (build_pointer_type (char8_type_node)))
1452 return build_pointer_type (char8_type_node);
1453
1454 if (mode == TYPE_MODE (build_pointer_type (d_int_type)))
1455 return build_pointer_type (d_int_type);
1456
1457 for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1458 {
1459 if (int_n_enabled_p[i] && mode == int_n_data[i].m)
1460 {
1461 if (unsignedp)
1462 return int_n_trees[i].unsigned_type;
1463 else
1464 return int_n_trees[i].signed_type;
1465 }
1466 }
1467
1468 if (COMPLEX_MODE_P (mode))
1469 {
1470 machine_mode inner_mode;
1471 tree inner_type;
1472
1473 if (mode == TYPE_MODE (complex_float_type_node))
1474 return complex_float_type_node;
1475 if (mode == TYPE_MODE (complex_double_type_node))
1476 return complex_double_type_node;
1477 if (mode == TYPE_MODE (complex_long_double_type_node))
1478 return complex_long_double_type_node;
1479
1480 inner_mode = (machine_mode) GET_MODE_INNER (mode);
1481 inner_type = d_type_for_mode (inner_mode, unsignedp);
1482 if (inner_type != NULL_TREE)
1483 return build_complex_type (inner_type);
1484 }
1485 else if (VECTOR_MODE_P (mode))
1486 {
1487 machine_mode inner_mode = (machine_mode) GET_MODE_INNER (mode);
1488 tree inner_type = d_type_for_mode (inner_mode, unsignedp);
1489 if (inner_type != NULL_TREE)
1490 return build_vector_type_for_mode (inner_type, mode);
1491 }
1492
1493 return 0;
1494 }
1495
1496 /* Implements the lang_hooks.types.type_for_size routine for language D. */
1497
1498 static tree
1499 d_type_for_size (unsigned bits, int unsignedp)
1500 {
1501 if (bits <= TYPE_PRECISION (d_byte_type))
1502 return unsignedp ? d_ubyte_type : d_byte_type;
1503
1504 if (bits <= TYPE_PRECISION (d_short_type))
1505 return unsignedp ? d_ushort_type : d_short_type;
1506
1507 if (bits <= TYPE_PRECISION (d_int_type))
1508 return unsignedp ? d_uint_type : d_int_type;
1509
1510 if (bits <= TYPE_PRECISION (d_long_type))
1511 return unsignedp ? d_ulong_type : d_long_type;
1512
1513 if (bits <= TYPE_PRECISION (d_cent_type))
1514 return unsignedp ? d_ucent_type : d_cent_type;
1515
1516 for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1517 {
1518 if (int_n_enabled_p[i] && bits == int_n_data[i].bitsize)
1519 {
1520 if (unsignedp)
1521 return int_n_trees[i].unsigned_type;
1522 else
1523 return int_n_trees[i].signed_type;
1524 }
1525 }
1526
1527 return 0;
1528 }
1529
1530 /* Implements the lang_hooks.types.type_promotes_to routine for language D. */
1531
1532 static tree
1533 d_type_promotes_to (tree type)
1534 {
1535 /* Promotions are only applied on unnamed function arguments for declarations
1536 with `extern(C)' or `extern(C++)' linkage. */
1537 if (cfun && DECL_LANG_FRONTEND (cfun->decl)
1538 && DECL_LANG_FRONTEND (cfun->decl)->resolvedLinkage () != LINK::d)
1539 {
1540 /* In [type/integer-promotions], integer promotions are conversions of the
1541 following types:
1542
1543 bool int
1544 byte int
1545 ubyte int
1546 short int
1547 ushort int
1548 char int
1549 wchar int
1550 dchar uint
1551
1552 If an enum has as a base type one of the types in the left column, it
1553 is converted to the type in the right column. */
1554 if (TREE_CODE (type) == ENUMERAL_TYPE && ENUM_IS_SCOPED (type))
1555 type = TREE_TYPE (type);
1556
1557 type = TYPE_MAIN_VARIANT (type);
1558
1559 /* Check for promotions of target-defined types first. */
1560 tree promoted_type = targetm.promoted_type (type);
1561 if (promoted_type)
1562 return promoted_type;
1563
1564 if (TREE_CODE (type) == BOOLEAN_TYPE)
1565 return d_int_type;
1566
1567 if (INTEGRAL_TYPE_P (type))
1568 {
1569 if (type == d_byte_type || type == d_ubyte_type
1570 || type == d_short_type || type == d_ushort_type
1571 || type == char8_type_node || type == char16_type_node)
1572 return d_int_type;
1573
1574 if (type == char32_type_node)
1575 return d_uint_type;
1576
1577 if (TYPE_PRECISION (type) < TYPE_PRECISION (d_int_type))
1578 return d_int_type;
1579 }
1580
1581 /* Float arguments are converted to doubles. */
1582 if (type == float_type_node)
1583 return double_type_node;
1584
1585 if (type == ifloat_type_node)
1586 return idouble_type_node;
1587 }
1588
1589 return type;
1590 }
1591
1592 /* Implements the lang_hooks.decls.global_bindings_p routine for language D.
1593 Return true if we are in the global binding level. */
1594
1595 static bool
1596 d_global_bindings_p (void)
1597 {
1598 return (current_binding_level == global_binding_level);
1599 }
1600
1601 /* Return global_context, but create it first if need be. */
1602
1603 static tree
1604 get_global_context (void)
1605 {
1606 if (!global_context)
1607 {
1608 global_context = build_translation_unit_decl (NULL_TREE);
1609 debug_hooks->register_main_translation_unit (global_context);
1610 }
1611
1612 return global_context;
1613 }
1614
1615 /* Implements the lang_hooks.decls.pushdecl routine for language D.
1616 Record DECL as belonging to the current lexical scope. */
1617
1618 tree
1619 d_pushdecl (tree decl)
1620 {
1621 /* Set the context of the decl. If current_function_decl did not help in
1622 determining the context, use global scope. */
1623 if (!DECL_CONTEXT (decl))
1624 {
1625 if (current_function_decl)
1626 DECL_CONTEXT (decl) = current_function_decl;
1627 else
1628 DECL_CONTEXT (decl) = get_global_context ();
1629 }
1630
1631 /* Put decls on list in reverse order. */
1632 if (TREE_STATIC (decl) || d_global_bindings_p ())
1633 vec_safe_push (global_declarations, decl);
1634 else
1635 {
1636 TREE_CHAIN (decl) = current_binding_level->names;
1637 current_binding_level->names = decl;
1638 }
1639
1640 return decl;
1641 }
1642
1643 /* Implements the lang_hooks.decls.getdecls routine for language D.
1644 Return the list of declarations of the current level. */
1645
1646 static tree
1647 d_getdecls (void)
1648 {
1649 if (current_binding_level)
1650 return current_binding_level->names;
1651
1652 return NULL_TREE;
1653 }
1654
1655
1656 /* Implements the lang_hooks.get_alias_set routine for language D.
1657 Get the alias set corresponding to type or expression T.
1658 Return -1 if we don't do anything special. */
1659
1660 static alias_set_type
1661 d_get_alias_set (tree)
1662 {
1663 /* For now in D, assume everything aliases everything else, until we define
1664 some solid rules backed by a specification. There are also some parts
1665 of code generation routines that don't adhere to C alias rules, such as
1666 build_vconvert. In any case, a lot of user code already assumes there
1667 is no strict aliasing and will break if we were to change that. */
1668 return 0;
1669 }
1670
1671 /* Implements the lang_hooks.types_compatible_p routine for language D.
1672 Compares two types for equivalence in the D programming language.
1673 This routine should only return 1 if it is sure, even though the frontend
1674 should have already ensured that all types are compatible before handing
1675 over the parsed ASTs to the code generator. */
1676
1677 static int
1678 d_types_compatible_p (tree x, tree y)
1679 {
1680 Type *tx = TYPE_LANG_FRONTEND (x);
1681 Type *ty = TYPE_LANG_FRONTEND (y);
1682
1683 /* Try validating the types in the frontend. */
1684 if (tx != NULL && ty != NULL)
1685 {
1686 /* Types are equivalent. */
1687 if (same_type_p (tx, ty))
1688 return true;
1689
1690 /* Type system allows implicit conversion between. */
1691 if (tx->implicitConvTo (ty) != MATCH::nomatch
1692 || ty->implicitConvTo (tx) != MATCH::nomatch)
1693 return true;
1694 }
1695
1696 /* Fallback on using type flags for comparison. E.g: all dynamic arrays
1697 are distinct types in D, but are VIEW_CONVERT compatible. */
1698 if (TREE_CODE (x) == RECORD_TYPE && TREE_CODE (y) == RECORD_TYPE)
1699 {
1700 if (TYPE_DYNAMIC_ARRAY (x) && TYPE_DYNAMIC_ARRAY (y))
1701 return true;
1702
1703 if (TYPE_DELEGATE (x) && TYPE_DELEGATE (y))
1704 return true;
1705
1706 if (TYPE_ASSOCIATIVE_ARRAY (x) && TYPE_ASSOCIATIVE_ARRAY (y))
1707 return true;
1708 }
1709
1710 return false;
1711 }
1712
1713 /* Implements the lang_hooks.finish_incomplete_decl routine for language D. */
1714
1715 static void
1716 d_finish_incomplete_decl (tree decl)
1717 {
1718 if (VAR_P (decl))
1719 {
1720 /* D allows zero-length declarations. Such a declaration ends up with
1721 DECL_SIZE (t) == NULL_TREE which is what the back-end function
1722 assembler_variable checks. This could change in later versions, or
1723 maybe all of these variables should be aliased to one symbol. */
1724 if (DECL_SIZE (decl) == 0)
1725 {
1726 DECL_SIZE (decl) = bitsize_zero_node;
1727 DECL_SIZE_UNIT (decl) = size_zero_node;
1728 }
1729 }
1730 }
1731
1732 /* Implements the lang_hooks.types.classify_record routine for language D.
1733 Return the true debug type for TYPE. */
1734
1735 static classify_record
1736 d_classify_record (tree type)
1737 {
1738 Type *t = TYPE_LANG_FRONTEND (type);
1739 TypeClass *tc = t ? t->isTypeClass () : NULL;
1740
1741 if (tc != NULL)
1742 {
1743 /* extern(C++) interfaces get emitted as classes. */
1744 if (tc->sym->isInterfaceDeclaration ()
1745 && !tc->sym->isCPPinterface ())
1746 return RECORD_IS_INTERFACE;
1747
1748 return RECORD_IS_CLASS;
1749 }
1750
1751 return RECORD_IS_STRUCT;
1752 }
1753
1754 /* Implements the lang_hooks.tree_size routine for language D.
1755 Determine the size of our tcc_constant or tcc_exceptional nodes. */
1756
1757 static size_t
1758 d_tree_size (tree_code code)
1759 {
1760 switch (code)
1761 {
1762 case FUNCFRAME_INFO:
1763 return sizeof (tree_frame_info);
1764
1765 default:
1766 gcc_unreachable ();
1767 }
1768 }
1769
1770 /* Implements the lang_hooks.print_xnode routine for language D. */
1771
1772 static void
1773 d_print_xnode (FILE *file, tree node, int indent)
1774 {
1775 switch (TREE_CODE (node))
1776 {
1777 case FUNCFRAME_INFO:
1778 print_node (file, "frame_type", FRAMEINFO_TYPE (node), indent + 4);
1779 break;
1780
1781 default:
1782 break;
1783 }
1784 }
1785
1786 /* Return which tree structure is used by NODE, or TS_D_GENERIC if NODE
1787 is one of the language-independent trees. */
1788
1789 d_tree_node_structure_enum
1790 d_tree_node_structure (lang_tree_node *t)
1791 {
1792 switch (TREE_CODE (&t->generic))
1793 {
1794 case IDENTIFIER_NODE:
1795 return TS_D_IDENTIFIER;
1796
1797 case FUNCFRAME_INFO:
1798 return TS_D_FRAMEINFO;
1799
1800 default:
1801 return TS_D_GENERIC;
1802 }
1803 }
1804
1805 /* Allocate and return a lang specific structure for the frontend type. */
1806
1807 struct lang_type *
1808 build_lang_type (Type *t)
1809 {
1810 struct lang_type *lt = ggc_cleared_alloc <struct lang_type> ();
1811 lt->type = t;
1812 return lt;
1813 }
1814
1815 /* Allocate and return a lang specific structure for the frontend decl. */
1816
1817 struct lang_decl *
1818 build_lang_decl (Declaration *d)
1819 {
1820 /* For compiler generated run-time typeinfo, a lang_decl is allocated even if
1821 there's no associated frontend symbol to refer to (yet). If the symbol
1822 appears later in the compilation, then the slot will be re-used. */
1823 if (d == NULL)
1824 return ggc_cleared_alloc <struct lang_decl> ();
1825
1826 struct lang_decl *ld = (d->csym) ? DECL_LANG_SPECIFIC (d->csym) : NULL;
1827 if (ld == NULL)
1828 ld = ggc_cleared_alloc <struct lang_decl> ();
1829
1830 if (ld->decl == NULL)
1831 ld->decl = d;
1832
1833 return ld;
1834 }
1835
1836 /* Implements the lang_hooks.dup_lang_specific_decl routine for language D.
1837 Replace the DECL_LANG_SPECIFIC field of NODE with a copy. */
1838
1839 static void
1840 d_dup_lang_specific_decl (tree node)
1841 {
1842 if (!DECL_LANG_SPECIFIC (node))
1843 return;
1844
1845 struct lang_decl *ld = ggc_alloc <struct lang_decl> ();
1846 memcpy (ld, DECL_LANG_SPECIFIC (node), sizeof (struct lang_decl));
1847 DECL_LANG_SPECIFIC (node) = ld;
1848 }
1849
1850 /* This preserves trees we create from the garbage collector. */
1851
1852 static GTY(()) tree d_keep_list = NULL_TREE;
1853
1854 void
1855 d_keep (tree t)
1856 {
1857 d_keep_list = tree_cons (NULL_TREE, t, d_keep_list);
1858 }
1859
1860 /* Implements the lang_hooks.eh_personality routine for language D.
1861 Return the GDC personality function decl. */
1862
1863 static GTY(()) tree d_eh_personality_decl;
1864
1865 static tree
1866 d_eh_personality (void)
1867 {
1868 if (!d_eh_personality_decl)
1869 d_eh_personality_decl = build_personality_function ("gdc");
1870
1871 return d_eh_personality_decl;
1872 }
1873
1874 /* Implements the lang_hooks.eh_runtime_type routine for language D. */
1875
1876 static tree
1877 d_build_eh_runtime_type (tree type)
1878 {
1879 Type *t = TYPE_LANG_FRONTEND (type);
1880 gcc_assert (t != NULL);
1881 t = t->toBasetype ();
1882
1883 ClassDeclaration *cd = t->isTypeClass ()->sym;
1884 tree decl;
1885
1886 if (cd->isCPPclass ())
1887 decl = get_cpp_typeinfo_decl (cd);
1888 else
1889 decl = get_classinfo_decl (cd);
1890
1891 return convert (ptr_type_node, build_address (decl));
1892 }
1893
1894 /* Implements the lang_hooks.enum_underlying_base_type routine for language D.
1895 Returns the underlying type of the given enumeration TYPE. */
1896
1897 static tree
1898 d_enum_underlying_base_type (const_tree type)
1899 {
1900 gcc_assert (TREE_CODE (type) == ENUMERAL_TYPE);
1901 return TREE_TYPE (type);
1902 }
1903
1904 /* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
1905 based on the list in SARIF v2.1.0 Appendix J. */
1906
1907 static const char *
1908 d_get_sarif_source_language (const char *)
1909 {
1910 return "d";
1911 }
1912
1913 /* Definitions for our language-specific hooks. */
1914
1915 #undef LANG_HOOKS_NAME
1916 #undef LANG_HOOKS_INIT
1917 #undef LANG_HOOKS_INIT_TS
1918 #undef LANG_HOOKS_INIT_OPTIONS
1919 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
1920 #undef LANG_HOOKS_OPTION_LANG_MASK
1921 #undef LANG_HOOKS_HANDLE_OPTION
1922 #undef LANG_HOOKS_POST_OPTIONS
1923 #undef LANG_HOOKS_PARSE_FILE
1924 #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
1925 #undef LANG_HOOKS_ATTRIBUTE_TABLE
1926 #undef LANG_HOOKS_GET_ALIAS_SET
1927 #undef LANG_HOOKS_TYPES_COMPATIBLE_P
1928 #undef LANG_HOOKS_BUILTIN_FUNCTION
1929 #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
1930 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
1931 #undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
1932 #undef LANG_HOOKS_GIMPLIFY_EXPR
1933 #undef LANG_HOOKS_CLASSIFY_RECORD
1934 #undef LANG_HOOKS_TREE_SIZE
1935 #undef LANG_HOOKS_PRINT_XNODE
1936 #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
1937 #undef LANG_HOOKS_EH_PERSONALITY
1938 #undef LANG_HOOKS_EH_RUNTIME_TYPE
1939 #undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
1940 #undef LANG_HOOKS_PUSHDECL
1941 #undef LANG_HOOKS_GETDECLS
1942 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
1943 #undef LANG_HOOKS_TYPE_FOR_MODE
1944 #undef LANG_HOOKS_TYPE_FOR_SIZE
1945 #undef LANG_HOOKS_TYPE_PROMOTES_TO
1946 #undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
1947
1948 #define LANG_HOOKS_NAME "GNU D"
1949 #define LANG_HOOKS_INIT d_init
1950 #define LANG_HOOKS_INIT_TS d_init_ts
1951 #define LANG_HOOKS_INIT_OPTIONS d_init_options
1952 #define LANG_HOOKS_INIT_OPTIONS_STRUCT d_init_options_struct
1953 #define LANG_HOOKS_OPTION_LANG_MASK d_option_lang_mask
1954 #define LANG_HOOKS_HANDLE_OPTION d_handle_option
1955 #define LANG_HOOKS_POST_OPTIONS d_post_options
1956 #define LANG_HOOKS_PARSE_FILE d_parse_file
1957 #define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE d_langhook_common_attribute_table
1958 #define LANG_HOOKS_ATTRIBUTE_TABLE d_langhook_attribute_table
1959 #define LANG_HOOKS_GET_ALIAS_SET d_get_alias_set
1960 #define LANG_HOOKS_TYPES_COMPATIBLE_P d_types_compatible_p
1961 #define LANG_HOOKS_BUILTIN_FUNCTION d_builtin_function
1962 #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE d_builtin_function_ext_scope
1963 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE d_register_builtin_type
1964 #define LANG_HOOKS_FINISH_INCOMPLETE_DECL d_finish_incomplete_decl
1965 #define LANG_HOOKS_GIMPLIFY_EXPR d_gimplify_expr
1966 #define LANG_HOOKS_CLASSIFY_RECORD d_classify_record
1967 #define LANG_HOOKS_TREE_SIZE d_tree_size
1968 #define LANG_HOOKS_PRINT_XNODE d_print_xnode
1969 #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL d_dup_lang_specific_decl
1970 #define LANG_HOOKS_EH_PERSONALITY d_eh_personality
1971 #define LANG_HOOKS_EH_RUNTIME_TYPE d_build_eh_runtime_type
1972 #define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE d_enum_underlying_base_type
1973 #define LANG_HOOKS_PUSHDECL d_pushdecl
1974 #define LANG_HOOKS_GETDECLS d_getdecls
1975 #define LANG_HOOKS_GLOBAL_BINDINGS_P d_global_bindings_p
1976 #define LANG_HOOKS_TYPE_FOR_MODE d_type_for_mode
1977 #define LANG_HOOKS_TYPE_FOR_SIZE d_type_for_size
1978 #define LANG_HOOKS_TYPE_PROMOTES_TO d_type_promotes_to
1979 #define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE d_get_sarif_source_language
1980
1981 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1982
1983 #include "gt-d-d-lang.h"
1984 #include "gtype-d.h"