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