]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/d-lang.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / d / d-lang.cc
1 /* d-lang.cc -- Language-dependent hooks for D.
2 Copyright (C) 2006-2024 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.compileEnv.vendor = lang_hooks.name;
297 global.params.argv0 = xstrdup (decoded_options[0].arg);
298
299 /* Default extern(C++) mangling to C++17. */
300 global.params.cplusplus = CppStdRevisionCpp17;
301
302 /* Warnings and deprecations are disabled by default. */
303 global.params.useDeprecated = DIAGNOSTICinform;
304 global.params.warnings = DIAGNOSTICoff;
305 global.params.v.errorLimit = flag_max_errors;
306 global.params.v.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 DebugCondition::addGlobalIdent (arg);
462 break;
463 }
464
465 error ("bad argument for %<-fdebug%>: %qs", arg);
466 break;
467
468 case OPT_fdoc:
469 global.params.ddoc.doOutput = value;
470 break;
471
472 case OPT_fdoc_dir_:
473 global.params.ddoc.doOutput = true;
474 global.params.ddoc.dir = arg;
475 break;
476
477 case OPT_fdoc_file_:
478 global.params.ddoc.doOutput = true;
479 global.params.ddoc.name = arg;
480 break;
481
482 case OPT_fdoc_inc_:
483 global.params.ddoc.files.push (arg);
484 break;
485
486 case OPT_fdruntime:
487 global.params.betterC = !value;
488 break;
489
490 case OPT_fdump_c___spec_:
491 global.params.cxxhdr.doOutput = true;
492 global.params.cxxhdr.name = arg;
493 break;
494
495 case OPT_fdump_c___spec_verbose:
496 global.params.cxxhdr.fullOutput = true;
497 break;
498
499 case OPT_fdump_d_original:
500 global.params.vcg_ast = value;
501 break;
502
503 case OPT_fexceptions:
504 global.params.useExceptions = value;
505 break;
506
507 case OPT_fextern_std_:
508 switch (value)
509 {
510 case CppStdRevisionCpp98:
511 case CppStdRevisionCpp11:
512 case CppStdRevisionCpp14:
513 case CppStdRevisionCpp17:
514 case CppStdRevisionCpp20:
515 global.params.cplusplus = (CppStdRevision) value;
516 break;
517
518 default:
519 error ("bad argument for %<-fextern-std%>: %qs", arg);
520 }
521 break;
522
523 case OPT_fignore_unknown_pragmas:
524 global.params.ignoreUnsupportedPragmas = value;
525 break;
526
527 case OPT_finvariants:
528 global.params.useInvariants = value ? CHECKENABLEon : CHECKENABLEoff;
529 break;
530
531 case OPT_fmain:
532 global.params.addMain = value;
533 break;
534
535 case OPT_fmodule_file_:
536 global.params.modFileAliasStrings.push (arg);
537 if (!strchr (arg, '='))
538 error ("bad argument for %<-fmodule-file%>: %qs", arg);
539 break;
540
541 case OPT_fmoduleinfo:
542 global.params.useModuleInfo = value;
543 break;
544
545 case OPT_fonly_:
546 d_option.fonly = arg;
547 break;
548
549 case OPT_fpostconditions:
550 global.params.useOut = value ? CHECKENABLEon : CHECKENABLEoff;
551 break;
552
553 case OPT_fpreconditions:
554 global.params.useIn = value ? CHECKENABLEon : CHECKENABLEoff;
555 break;
556
557 case OPT_fpreview_all:
558 global.params.ehnogc = value;
559 global.params.useDIP1000 = FeatureState::enabled;
560 global.params.useDIP1021 = value;
561 global.params.bitfields = value;
562 global.params.dtorFields = FeatureState::enabled;
563 global.params.fieldwise = FeatureState::enabled;
564 global.params.fixAliasThis = value;
565 global.params.previewIn = value;
566 global.params.fix16997 = value;
567 global.params.noSharedAccess = FeatureState::enabled;
568 global.params.rvalueRefParam = FeatureState::enabled;
569 global.params.inclusiveInContracts = value;
570 global.params.systemVariables = FeatureState::enabled;
571 global.params.fixImmutableConv = value;
572 break;
573
574 case OPT_fpreview_bitfields:
575 global.params.bitfields = value;
576 break;
577
578 case OPT_fpreview_dip1000:
579 global.params.useDIP1000 = FeatureState::enabled;
580 break;
581
582 case OPT_fpreview_dip1008:
583 global.params.ehnogc = value;
584 break;
585
586 case OPT_fpreview_dip1021:
587 global.params.useDIP1021 = value;
588 break;
589
590 case OPT_fpreview_dtorfields:
591 global.params.dtorFields = FeatureState::enabled;
592 break;
593
594 case OPT_fpreview_fieldwise:
595 global.params.fieldwise = FeatureState::enabled;
596 break;
597
598 case OPT_fpreview_fixaliasthis:
599 global.params.fixAliasThis = value;
600 break;
601
602 case OPT_fpreview_fiximmutableconv:
603 global.params.fixImmutableConv = value;
604 break;
605
606 case OPT_fpreview_in:
607 global.params.previewIn = value;
608 break;
609
610 case OPT_fpreview_inclusiveincontracts:
611 global.params.inclusiveInContracts = value;
612 break;
613
614 case OPT_fpreview_nosharedaccess:
615 global.params.noSharedAccess = FeatureState::enabled;
616 break;
617
618 case OPT_fpreview_rvaluerefparam:
619 global.params.rvalueRefParam = FeatureState::enabled;
620 break;
621
622 case OPT_fpreview_systemvariables:
623 global.params.systemVariables = FeatureState::enabled;
624 break;
625
626 case OPT_frelease:
627 global.params.release = value;
628 break;
629
630 case OPT_frevert_all:
631 global.params.useDIP1000 = FeatureState::disabled;
632 global.params.dtorFields = FeatureState::disabled;
633 global.params.fix16997 = !value;
634 break;
635
636 case OPT_frevert_dip1000:
637 global.params.useDIP1000 = FeatureState::disabled;
638 break;
639
640 case OPT_frevert_dtorfields:
641 global.params.dtorFields = FeatureState::disabled;
642 break;
643
644 case OPT_frevert_intpromote:
645 global.params.fix16997 = !value;
646 break;
647
648 case OPT_frtti:
649 global.params.useTypeInfo = value;
650 break;
651
652 case OPT_fsave_mixins_:
653 global.params.mixinOut.doOutput = true;
654 global.params.mixinOut.name = arg;
655 global.params.mixinOut.buffer = d_gc_malloc<OutBuffer> ();
656 break;
657
658 case OPT_fswitch_errors:
659 global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
660 break;
661
662 case OPT_ftransition_all:
663 global.params.v.field = value;
664 global.params.v.gc = value;
665 global.params.v.vin = value;
666 global.params.v.tls = value;
667 break;
668
669 case OPT_ftransition_field:
670 global.params.v.field = value;
671 break;
672
673 case OPT_ftransition_in:
674 global.params.v.vin = value;
675 break;
676
677 case OPT_ftransition_nogc:
678 global.params.v.gc = value;
679 break;
680
681 case OPT_ftransition_templates:
682 global.params.v.templates = value;
683 break;
684
685 case OPT_ftransition_tls:
686 global.params.v.tls = value;
687 break;
688
689 case OPT_funittest:
690 global.params.useUnitTests = value;
691 break;
692
693 case OPT_fversion_:
694 if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
695 {
696 VersionCondition::addGlobalIdent (arg);
697 break;
698 }
699
700 error ("bad argument for %<-fversion%>: %qs", arg);
701 break;
702
703 case OPT_H:
704 global.params.dihdr.doOutput = true;
705 break;
706
707 case OPT_Hd:
708 global.params.dihdr.doOutput = true;
709 global.params.dihdr.dir = arg;
710 break;
711
712 case OPT_Hf:
713 global.params.dihdr.doOutput = true;
714 global.params.dihdr.name = arg;
715 break;
716
717 case OPT_imultilib:
718 d_option.multilib = arg;
719 break;
720
721 case OPT_iprefix:
722 d_option.prefix = arg;
723 break;
724
725 case OPT_I:
726 global.params.imppath->push (arg);
727 break;
728
729 case OPT_J:
730 global.params.fileImppath->push (arg);
731 break;
732
733 case OPT_MM:
734 d_option.deps_skip_system = true;
735 /* Fall through. */
736
737 case OPT_M:
738 d_option.deps = true;
739 break;
740
741 case OPT_MMD:
742 d_option.deps_skip_system = true;
743 /* Fall through. */
744
745 case OPT_MD:
746 d_option.deps = true;
747 d_option.deps_filename = arg;
748 break;
749
750 case OPT_MF:
751 /* If specified multiple times, last one wins. */
752 d_option.deps_filename_user = arg;
753 break;
754
755 case OPT_MP:
756 d_option.deps_phony = true;
757 break;
758
759 case OPT_MQ:
760 deps_add_target (arg, true);
761 break;
762
763 case OPT_MT:
764 deps_add_target (arg, false);
765 break;
766
767 case OPT_nostdinc:
768 d_option.stdinc = false;
769 break;
770
771 case OPT_v:
772 global.params.v.verbose = value;
773 break;
774
775 case OPT_Wall:
776 if (value)
777 global.params.warnings = DIAGNOSTICinform;
778 break;
779
780 case OPT_Wdeprecated:
781 global.params.useDeprecated = value ? DIAGNOSTICinform : DIAGNOSTICoff;
782 break;
783
784 case OPT_Werror:
785 if (value)
786 global.params.warnings = DIAGNOSTICerror;
787 break;
788
789 case OPT_Wspeculative:
790 if (value)
791 global.params.v.showGaggedErrors = 1;
792 break;
793
794 case OPT_Xf:
795 global.params.json.name = arg;
796 /* Fall through. */
797
798 case OPT_X:
799 global.params.json.doOutput = true;
800 break;
801
802 default:
803 break;
804 }
805
806 D_handle_option_auto (&global_options, &global_options_set,
807 scode, arg, value,
808 d_option_lang_mask (), kind,
809 loc, handlers, global_dc);
810
811 return result;
812 }
813
814 /* Implements the lang_hooks.post_options routine for language D.
815 Deal with any options that imply the turning on/off of features.
816 FN is the main input filename passed on the command line. */
817
818 static bool
819 d_post_options (const char ** fn)
820 {
821 /* Verify the input file name. */
822 const char *filename = *fn;
823 if (!filename || strcmp (filename, "-") == 0)
824 filename = "";
825
826 /* The front end considers the first input file to be the main one. */
827 *fn = filename;
828
829 /* Release mode doesn't turn off bounds checking for safe functions. */
830 if (global.params.useArrayBounds == CHECKENABLEdefault)
831 {
832 global.params.useArrayBounds = global.params.release
833 ? CHECKENABLEsafeonly : CHECKENABLEon;
834 }
835
836 /* Assert code is generated if unittests are being compiled also, even if
837 release mode is turned on. */
838 if (global.params.useAssert == CHECKENABLEdefault)
839 {
840 if (global.params.useUnitTests || !global.params.release)
841 global.params.useAssert = CHECKENABLEon;
842 else
843 global.params.useAssert = CHECKENABLEoff;
844 }
845
846 /* Checks for switches without a default are turned off in release mode. */
847 if (global.params.useSwitchError == CHECKENABLEdefault)
848 {
849 global.params.useSwitchError = global.params.release
850 ? CHECKENABLEoff : CHECKENABLEon;
851 }
852
853 /* Contracts are turned off in release mode. */
854 if (global.params.useInvariants == CHECKENABLEdefault)
855 {
856 global.params.useInvariants = global.params.release
857 ? CHECKENABLEoff : CHECKENABLEon;
858 }
859
860 if (global.params.useIn == CHECKENABLEdefault)
861 {
862 global.params.useIn = global.params.release
863 ? CHECKENABLEoff : CHECKENABLEon;
864 }
865
866 if (global.params.useOut == CHECKENABLEdefault)
867 {
868 global.params.useOut = global.params.release
869 ? CHECKENABLEoff : CHECKENABLEon;
870 }
871
872 /* When not linking against D runtime, turn off all code generation that
873 would otherwise reference it. */
874 if (global.params.betterC)
875 {
876 if (!OPTION_SET_P (flag_moduleinfo))
877 global.params.useModuleInfo = false;
878
879 /* Ensure that the front-end options are in sync with the `-frtti' and
880 `-fexceptions' flags. */
881 if (!OPTION_SET_P (flag_rtti))
882 {
883 global.params.useTypeInfo = false;
884 flag_rtti = false;
885 }
886
887 if (!OPTION_SET_P (flag_exceptions))
888 {
889 global.params.useExceptions = false;
890 flag_exceptions = false;
891 }
892
893 global.params.useGC = false;
894 global.params.checkAction = CHECKACTION_C;
895 }
896
897 /* Enabling DIP1021 implies DIP1000. */
898 if (global.params.useDIP1021)
899 global.params.useDIP1000 = FeatureState::enabled;
900
901 /* Keep in sync with existing -fbounds-check flag. */
902 flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
903
904 /* Turn off partitioning unless it was explicitly requested, as it doesn't
905 work with D exception chaining, where EH handler uses LSDA to determine
906 whether two thrown exception are in the same context. */
907 if (!OPTION_SET_P (flag_reorder_blocks_and_partition))
908 global_options.x_flag_reorder_blocks_and_partition = 0;
909
910 /* Error about use of deprecated features. */
911 if (global.params.useDeprecated == DIAGNOSTICinform
912 && global.params.warnings == DIAGNOSTICerror)
913 global.params.useDeprecated = DIAGNOSTICerror;
914
915 if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
916 flag_excess_precision = EXCESS_PRECISION_STANDARD;
917
918 global.params.useInline = flag_inline_functions;
919
920 /* Make -fmax-errors visible to frontend's diagnostic machinery. */
921 if (OPTION_SET_P (flag_max_errors))
922 global.params.v.errorLimit = flag_max_errors;
923
924 global.params.v.showColumns = flag_show_column;
925 global.params.v.printErrorContext = flag_diagnostics_show_caret;
926
927 /* Keep the front-end location type in sync with params. */
928 Loc::set (global.params.v.showColumns, global.params.v.messageStyle);
929
930 if (global.params.useInline)
931 global.params.dihdr.fullOutput = true;
932
933 global.params.obj = !flag_syntax_only;
934
935 /* The front-end parser only has access to `compileEnv', synchronize its
936 fields with params. */
937 global.compileEnv.previewIn = global.params.previewIn;
938 global.compileEnv.ddocOutput = global.params.ddoc.doOutput;
939
940 if (warn_return_type == -1)
941 warn_return_type = 0;
942
943 return false;
944 }
945
946 /* Add the module M to the list of modules that may declare GCC builtins.
947 These are scanned after first semantic and before codegen passes.
948 See d_maybe_set_builtin() for the implementation. */
949
950 void
951 d_add_builtin_module (Module *m)
952 {
953 builtin_modules.push (m);
954 }
955
956 /* Writes to FILENAME. DATA is the full content of the file to be written. */
957
958 static void
959 d_write_file (const char *filename, const char *data)
960 {
961 FILE *stream;
962
963 if (filename && (filename[0] != '-' || filename[1] != '\0'))
964 stream = fopen (filename, "w");
965 else
966 stream = stdout;
967
968 if (!stream)
969 {
970 error ("unable to open %s for writing: %m", filename);
971 return;
972 }
973
974 fprintf (stream, "%s", data);
975
976 if (stream != stdout && (ferror (stream) || fclose (stream)))
977 error ("writing output file %s: %m", filename);
978 }
979
980 /* Read ddoc macro files named by the DDOCFILES, then write the concatenated
981 the contents into DDOCBUF. */
982
983 static void
984 d_read_ddoc_files (Strings &ddocfiles, OutBuffer &ddocbuf)
985 {
986 if (ddocbuf.length ())
987 return;
988
989 for (size_t i = 0; i < ddocfiles.length; i++)
990 {
991 int fd = open (ddocfiles[i], O_RDONLY);
992 bool ok = false;
993 struct stat buf;
994
995 if (fd == -1 || fstat (fd, &buf))
996 {
997 error ("unable to open %s for reading: %m", ddocfiles[i]);
998 continue;
999 }
1000
1001 /* Check we've not been given a directory, or a file bigger than 4GB. */
1002 if (S_ISDIR (buf.st_mode))
1003 errno = ENOENT;
1004 else if (buf.st_size != unsigned (buf.st_size))
1005 errno = EMFILE;
1006 else
1007 {
1008 unsigned size = unsigned (buf.st_size);
1009 char *buffer = (char *) xmalloc (size);
1010
1011 if (read (fd, buffer, size) == ssize_t (size))
1012 {
1013 ddocbuf.write (buffer, size);
1014 ok = true;
1015 }
1016
1017 free (buffer);
1018 }
1019
1020 close (fd);
1021 if (!ok)
1022 fatal_error (input_location, "reading ddoc file %s: %m", ddocfiles[i]);
1023 }
1024 }
1025
1026 static void
1027 d_generate_ddoc_file (Module *m, OutBuffer &ddocbuf)
1028 {
1029 input_location = make_location_t (m->loc);
1030
1031 d_read_ddoc_files (global.params.ddoc.files, ddocbuf);
1032
1033 OutBuffer ddocbuf_out;
1034 gendocfile (m, ddocbuf.peekChars (), ddocbuf.length (), global.datetime,
1035 global.errorSink, ddocbuf_out);
1036
1037 d_write_file (m->docfile.toChars (), ddocbuf_out.peekChars ());
1038 }
1039
1040 /* Implements the lang_hooks.parse_file routine for language D. */
1041
1042 static void
1043 d_parse_file (void)
1044 {
1045 if (global.params.v.verbose)
1046 {
1047 message ("binary %s", global.params.argv0.ptr);
1048 message ("version %s", global.versionChars ());
1049
1050 if (global.versionids)
1051 {
1052 obstack buffer;
1053 gcc_obstack_init (&buffer);
1054 obstack_grow (&buffer, "predefs ", 9);
1055 for (size_t i = 0; i < global.versionids->length; i++)
1056 {
1057 Identifier *id = (*global.versionids)[i];
1058 const char *str = id->toChars ();
1059 obstack_1grow (&buffer, ' ');
1060 obstack_grow (&buffer, str, strlen (str));
1061 }
1062
1063 obstack_1grow (&buffer, '\0');
1064 message ("%s", (char *) obstack_finish (&buffer));
1065 }
1066 }
1067
1068 /* Start the main input file, if the debug writer wants it. */
1069 if (debug_hooks->start_end_main_source_file)
1070 debug_hooks->start_source_file (0, main_input_filename);
1071
1072 /* Create Module's for all sources we will load. */
1073 Modules modules;
1074 modules.reserve (num_in_fnames);
1075
1076 /* Buffer for contents of .ddoc files. */
1077 OutBuffer ddocbuf;
1078
1079 /* In this mode, the first file name is supposed to be a duplicate
1080 of one of the input files. */
1081 if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
1082 error ("%<-fonly=%> argument is different from first input file name");
1083
1084 for (size_t i = 0; i < num_in_fnames; i++)
1085 {
1086 if (strcmp (in_fnames[i], "-") == 0)
1087 {
1088 /* Load the entire contents of stdin into memory. 8 kilobytes should
1089 be a good enough initial size, but double on each iteration.
1090 16 bytes are added for the final '\n' and 15 bytes of padding. */
1091 ssize_t size = 8 * 1024;
1092 uchar *buffer = XNEWVEC (uchar, size + 16);
1093 ssize_t len = 0;
1094 ssize_t count;
1095
1096 while ((count = read (STDIN_FILENO, buffer + len, size - len)) > 0)
1097 {
1098 len += count;
1099 if (len == size)
1100 {
1101 size *= 2;
1102 buffer = XRESIZEVEC (uchar, buffer, size + 16);
1103 }
1104 }
1105
1106 if (count < 0)
1107 {
1108 error (Loc ("stdin", 0, 0), "%s", xstrerror (errno));
1109 free (buffer);
1110 continue;
1111 }
1112
1113 /* Handling stdin, generate a unique name for the module. */
1114 Module *m = Module::create (in_fnames[i],
1115 Identifier::idPool ("__stdin"),
1116 global.params.ddoc.doOutput,
1117 global.params.dihdr.doOutput);
1118 modules.push (m);
1119
1120 /* Zero the padding past the end of the buffer so the D lexer has a
1121 sentinel. The lexer only reads up to 4 bytes at a time. */
1122 memset (buffer + len, '\0', 16);
1123
1124 /* Overwrite the source file for the module, the one created by
1125 Module::create would have a forced a `.d' suffix. */
1126 m->src.length = len;
1127 m->src.ptr = buffer;
1128 }
1129 else
1130 {
1131 /* Handling a D source file, strip off the path and extension. */
1132 const char *basename = FileName::name (in_fnames[i]);
1133 const char *name = FileName::removeExt (basename);
1134
1135 Module *m = Module::create (in_fnames[i], Identifier::idPool (name),
1136 global.params.ddoc.doOutput,
1137 global.params.dihdr.doOutput);
1138 modules.push (m);
1139 FileName::free (name);
1140 }
1141 }
1142
1143 /* Read all D source files. */
1144 for (size_t i = 0; i < modules.length; i++)
1145 {
1146 Module *m = modules[i];
1147 m->read (Loc ());
1148 }
1149
1150 /* Parse all D source files. */
1151 for (size_t i = 0; i < modules.length; i++)
1152 {
1153 Module *m = modules[i];
1154
1155 if (global.params.v.verbose)
1156 message ("parse %s", m->toChars ());
1157
1158 if (!Module::rootModule)
1159 Module::rootModule = m;
1160
1161 m->importedFrom = m;
1162 m->parse ();
1163
1164 if (m->filetype == FileType::ddoc)
1165 {
1166 d_generate_ddoc_file (m, ddocbuf);
1167
1168 /* Remove M from list of modules. */
1169 modules.remove (i);
1170 i--;
1171 }
1172 }
1173
1174 /* Load the module containing D main. */
1175 Module *main_module = NULL;
1176 if (global.params.addMain)
1177 {
1178 unsigned errors = global.startGagging ();
1179 main_module = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
1180
1181 if (!global.endGagging (errors))
1182 {
1183 main_module->importedFrom = main_module;
1184 modules.push (main_module);
1185 }
1186 }
1187
1188 /* If an error occurs later during compilation, remember that we generated
1189 the headers, so that they can be removed before exit. */
1190 bool dump_headers = false;
1191
1192 if (global.errors)
1193 goto had_errors;
1194
1195 if (global.params.dihdr.doOutput)
1196 {
1197 /* Generate 'header' import files. Since 'header' import files must be
1198 independent of command line switches and what else is imported, they
1199 are generated before any semantic analysis. */
1200 for (size_t i = 0; i < modules.length; i++)
1201 {
1202 Module *m = modules[i];
1203 if (m->filetype == FileType::dhdr
1204 || (d_option.fonly && m != Module::rootModule))
1205 continue;
1206
1207 if (global.params.v.verbose)
1208 message ("import %s", m->toChars ());
1209
1210 OutBuffer buf;
1211 genhdrfile (m, buf);
1212 d_write_file (m->hdrfile.toChars (), buf.peekChars ());
1213 }
1214
1215 dump_headers = true;
1216 }
1217
1218 if (global.errors)
1219 goto had_errors;
1220
1221 /* Load all unconditional imports for better symbol resolving. */
1222 for (size_t i = 0; i < modules.length; i++)
1223 {
1224 Module *m = modules[i];
1225
1226 if (global.params.v.verbose)
1227 message ("importall %s", m->toChars ());
1228
1229 m->importAll (NULL);
1230 }
1231
1232 if (global.errors)
1233 goto had_errors;
1234
1235 /* Do semantic analysis. */
1236 doing_semantic_analysis_p = true;
1237
1238 for (size_t i = 0; i < modules.length; i++)
1239 {
1240 Module *m = modules[i];
1241
1242 /* If this is the `__main` module, check that `D main` hasn't already
1243 been declared in user code before running semantic on it. */
1244 if (m == main_module && global.hasMainFunction)
1245 {
1246 modules.remove (i);
1247 continue;
1248 }
1249
1250 if (global.params.v.verbose)
1251 message ("semantic %s", m->toChars ());
1252
1253 dsymbolSemantic (m, NULL);
1254 }
1255
1256 /* Do deferred semantic analysis. */
1257 Module::runDeferredSemantic ();
1258
1259 if (Module::deferred.length)
1260 {
1261 for (size_t i = 0; i < Module::deferred.length; i++)
1262 {
1263 Dsymbol *sd = Module::deferred[i];
1264 error_at (make_location_t (sd->loc),
1265 "unable to resolve forward reference in definition");
1266 }
1267 }
1268
1269 /* Process all built-in modules or functions now for CTFE. */
1270 while (builtin_modules.length != 0)
1271 {
1272 Module *m = builtin_modules.pop ();
1273 d_maybe_set_builtin (m);
1274 }
1275
1276 /* Do pass 2 semantic analysis. */
1277 for (size_t i = 0; i < modules.length; i++)
1278 {
1279 Module *m = modules[i];
1280
1281 if (global.params.v.verbose)
1282 message ("semantic2 %s", m->toChars ());
1283
1284 semantic2 (m, NULL);
1285 }
1286
1287 Module::runDeferredSemantic2 ();
1288
1289 if (global.errors)
1290 goto had_errors;
1291
1292 /* Do pass 3 semantic analysis. */
1293 for (size_t i = 0; i < modules.length; i++)
1294 {
1295 Module *m = modules[i];
1296
1297 if (global.params.v.verbose)
1298 message ("semantic3 %s", m->toChars ());
1299
1300 semantic3 (m, NULL);
1301 }
1302
1303 Module::runDeferredSemantic3 ();
1304
1305 /* Check again, incase semantic3 pass loaded any more modules. */
1306 while (builtin_modules.length != 0)
1307 {
1308 Module *m = builtin_modules.pop ();
1309 d_maybe_set_builtin (m);
1310 }
1311
1312 /* Do not attempt to generate output files if errors or warnings occurred. */
1313 if (global.errors || global.warnings)
1314 goto had_errors;
1315
1316 /* Generate output files. */
1317 doing_semantic_analysis_p = false;
1318
1319 if (Module::rootModule)
1320 {
1321 /* Declare the name of the root module as the first global name in order
1322 to make the middle-end fully deterministic. */
1323 OutBuffer buf;
1324 mangleToBuffer (Module::rootModule, buf);
1325 first_global_object_name = buf.extractChars ();
1326 }
1327
1328 /* Make dependencies. */
1329 if (d_option.deps)
1330 {
1331 obstack buffer;
1332 gcc_obstack_init (&buffer);
1333
1334 for (size_t i = 0; i < modules.length; i++)
1335 deps_write (modules[i], &buffer);
1336
1337 /* -MF <arg> overrides -M[M]D. */
1338 if (d_option.deps_filename_user)
1339 d_option.deps_filename = d_option.deps_filename_user;
1340
1341 d_write_file (d_option.deps_filename,
1342 (char *) obstack_finish (&buffer));
1343 }
1344
1345 if (global.params.v.templates)
1346 printTemplateStats ();
1347
1348 /* Generate JSON files. */
1349 if (global.params.json.doOutput)
1350 {
1351 OutBuffer buf;
1352 json_generate (modules, buf);
1353 d_write_file (global.params.json.name.ptr, buf.peekChars ());
1354 }
1355
1356 /* Generate Ddoc files. */
1357 if (global.params.ddoc.doOutput && !global.errors && !errorcount)
1358 {
1359 for (size_t i = 0; i < modules.length; i++)
1360 {
1361 Module *m = modules[i];
1362 d_generate_ddoc_file (m, ddocbuf);
1363 }
1364 }
1365
1366 /* Handle -fdump-d-original. */
1367 if (global.params.vcg_ast)
1368 {
1369 for (size_t i = 0; i < modules.length; i++)
1370 {
1371 Module *m = modules[i];
1372 OutBuffer buf;
1373 buf.doindent = 1;
1374
1375 moduleToBuffer (buf, m);
1376 message ("%s", buf.peekChars ());
1377 }
1378 }
1379
1380 /* Generate C++ header files. */
1381 if (global.params.cxxhdr.doOutput)
1382 genCppHdrFiles (modules);
1383
1384 if (global.errors)
1385 goto had_errors;
1386
1387 for (size_t i = 0; i < modules.length; i++)
1388 {
1389 Module *m = modules[i];
1390
1391 /* Skip generating code for header files, or when the module wasn't
1392 specified by `-fonly=`. */
1393 if ((m->filetype == FileType::dhdr && m != main_module)
1394 || (d_option.fonly && m != Module::rootModule))
1395 continue;
1396
1397 if (global.params.v.verbose)
1398 message ("code %s", m->toChars ());
1399
1400 if (!flag_syntax_only)
1401 build_decl_tree (m);
1402 }
1403
1404 /* And end the main input file, if the debug writer wants it. */
1405 if (debug_hooks->start_end_main_source_file)
1406 debug_hooks->end_source_file (0);
1407
1408 had_errors:
1409 /* Add the D frontend error count to the GCC error count to correctly
1410 exit with an error status. */
1411 errorcount += (global.errors + global.warnings);
1412
1413 /* We want to write the mixin expansion file also on error. */
1414 if (global.params.mixinOut.doOutput)
1415 {
1416 d_write_file (global.params.mixinOut.name.ptr,
1417 global.params.mixinOut.buffer->peekChars ());
1418 }
1419
1420 /* Remove generated .di files on error. */
1421 if (errorcount && dump_headers)
1422 {
1423 for (size_t i = 0; i < modules.length; i++)
1424 {
1425 Module *m = modules[i];
1426 if (m->filetype == FileType::dhdr
1427 || (d_option.fonly && m != Module::rootModule))
1428 continue;
1429
1430 remove (m->hdrfile.toChars ());
1431 }
1432 }
1433
1434 /* Write out globals. */
1435 d_finish_compilation (vec_safe_address (global_declarations),
1436 vec_safe_length (global_declarations));
1437 }
1438
1439 /* Implements the lang_hooks.types.type_for_mode routine for language D. */
1440
1441 static tree
1442 d_type_for_mode (machine_mode mode, int unsignedp)
1443 {
1444 if (mode == QImode)
1445 return unsignedp ? d_ubyte_type : d_byte_type;
1446
1447 if (mode == HImode)
1448 return unsignedp ? d_ushort_type : d_short_type;
1449
1450 if (mode == SImode)
1451 return unsignedp ? d_uint_type : d_int_type;
1452
1453 if (mode == DImode)
1454 return unsignedp ? d_ulong_type : d_long_type;
1455
1456 if (mode == TYPE_MODE (d_cent_type))
1457 return unsignedp ? d_ucent_type : d_cent_type;
1458
1459 if (mode == TYPE_MODE (float_type_node))
1460 return float_type_node;
1461
1462 if (mode == TYPE_MODE (double_type_node))
1463 return double_type_node;
1464
1465 if (mode == TYPE_MODE (long_double_type_node))
1466 return long_double_type_node;
1467
1468 if (mode == TYPE_MODE (build_pointer_type (char8_type_node)))
1469 return build_pointer_type (char8_type_node);
1470
1471 if (mode == TYPE_MODE (build_pointer_type (d_int_type)))
1472 return build_pointer_type (d_int_type);
1473
1474 for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1475 {
1476 if (int_n_enabled_p[i] && mode == int_n_data[i].m)
1477 {
1478 if (unsignedp)
1479 return int_n_trees[i].unsigned_type;
1480 else
1481 return int_n_trees[i].signed_type;
1482 }
1483 }
1484
1485 if (COMPLEX_MODE_P (mode))
1486 {
1487 machine_mode inner_mode;
1488 tree inner_type;
1489
1490 if (mode == TYPE_MODE (complex_float_type_node))
1491 return complex_float_type_node;
1492 if (mode == TYPE_MODE (complex_double_type_node))
1493 return complex_double_type_node;
1494 if (mode == TYPE_MODE (complex_long_double_type_node))
1495 return complex_long_double_type_node;
1496
1497 inner_mode = (machine_mode) GET_MODE_INNER (mode);
1498 inner_type = d_type_for_mode (inner_mode, unsignedp);
1499 if (inner_type != NULL_TREE)
1500 return build_complex_type (inner_type);
1501 }
1502 else if (VECTOR_MODE_P (mode))
1503 {
1504 machine_mode inner_mode = (machine_mode) GET_MODE_INNER (mode);
1505 tree inner_type = d_type_for_mode (inner_mode, unsignedp);
1506 if (inner_type != NULL_TREE)
1507 return build_vector_type_for_mode (inner_type, mode);
1508 }
1509
1510 return 0;
1511 }
1512
1513 /* Implements the lang_hooks.types.type_for_size routine for language D. */
1514
1515 static tree
1516 d_type_for_size (unsigned bits, int unsignedp)
1517 {
1518 if (bits <= TYPE_PRECISION (d_byte_type))
1519 return unsignedp ? d_ubyte_type : d_byte_type;
1520
1521 if (bits <= TYPE_PRECISION (d_short_type))
1522 return unsignedp ? d_ushort_type : d_short_type;
1523
1524 if (bits <= TYPE_PRECISION (d_int_type))
1525 return unsignedp ? d_uint_type : d_int_type;
1526
1527 if (bits <= TYPE_PRECISION (d_long_type))
1528 return unsignedp ? d_ulong_type : d_long_type;
1529
1530 if (bits <= TYPE_PRECISION (d_cent_type))
1531 return unsignedp ? d_ucent_type : d_cent_type;
1532
1533 for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1534 {
1535 if (int_n_enabled_p[i] && bits == int_n_data[i].bitsize)
1536 {
1537 if (unsignedp)
1538 return int_n_trees[i].unsigned_type;
1539 else
1540 return int_n_trees[i].signed_type;
1541 }
1542 }
1543
1544 return 0;
1545 }
1546
1547 /* Implements the lang_hooks.types.type_promotes_to routine for language D. */
1548
1549 static tree
1550 d_type_promotes_to (tree type)
1551 {
1552 /* Promotions are only applied on unnamed function arguments for declarations
1553 with `extern(C)' or `extern(C++)' linkage. */
1554 if (cfun && DECL_LANG_FRONTEND (cfun->decl)
1555 && DECL_LANG_FRONTEND (cfun->decl)->resolvedLinkage () != LINK::d)
1556 {
1557 /* In [type/integer-promotions], integer promotions are conversions of the
1558 following types:
1559
1560 bool int
1561 byte int
1562 ubyte int
1563 short int
1564 ushort int
1565 char int
1566 wchar int
1567 dchar uint
1568
1569 If an enum has as a base type one of the types in the left column, it
1570 is converted to the type in the right column. */
1571 if (TREE_CODE (type) == ENUMERAL_TYPE && ENUM_IS_SCOPED (type))
1572 type = TREE_TYPE (type);
1573
1574 type = TYPE_MAIN_VARIANT (type);
1575
1576 /* Check for promotions of target-defined types first. */
1577 tree promoted_type = targetm.promoted_type (type);
1578 if (promoted_type)
1579 return promoted_type;
1580
1581 if (TREE_CODE (type) == BOOLEAN_TYPE)
1582 return d_int_type;
1583
1584 if (INTEGRAL_TYPE_P (type))
1585 {
1586 if (type == d_byte_type || type == d_ubyte_type
1587 || type == d_short_type || type == d_ushort_type
1588 || type == char8_type_node || type == char16_type_node)
1589 return d_int_type;
1590
1591 if (type == char32_type_node)
1592 return d_uint_type;
1593
1594 if (TYPE_PRECISION (type) < TYPE_PRECISION (d_int_type))
1595 return d_int_type;
1596 }
1597
1598 /* Float arguments are converted to doubles. */
1599 if (type == float_type_node)
1600 return double_type_node;
1601
1602 if (type == ifloat_type_node)
1603 return idouble_type_node;
1604 }
1605
1606 return type;
1607 }
1608
1609 /* Implements the lang_hooks.decls.global_bindings_p routine for language D.
1610 Return true if we are in the global binding level. */
1611
1612 static bool
1613 d_global_bindings_p (void)
1614 {
1615 return (current_binding_level == global_binding_level);
1616 }
1617
1618 /* Return global_context, but create it first if need be. */
1619
1620 static tree
1621 get_global_context (void)
1622 {
1623 if (!global_context)
1624 {
1625 global_context = build_translation_unit_decl (NULL_TREE);
1626 debug_hooks->register_main_translation_unit (global_context);
1627 }
1628
1629 return global_context;
1630 }
1631
1632 /* Implements the lang_hooks.decls.pushdecl routine for language D.
1633 Record DECL as belonging to the current lexical scope. */
1634
1635 tree
1636 d_pushdecl (tree decl)
1637 {
1638 /* Set the context of the decl. If current_function_decl did not help in
1639 determining the context, use global scope. */
1640 if (!DECL_CONTEXT (decl))
1641 {
1642 if (current_function_decl)
1643 DECL_CONTEXT (decl) = current_function_decl;
1644 else
1645 DECL_CONTEXT (decl) = get_global_context ();
1646 }
1647
1648 /* Put decls on list in reverse order. */
1649 if (TREE_STATIC (decl) || d_global_bindings_p ())
1650 vec_safe_push (global_declarations, decl);
1651 else
1652 {
1653 TREE_CHAIN (decl) = current_binding_level->names;
1654 current_binding_level->names = decl;
1655 }
1656
1657 return decl;
1658 }
1659
1660 /* Implements the lang_hooks.decls.getdecls routine for language D.
1661 Return the list of declarations of the current level. */
1662
1663 static tree
1664 d_getdecls (void)
1665 {
1666 if (current_binding_level)
1667 return current_binding_level->names;
1668
1669 return NULL_TREE;
1670 }
1671
1672
1673 /* Implements the lang_hooks.get_alias_set routine for language D.
1674 Get the alias set corresponding to type or expression T.
1675 Return -1 if we don't do anything special. */
1676
1677 static alias_set_type
1678 d_get_alias_set (tree)
1679 {
1680 /* For now in D, assume everything aliases everything else, until we define
1681 some solid rules backed by a specification. There are also some parts
1682 of code generation routines that don't adhere to C alias rules, such as
1683 build_vconvert. In any case, a lot of user code already assumes there
1684 is no strict aliasing and will break if we were to change that. */
1685 return 0;
1686 }
1687
1688 /* Implements the lang_hooks.types_compatible_p routine for language D.
1689 Compares two types for equivalence in the D programming language.
1690 This routine should only return 1 if it is sure, even though the frontend
1691 should have already ensured that all types are compatible before handing
1692 over the parsed ASTs to the code generator. */
1693
1694 static int
1695 d_types_compatible_p (tree x, tree y)
1696 {
1697 Type *tx = TYPE_LANG_FRONTEND (x);
1698 Type *ty = TYPE_LANG_FRONTEND (y);
1699
1700 /* Try validating the types in the frontend. */
1701 if (tx != NULL && ty != NULL)
1702 {
1703 /* Types are equivalent. */
1704 if (same_type_p (tx, ty))
1705 return true;
1706
1707 /* Type system allows implicit conversion between. */
1708 if (tx->implicitConvTo (ty) != MATCH::nomatch
1709 || ty->implicitConvTo (tx) != MATCH::nomatch)
1710 return true;
1711 }
1712
1713 /* Fallback on using type flags for comparison. E.g: all dynamic arrays
1714 are distinct types in D, but are VIEW_CONVERT compatible. */
1715 if (TREE_CODE (x) == RECORD_TYPE && TREE_CODE (y) == RECORD_TYPE)
1716 {
1717 if (TYPE_DYNAMIC_ARRAY (x) && TYPE_DYNAMIC_ARRAY (y))
1718 return true;
1719
1720 if (TYPE_DELEGATE (x) && TYPE_DELEGATE (y))
1721 return true;
1722
1723 if (TYPE_ASSOCIATIVE_ARRAY (x) && TYPE_ASSOCIATIVE_ARRAY (y))
1724 return true;
1725 }
1726
1727 return false;
1728 }
1729
1730 /* Implements the lang_hooks.finish_incomplete_decl routine for language D. */
1731
1732 static void
1733 d_finish_incomplete_decl (tree decl)
1734 {
1735 if (VAR_P (decl))
1736 {
1737 /* D allows zero-length declarations. Such a declaration ends up with
1738 DECL_SIZE (t) == NULL_TREE which is what the back-end function
1739 assembler_variable checks. This could change in later versions, or
1740 maybe all of these variables should be aliased to one symbol. */
1741 if (DECL_SIZE (decl) == 0)
1742 {
1743 DECL_SIZE (decl) = bitsize_zero_node;
1744 DECL_SIZE_UNIT (decl) = size_zero_node;
1745 }
1746 }
1747 }
1748
1749 /* Implements the lang_hooks.types.classify_record routine for language D.
1750 Return the true debug type for TYPE. */
1751
1752 static classify_record
1753 d_classify_record (tree type)
1754 {
1755 Type *t = TYPE_LANG_FRONTEND (type);
1756 TypeClass *tc = t ? t->isTypeClass () : NULL;
1757
1758 if (tc != NULL)
1759 {
1760 /* extern(C++) interfaces get emitted as classes. */
1761 if (tc->sym->isInterfaceDeclaration ()
1762 && !tc->sym->isCPPinterface ())
1763 return RECORD_IS_INTERFACE;
1764
1765 return RECORD_IS_CLASS;
1766 }
1767
1768 return RECORD_IS_STRUCT;
1769 }
1770
1771 /* Implements the lang_hooks.tree_size routine for language D.
1772 Determine the size of our tcc_constant or tcc_exceptional nodes. */
1773
1774 static size_t
1775 d_tree_size (tree_code code)
1776 {
1777 switch (code)
1778 {
1779 case FUNCFRAME_INFO:
1780 return sizeof (tree_frame_info);
1781
1782 default:
1783 gcc_unreachable ();
1784 }
1785 }
1786
1787 /* Implements the lang_hooks.print_xnode routine for language D. */
1788
1789 static void
1790 d_print_xnode (FILE *file, tree node, int indent)
1791 {
1792 switch (TREE_CODE (node))
1793 {
1794 case FUNCFRAME_INFO:
1795 print_node (file, "frame_type", FRAMEINFO_TYPE (node), indent + 4);
1796 break;
1797
1798 default:
1799 break;
1800 }
1801 }
1802
1803 /* Return which tree structure is used by NODE, or TS_D_GENERIC if NODE
1804 is one of the language-independent trees. */
1805
1806 d_tree_node_structure_enum
1807 d_tree_node_structure (lang_tree_node *t)
1808 {
1809 switch (TREE_CODE (&t->generic))
1810 {
1811 case IDENTIFIER_NODE:
1812 return TS_D_IDENTIFIER;
1813
1814 case FUNCFRAME_INFO:
1815 return TS_D_FRAMEINFO;
1816
1817 default:
1818 return TS_D_GENERIC;
1819 }
1820 }
1821
1822 /* Allocate and return a lang specific structure for the frontend type. */
1823
1824 struct lang_type *
1825 build_lang_type (Type *t)
1826 {
1827 struct lang_type *lt = ggc_cleared_alloc <struct lang_type> ();
1828 lt->type = t;
1829 return lt;
1830 }
1831
1832 /* Allocate and return a lang specific structure for the frontend decl. */
1833
1834 struct lang_decl *
1835 build_lang_decl (Declaration *d)
1836 {
1837 /* For compiler generated run-time typeinfo, a lang_decl is allocated even if
1838 there's no associated frontend symbol to refer to (yet). If the symbol
1839 appears later in the compilation, then the slot will be re-used. */
1840 if (d == NULL)
1841 return ggc_cleared_alloc <struct lang_decl> ();
1842
1843 struct lang_decl *ld = (d->csym) ? DECL_LANG_SPECIFIC (d->csym) : NULL;
1844 if (ld == NULL)
1845 ld = ggc_cleared_alloc <struct lang_decl> ();
1846
1847 if (ld->decl == NULL)
1848 ld->decl = d;
1849
1850 return ld;
1851 }
1852
1853 /* Implements the lang_hooks.dup_lang_specific_decl routine for language D.
1854 Replace the DECL_LANG_SPECIFIC field of NODE with a copy. */
1855
1856 static void
1857 d_dup_lang_specific_decl (tree node)
1858 {
1859 if (!DECL_LANG_SPECIFIC (node))
1860 return;
1861
1862 struct lang_decl *ld = ggc_alloc <struct lang_decl> ();
1863 memcpy (ld, DECL_LANG_SPECIFIC (node), sizeof (struct lang_decl));
1864 DECL_LANG_SPECIFIC (node) = ld;
1865 }
1866
1867 /* This preserves trees we create from the garbage collector. */
1868
1869 static GTY(()) tree d_keep_list = NULL_TREE;
1870
1871 void
1872 d_keep (tree t)
1873 {
1874 d_keep_list = tree_cons (NULL_TREE, t, d_keep_list);
1875 }
1876
1877 /* Implements the lang_hooks.eh_personality routine for language D.
1878 Return the GDC personality function decl. */
1879
1880 static GTY(()) tree d_eh_personality_decl;
1881
1882 static tree
1883 d_eh_personality (void)
1884 {
1885 if (!d_eh_personality_decl)
1886 d_eh_personality_decl = build_personality_function ("gdc");
1887
1888 return d_eh_personality_decl;
1889 }
1890
1891 /* Implements the lang_hooks.eh_runtime_type routine for language D. */
1892
1893 static tree
1894 d_build_eh_runtime_type (tree type)
1895 {
1896 Type *t = TYPE_LANG_FRONTEND (type);
1897 gcc_assert (t != NULL);
1898 t = t->toBasetype ();
1899
1900 ClassDeclaration *cd = t->isTypeClass ()->sym;
1901 tree decl;
1902
1903 if (cd->isCPPclass ())
1904 decl = get_cpp_typeinfo_decl (cd);
1905 else
1906 decl = get_classinfo_decl (cd);
1907
1908 return convert (ptr_type_node, build_address (decl));
1909 }
1910
1911 /* Implements the lang_hooks.enum_underlying_base_type routine for language D.
1912 Returns the underlying type of the given enumeration TYPE. */
1913
1914 static tree
1915 d_enum_underlying_base_type (const_tree type)
1916 {
1917 gcc_assert (TREE_CODE (type) == ENUMERAL_TYPE);
1918 return TREE_TYPE (type);
1919 }
1920
1921 /* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
1922 based on the list in SARIF v2.1.0 Appendix J. */
1923
1924 static const char *
1925 d_get_sarif_source_language (const char *)
1926 {
1927 return "d";
1928 }
1929
1930 const scoped_attribute_specs *const d_langhook_attribute_table[] =
1931 {
1932 &d_langhook_gnu_attribute_table,
1933 &d_langhook_common_attribute_table,
1934 };
1935
1936 /* Definitions for our language-specific hooks. */
1937
1938 #undef LANG_HOOKS_NAME
1939 #undef LANG_HOOKS_INIT
1940 #undef LANG_HOOKS_INIT_TS
1941 #undef LANG_HOOKS_INIT_OPTIONS
1942 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
1943 #undef LANG_HOOKS_OPTION_LANG_MASK
1944 #undef LANG_HOOKS_HANDLE_OPTION
1945 #undef LANG_HOOKS_POST_OPTIONS
1946 #undef LANG_HOOKS_PARSE_FILE
1947 #undef LANG_HOOKS_ATTRIBUTE_TABLE
1948 #undef LANG_HOOKS_GET_ALIAS_SET
1949 #undef LANG_HOOKS_TYPES_COMPATIBLE_P
1950 #undef LANG_HOOKS_BUILTIN_FUNCTION
1951 #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
1952 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
1953 #undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
1954 #undef LANG_HOOKS_GIMPLIFY_EXPR
1955 #undef LANG_HOOKS_CLASSIFY_RECORD
1956 #undef LANG_HOOKS_TREE_SIZE
1957 #undef LANG_HOOKS_PRINT_XNODE
1958 #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
1959 #undef LANG_HOOKS_EH_PERSONALITY
1960 #undef LANG_HOOKS_EH_RUNTIME_TYPE
1961 #undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
1962 #undef LANG_HOOKS_PUSHDECL
1963 #undef LANG_HOOKS_GETDECLS
1964 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
1965 #undef LANG_HOOKS_TYPE_FOR_MODE
1966 #undef LANG_HOOKS_TYPE_FOR_SIZE
1967 #undef LANG_HOOKS_TYPE_PROMOTES_TO
1968 #undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
1969
1970 #define LANG_HOOKS_NAME "GNU D"
1971 #define LANG_HOOKS_INIT d_init
1972 #define LANG_HOOKS_INIT_TS d_init_ts
1973 #define LANG_HOOKS_INIT_OPTIONS d_init_options
1974 #define LANG_HOOKS_INIT_OPTIONS_STRUCT d_init_options_struct
1975 #define LANG_HOOKS_OPTION_LANG_MASK d_option_lang_mask
1976 #define LANG_HOOKS_HANDLE_OPTION d_handle_option
1977 #define LANG_HOOKS_POST_OPTIONS d_post_options
1978 #define LANG_HOOKS_PARSE_FILE d_parse_file
1979 #define LANG_HOOKS_ATTRIBUTE_TABLE d_langhook_attribute_table
1980 #define LANG_HOOKS_GET_ALIAS_SET d_get_alias_set
1981 #define LANG_HOOKS_TYPES_COMPATIBLE_P d_types_compatible_p
1982 #define LANG_HOOKS_BUILTIN_FUNCTION d_builtin_function
1983 #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE d_builtin_function_ext_scope
1984 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE d_register_builtin_type
1985 #define LANG_HOOKS_FINISH_INCOMPLETE_DECL d_finish_incomplete_decl
1986 #define LANG_HOOKS_GIMPLIFY_EXPR d_gimplify_expr
1987 #define LANG_HOOKS_CLASSIFY_RECORD d_classify_record
1988 #define LANG_HOOKS_TREE_SIZE d_tree_size
1989 #define LANG_HOOKS_PRINT_XNODE d_print_xnode
1990 #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL d_dup_lang_specific_decl
1991 #define LANG_HOOKS_EH_PERSONALITY d_eh_personality
1992 #define LANG_HOOKS_EH_RUNTIME_TYPE d_build_eh_runtime_type
1993 #define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE d_enum_underlying_base_type
1994 #define LANG_HOOKS_PUSHDECL d_pushdecl
1995 #define LANG_HOOKS_GETDECLS d_getdecls
1996 #define LANG_HOOKS_GLOBAL_BINDINGS_P d_global_bindings_p
1997 #define LANG_HOOKS_TYPE_FOR_MODE d_type_for_mode
1998 #define LANG_HOOKS_TYPE_FOR_SIZE d_type_for_size
1999 #define LANG_HOOKS_TYPE_PROMOTES_TO d_type_promotes_to
2000 #define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE d_get_sarif_source_language
2001
2002 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
2003
2004 #include "gt-d-d-lang.h"
2005 #include "gtype-d.h"