1 /* global.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1997 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.org).
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 Manages information kept across individual program units within a single
26 source file. This includes reporting errors when a name is defined
27 multiple times (for example, two program units named FOO) and when a
28 COMMON block is given initial data in more than one program unit.
44 /* Externals defined here. */
47 /* Simple definitions and enumerations. */
50 /* Internal typedefs. */
53 /* Private include files. */
56 /* Internal structure definitions. */
59 /* Static objects accessed by functions in this module. */
62 static ffenameSpace ffeglobal_filewide_ = NULL;
63 static char *ffeglobal_type_string_[] =
65 [FFEGLOBAL_typeNONE] "??",
66 [FFEGLOBAL_typeMAIN] "main program",
67 [FFEGLOBAL_typeEXT] "external",
68 [FFEGLOBAL_typeSUBR] "subroutine",
69 [FFEGLOBAL_typeFUNC] "function",
70 [FFEGLOBAL_typeBDATA] "block data",
71 [FFEGLOBAL_typeCOMMON] "common block",
72 [FFEGLOBAL_typeANY] "?any?"
76 /* Static functions (internal). */
79 /* Internal macros. */
82 /* Call given fn with all globals
84 ffeglobal (*fn)(ffeglobal g);
85 ffeglobal_drive(fn); */
89 ffeglobal_drive (ffeglobal (*fn) ())
91 if (ffeglobal_filewide_ != NULL)
92 ffename_space_drive_global (ffeglobal_filewide_, fn);
96 /* ffeglobal_new_ -- Make new global
100 g = ffeglobal_new_(n); */
102 #if FFEGLOBAL_ENABLED
104 ffeglobal_new_ (ffename n)
110 g = (ffeglobal) malloc_new_ks (malloc_pool_image (), "FFEGLOBAL",
113 #ifdef FFECOM_globalHOOK
114 g->hook = FFECOM_globalNULL;
118 ffename_set_global (n, g);
124 /* ffeglobal_init_1 -- Initialize per file
126 ffeglobal_init_1(); */
131 #if FFEGLOBAL_ENABLED
132 if (ffeglobal_filewide_ != NULL)
133 ffename_space_kill (ffeglobal_filewide_);
134 ffeglobal_filewide_ = ffename_space_new (malloc_pool_image ());
138 /* ffeglobal_init_common -- Initial value specified for common block
140 ffesymbol s; // the ffesymbol for the common block
141 ffelexToken t; // the token with the point of initialization
142 ffeglobal_init_common(s,t);
144 For back ends where file-wide global symbols are not maintained, does
145 nothing. Otherwise, makes sure this common block hasn't already been
146 initialized in a previous program unit, and flag that it's been
147 initialized in this one. */
150 ffeglobal_init_common (ffesymbol s, ffelexToken t)
152 #if FFEGLOBAL_ENABLED
155 g = ffesymbol_global (s);
157 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
159 if (g->type == FFEGLOBAL_typeANY)
162 if (g->tick == ffe_count_2)
167 if (g->u.common.initt != NULL)
169 ffebad_start (FFEBAD_COMMON_ALREADY_INIT);
170 ffebad_string (ffesymbol_text (s));
171 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
172 ffebad_here (1, ffelex_token_where_line (g->u.common.initt),
173 ffelex_token_where_column (g->u.common.initt));
177 /* Complain about just one attempt to reinit per program unit, but
178 continue referring back to the first such successful attempt. */
182 if (g->u.common.blank)
184 ffebad_start (FFEBAD_COMMON_BLANK_INIT);
185 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
189 g->u.common.initt = ffelex_token_use (t);
192 g->tick = ffe_count_2;
196 /* ffeglobal_new_common -- New common block
198 ffesymbol s; // the ffesymbol for the new common block
199 ffelexToken t; // the token with the name of the common block
200 bool blank; // TRUE if blank common
201 ffeglobal_new_common(s,t,blank);
203 For back ends where file-wide global symbols are not maintained, does
204 nothing. Otherwise, makes sure this symbol hasn't been seen before or
205 is known as a common block. */
208 ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
210 #if FFEGLOBAL_ENABLED
214 if (ffesymbol_global (s) == NULL)
216 n = ffename_find (ffeglobal_filewide_, t);
217 g = ffename_global (n);
221 g = ffesymbol_global (s);
225 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
228 if ((g != NULL) && (g->type != FFEGLOBAL_typeNONE))
230 if (g->type == FFEGLOBAL_typeCOMMON)
232 assert (g->u.common.blank == blank);
236 if (ffe_is_globals () || ffe_is_warn_globals ())
238 ffebad_start (ffe_is_globals ()
239 ? FFEBAD_FILEWIDE_ALREADY_SEEN
240 : FFEBAD_FILEWIDE_ALREADY_SEEN_W);
241 ffebad_string (ffelex_token_text (t));
242 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
243 ffebad_here (1, ffelex_token_where_line (g->t),
244 ffelex_token_where_column (g->t));
247 g->type = FFEGLOBAL_typeANY;
254 g = ffeglobal_new_ (n);
255 g->intrinsic = FALSE;
257 else if (g->intrinsic
258 && !g->explicit_intrinsic
259 && ffe_is_warn_globals ())
261 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
262 ffebad_string (ffelex_token_text (t));
263 ffebad_string ("common block");
264 ffebad_string ("intrinsic");
265 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
266 ffebad_here (1, ffelex_token_where_line (g->t),
267 ffelex_token_where_column (g->t));
270 g->t = ffelex_token_use (t);
271 g->type = FFEGLOBAL_typeCOMMON;
272 g->u.common.have_pad = FALSE;
273 g->u.common.have_save = FALSE;
274 g->u.common.have_size = FALSE;
275 g->u.common.blank = blank;
278 ffesymbol_set_global (s, g);
282 /* ffeglobal_new_progunit_ -- New program unit
284 ffesymbol s; // the ffesymbol for the new unit
285 ffelexToken t; // the token with the name of the unit
286 ffeglobalType type; // the type of the new unit
287 ffeglobal_new_progunit_(s,t,type);
289 For back ends where file-wide global symbols are not maintained, does
290 nothing. Otherwise, makes sure this symbol hasn't been seen before. */
293 ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
295 #if FFEGLOBAL_ENABLED
299 n = ffename_find (ffeglobal_filewide_, t);
300 g = ffename_global (n);
301 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
305 && ((g->type == FFEGLOBAL_typeMAIN)
306 || (g->type == FFEGLOBAL_typeSUBR)
307 || (g->type == FFEGLOBAL_typeFUNC)
308 || (g->type == FFEGLOBAL_typeBDATA))
309 && g->u.proc.defined)
311 if (ffe_is_globals () || ffe_is_warn_globals ())
313 ffebad_start (ffe_is_globals ()
314 ? FFEBAD_FILEWIDE_ALREADY_SEEN
315 : FFEBAD_FILEWIDE_ALREADY_SEEN_W);
316 ffebad_string (ffelex_token_text (t));
317 ffebad_here (0, ffelex_token_where_line (t),
318 ffelex_token_where_column (t));
319 ffebad_here (1, ffelex_token_where_line (g->t),
320 ffelex_token_where_column (g->t));
323 g->type = FFEGLOBAL_typeANY;
326 && (g->type != FFEGLOBAL_typeNONE)
327 && (g->type != FFEGLOBAL_typeEXT)
328 && (g->type != type))
330 if (ffe_is_globals () || ffe_is_warn_globals ())
332 ffebad_start (ffe_is_globals ()
333 ? FFEBAD_FILEWIDE_DISAGREEMENT
334 : FFEBAD_FILEWIDE_DISAGREEMENT_W);
335 ffebad_string (ffelex_token_text (t));
336 ffebad_string (ffeglobal_type_string_[type]);
337 ffebad_string (ffeglobal_type_string_[g->type]);
338 ffebad_here (0, ffelex_token_where_line (t),
339 ffelex_token_where_column (t));
340 ffebad_here (1, ffelex_token_where_line (g->t),
341 ffelex_token_where_column (g->t));
344 g->type = FFEGLOBAL_typeANY;
350 g = ffeglobal_new_ (n);
351 g->intrinsic = FALSE;
352 g->u.proc.n_args = -1;
353 g->u.proc.other_t = NULL;
355 else if ((ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
356 && ((ffesymbol_basictype (s) != g->u.proc.bt)
357 || (ffesymbol_kindtype (s) != g->u.proc.kt)
358 || ((ffesymbol_size (s) != FFETARGET_charactersizeNONE)
359 && (ffesymbol_size (s) != g->u.proc.sz))))
361 if (ffe_is_globals () || ffe_is_warn_globals ())
363 ffebad_start (ffe_is_globals ()
364 ? FFEBAD_FILEWIDE_TYPE_MISMATCH
365 : FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
366 ffebad_string (ffelex_token_text (t));
367 ffebad_here (0, ffelex_token_where_line (t),
368 ffelex_token_where_column (t));
369 ffebad_here (1, ffelex_token_where_line (g->t),
370 ffelex_token_where_column (g->t));
373 g->type = FFEGLOBAL_typeANY;
377 && !g->explicit_intrinsic
378 && ffe_is_warn_globals ())
380 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
381 ffebad_string (ffelex_token_text (t));
382 ffebad_string ("global");
383 ffebad_string ("intrinsic");
384 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
385 ffebad_here (1, ffelex_token_where_line (g->t),
386 ffelex_token_where_column (g->t));
389 g->t = ffelex_token_use (t);
391 || (g->u.proc.bt == FFEINFO_basictypeNONE)
392 || (g->u.proc.kt == FFEINFO_kindtypeNONE))
394 g->u.proc.bt = ffesymbol_basictype (s);
395 g->u.proc.kt = ffesymbol_kindtype (s);
396 g->u.proc.sz = ffesymbol_size (s);
398 g->tick = ffe_count_2;
400 && (g->type != type))
401 g->u.proc.n_args = -1;
403 g->u.proc.defined = TRUE;
406 ffesymbol_set_global (s, g);
410 /* ffeglobal_pad_common -- Check initial padding of common area
412 ffesymbol s; // the common area
413 ffetargetAlign pad; // the initial padding
414 ffeglobal_pad_common(s,pad,ffesymbol_where_line(s),
415 ffesymbol_where_column(s));
417 In global-enabled mode, make sure the padding agrees with any existing
418 padding established for the common area, otherwise complain.
419 In global-disabled mode, warn about nonzero padding. */
422 ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
425 #if FFEGLOBAL_ENABLED
428 g = ffesymbol_global (s);
429 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
430 return; /* Let someone else catch this! */
431 if (g->type == FFEGLOBAL_typeANY)
434 if (!g->u.common.have_pad)
436 g->u.common.have_pad = TRUE;
437 g->u.common.pad = pad;
438 g->u.common.pad_where_line = ffewhere_line_use (wl);
439 g->u.common.pad_where_col = ffewhere_column_use (wc);
445 sprintf (&padding[0], "%" ffetargetAlign_f "u", pad);
446 ffebad_start (FFEBAD_COMMON_INIT_PAD);
447 ffebad_string (ffesymbol_text (s));
448 ffebad_string (padding);
449 ffebad_string ((pad == 1)
450 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
451 ffebad_here (0, wl, wc);
457 if (g->u.common.pad != pad)
462 sprintf (&padding_1[0], "%" ffetargetAlign_f "u", pad);
463 sprintf (&padding_2[0], "%" ffetargetAlign_f "u", g->u.common.pad);
464 ffebad_start (FFEBAD_COMMON_DIFF_PAD);
465 ffebad_string (ffesymbol_text (s));
466 ffebad_string (padding_1);
467 ffebad_here (0, wl, wc);
468 ffebad_string (padding_2);
469 ffebad_string ((pad == 1)
470 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
471 ffebad_string ((g->u.common.pad == 1)
472 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
473 ffebad_here (1, g->u.common.pad_where_line, g->u.common.pad_where_col);
477 if (g->u.common.pad < pad)
479 g->u.common.pad = pad;
480 g->u.common.pad_where_line = ffewhere_line_use (wl);
481 g->u.common.pad_where_col = ffewhere_column_use (wc);
487 /* Collect info for a global's argument. */
490 ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary as,
491 ffeinfoBasictype bt, ffeinfoKindtype kt,
494 ffeglobal g = ffesymbol_global (s);
495 ffeglobalArgInfo_ ai;
499 if (g->type == FFEGLOBAL_typeANY)
502 assert (g->u.proc.n_args >= 0);
504 if (argno >= g->u.proc.n_args)
505 return; /* Already complained about this discrepancy. */
507 ai = &g->u.proc.arg_info[argno];
509 /* Maybe warn about previous references. */
512 && ffe_is_warn_globals ())
520 case FFEGLOBAL_argsummaryREF:
521 if ((ai->as != FFEGLOBAL_argsummaryREF)
522 && (ai->as != FFEGLOBAL_argsummaryNONE)
523 && ((ai->as != FFEGLOBAL_argsummaryDESCR) /* Choose better message. */
524 || (ai->bt != FFEINFO_basictypeCHARACTER)
528 refwhy = "passed by reference";
532 case FFEGLOBAL_argsummaryDESCR:
533 if ((ai->as != FFEGLOBAL_argsummaryDESCR)
534 && (ai->as != FFEGLOBAL_argsummaryNONE)
535 && ((ai->as != FFEGLOBAL_argsummaryREF) /* Choose better message. */
536 || (bt != FFEINFO_basictypeCHARACTER)
540 refwhy = "passed by descriptor";
544 case FFEGLOBAL_argsummaryPROC:
545 if ((ai->as != FFEGLOBAL_argsummaryPROC)
546 && (ai->as != FFEGLOBAL_argsummarySUBR)
547 && (ai->as != FFEGLOBAL_argsummaryFUNC)
548 && (ai->as != FFEGLOBAL_argsummaryNONE))
551 refwhy = "a procedure";
555 case FFEGLOBAL_argsummarySUBR:
556 if ((ai->as != FFEGLOBAL_argsummaryPROC)
557 && (ai->as != FFEGLOBAL_argsummarySUBR)
558 && (ai->as != FFEGLOBAL_argsummaryNONE))
561 refwhy = "a subroutine";
565 case FFEGLOBAL_argsummaryFUNC:
566 if ((ai->as != FFEGLOBAL_argsummaryPROC)
567 && (ai->as != FFEGLOBAL_argsummaryFUNC)
568 && (ai->as != FFEGLOBAL_argsummaryNONE))
571 refwhy = "a function";
575 case FFEGLOBAL_argsummaryALTRTN:
576 if ((ai->as != FFEGLOBAL_argsummaryALTRTN)
577 && (ai->as != FFEGLOBAL_argsummaryNONE))
580 refwhy = "an alternate-return label";
588 if ((refwhy != NULL) && (defwhy == NULL))
590 /* Fill in the def info. */
594 case FFEGLOBAL_argsummaryNONE:
598 case FFEGLOBAL_argsummaryVAL:
599 defwhy = "passed by value";
602 case FFEGLOBAL_argsummaryREF:
603 defwhy = "passed by reference";
606 case FFEGLOBAL_argsummaryDESCR:
607 defwhy = "passed by descriptor";
610 case FFEGLOBAL_argsummaryPROC:
611 defwhy = "a procedure";
614 case FFEGLOBAL_argsummarySUBR:
615 defwhy = "a subroutine";
618 case FFEGLOBAL_argsummaryFUNC:
619 defwhy = "a function";
622 case FFEGLOBAL_argsummaryALTRTN:
623 defwhy = "an alternate-return label";
627 case FFEGLOBAL_argsummaryPTR:
628 defwhy = "a pointer";
639 && (bt != FFEINFO_basictypeHOLLERITH)
640 && (bt != FFEINFO_basictypeTYPELESS)
641 && (bt != FFEINFO_basictypeNONE)
642 && (ai->bt != FFEINFO_basictypeHOLLERITH)
643 && (ai->bt != FFEINFO_basictypeTYPELESS)
644 && (ai->bt != FFEINFO_basictypeNONE))
649 && ((bt != FFEINFO_basictypeREAL)
650 || (ai->bt != FFEINFO_basictypeCOMPLEX))
651 && ((bt != FFEINFO_basictypeCOMPLEX)
652 || (ai->bt != FFEINFO_basictypeREAL)))
654 warn = TRUE; /* We can cope with these differences. */
656 defwhy = "some other type";
659 if (!warn && (kt != ai->kt))
662 refwhy = "one precision";
663 defwhy = "some other precision";
672 sprintf (&num[0], "%d", argno + 1);
675 if (strlen (name) < 30)
676 sprintf (&num[0], "%d (named `%s')", argno + 1, name);
678 sprintf (&num[0], "%d (named `%.*s...')", argno + 1, 30, name);
680 ffebad_start (FFEBAD_FILEWIDE_ARG_W);
681 ffebad_string (ffesymbol_text (s));
683 ffebad_string (refwhy);
684 ffebad_string (defwhy);
685 ffebad_here (0, ffelex_token_where_line (g->t), ffelex_token_where_column (g->t));
686 ffebad_here (1, ffelex_token_where_line (ai->t), ffelex_token_where_column (ai->t));
691 /* Define this argument. */
694 ffelex_token_kill (ai->t);
695 if ((as != FFEGLOBAL_argsummaryPROC)
697 ai->as = as; /* Otherwise leave SUBR/FUNC info intact. */
698 ai->t = ffelex_token_use (g->t);
703 ai->name = malloc_new_ks (malloc_pool_image (),
704 "ffeglobalArgInfo_ name",
706 strcpy (ai->name, name);
713 /* Collect info on #args a global accepts. */
716 ffeglobal_proc_def_nargs (ffesymbol s, int n_args)
718 ffeglobal g = ffesymbol_global (s);
722 if (g->type == FFEGLOBAL_typeANY)
725 if (g->u.proc.n_args >= 0)
727 if (g->u.proc.n_args == n_args)
730 if (ffe_is_warn_globals ())
732 ffebad_start (FFEBAD_FILEWIDE_NARGS_W);
733 ffebad_string (ffesymbol_text (s));
734 if (g->u.proc.n_args > n_args)
735 ffebad_string ("few");
737 ffebad_string ("many");
738 ffebad_here (0, ffelex_token_where_line (g->u.proc.other_t),
739 ffelex_token_where_column (g->u.proc.other_t));
740 ffebad_here (1, ffelex_token_where_line (g->t),
741 ffelex_token_where_column (g->t));
746 /* This is new info we can use in cross-checking future references
747 and a possible future definition. */
749 g->u.proc.n_args = n_args;
750 g->u.proc.other_t = NULL; /* No other reference yet. */
754 g->u.proc.arg_info = NULL;
759 = (ffeglobalArgInfo_) malloc_new_ks (malloc_pool_image (),
761 n_args * sizeof (g->u.proc.arg_info[0]));
763 g->u.proc.arg_info[n_args].t = NULL;
766 /* Verify that the info for a global's argument is valid. */
769 ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
770 ffeinfoBasictype bt, ffeinfoKindtype kt,
771 bool array, ffelexToken t)
773 ffeglobal g = ffesymbol_global (s);
774 ffeglobalArgInfo_ ai;
778 if (g->type == FFEGLOBAL_typeANY)
781 assert (g->u.proc.n_args >= 0);
783 if (argno >= g->u.proc.n_args)
784 return TRUE; /* Already complained about this discrepancy. */
786 ai = &g->u.proc.arg_info[argno];
788 /* Warn about previous references. */
799 case FFEGLOBAL_argsummaryNONE:
800 if (g->u.proc.defined)
804 defwhy = "not optional";
808 case FFEGLOBAL_argsummaryVAL:
809 if (ai->as != FFEGLOBAL_argsummaryVAL)
812 refwhy = "passed by value";
816 case FFEGLOBAL_argsummaryREF:
817 if ((ai->as != FFEGLOBAL_argsummaryREF)
818 && (ai->as != FFEGLOBAL_argsummaryNONE)
819 && ((ai->as != FFEGLOBAL_argsummaryDESCR) /* Choose better message. */
820 || (ai->bt != FFEINFO_basictypeCHARACTER)
824 refwhy = "passed by reference";
828 case FFEGLOBAL_argsummaryDESCR:
829 if ((ai->as != FFEGLOBAL_argsummaryDESCR)
830 && (ai->as != FFEGLOBAL_argsummaryNONE)
831 && ((ai->as != FFEGLOBAL_argsummaryREF) /* Choose better message. */
832 || (bt != FFEINFO_basictypeCHARACTER)
836 refwhy = "passed by descriptor";
840 case FFEGLOBAL_argsummaryPROC:
841 if ((ai->as != FFEGLOBAL_argsummaryPROC)
842 && (ai->as != FFEGLOBAL_argsummarySUBR)
843 && (ai->as != FFEGLOBAL_argsummaryFUNC)
844 && (ai->as != FFEGLOBAL_argsummaryNONE))
847 refwhy = "a procedure";
851 case FFEGLOBAL_argsummarySUBR:
852 if ((ai->as != FFEGLOBAL_argsummaryPROC)
853 && (ai->as != FFEGLOBAL_argsummarySUBR)
854 && (ai->as != FFEGLOBAL_argsummaryNONE))
857 refwhy = "a subroutine";
861 case FFEGLOBAL_argsummaryFUNC:
862 if ((ai->as != FFEGLOBAL_argsummaryPROC)
863 && (ai->as != FFEGLOBAL_argsummaryFUNC)
864 && (ai->as != FFEGLOBAL_argsummaryNONE))
867 refwhy = "a function";
871 case FFEGLOBAL_argsummaryALTRTN:
872 if ((ai->as != FFEGLOBAL_argsummaryALTRTN)
873 && (ai->as != FFEGLOBAL_argsummaryNONE))
876 refwhy = "an alternate-return label";
881 case FFEGLOBAL_argsummaryPTR:
882 if ((ai->as != FFEGLOBAL_argsummaryPTR)
883 && (ai->as != FFEGLOBAL_argsummaryNONE))
886 refwhy = "a pointer";
895 if ((refwhy != NULL) && (defwhy == NULL))
897 /* Fill in the def info. */
901 case FFEGLOBAL_argsummaryNONE:
905 case FFEGLOBAL_argsummaryVAL:
906 defwhy = "passed by value";
909 case FFEGLOBAL_argsummaryREF:
910 defwhy = "passed by reference";
913 case FFEGLOBAL_argsummaryDESCR:
914 defwhy = "passed by descriptor";
917 case FFEGLOBAL_argsummaryPROC:
918 defwhy = "a procedure";
921 case FFEGLOBAL_argsummarySUBR:
922 defwhy = "a subroutine";
925 case FFEGLOBAL_argsummaryFUNC:
926 defwhy = "a function";
929 case FFEGLOBAL_argsummaryALTRTN:
930 defwhy = "an alternate-return label";
934 case FFEGLOBAL_argsummaryPTR:
935 defwhy = "a pointer";
946 && (bt != FFEINFO_basictypeHOLLERITH)
947 && (bt != FFEINFO_basictypeTYPELESS)
948 && (bt != FFEINFO_basictypeNONE)
949 && (ai->bt != FFEINFO_basictypeHOLLERITH)
950 && (ai->bt != FFEINFO_basictypeNONE)
951 && (ai->bt != FFEINFO_basictypeTYPELESS))
956 && ((bt != FFEINFO_basictypeREAL)
957 || (ai->bt != FFEINFO_basictypeCOMPLEX))
958 && ((bt != FFEINFO_basictypeCOMPLEX)
959 || (ai->bt != FFEINFO_basictypeREAL)))
961 if (((bt == FFEINFO_basictypeINTEGER)
962 && (ai->bt == FFEINFO_basictypeLOGICAL))
963 || ((bt == FFEINFO_basictypeLOGICAL)
964 && (ai->bt == FFEINFO_basictypeINTEGER)))
965 warn = TRUE; /* We can cope with these differences. */
969 defwhy = "some other type";
972 if (!fail && !warn && (kt != ai->kt))
975 refwhy = "one precision";
976 defwhy = "some other precision";
980 if (fail && ! g->u.proc.defined)
982 /* No point failing if we're worried only about invocations. */
987 if (fail && ! ffe_is_globals ())
993 if (fail || (warn && ffe_is_warn_globals ()))
997 if (ai->name == NULL)
998 sprintf (&num[0], "%d", argno + 1);
1001 if (strlen (ai->name) < 30)
1002 sprintf (&num[0], "%d (named `%s')", argno + 1, ai->name);
1004 sprintf (&num[0], "%d (named `%.*s...')", argno + 1, 30, ai->name);
1006 ffebad_start (fail ? FFEBAD_FILEWIDE_ARG : FFEBAD_FILEWIDE_ARG_W);
1007 ffebad_string (ffesymbol_text (s));
1008 ffebad_string (num);
1009 ffebad_string (refwhy);
1010 ffebad_string (defwhy);
1011 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1012 ffebad_here (1, ffelex_token_where_line (ai->t), ffelex_token_where_column (ai->t));
1014 return (fail ? FALSE : TRUE);
1021 /* Define this argument. */
1024 ffelex_token_kill (ai->t);
1025 if ((as != FFEGLOBAL_argsummaryPROC)
1028 ai->t = ffelex_token_use (g->t);
1037 ffeglobal_proc_ref_nargs (ffesymbol s, int n_args, ffelexToken t)
1039 ffeglobal g = ffesymbol_global (s);
1043 if (g->type == FFEGLOBAL_typeANY)
1046 if (g->u.proc.n_args >= 0)
1048 if (g->u.proc.n_args == n_args)
1051 if (g->u.proc.defined && ffe_is_globals ())
1053 ffebad_start (FFEBAD_FILEWIDE_NARGS);
1054 ffebad_string (ffesymbol_text (s));
1055 if (g->u.proc.n_args > n_args)
1056 ffebad_string ("few");
1058 ffebad_string ("many");
1059 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1060 ffebad_here (1, ffelex_token_where_line (g->t),
1061 ffelex_token_where_column (g->t));
1066 if (ffe_is_warn_globals ())
1068 ffebad_start (FFEBAD_FILEWIDE_NARGS_W);
1069 ffebad_string (ffesymbol_text (s));
1070 if (g->u.proc.n_args > n_args)
1071 ffebad_string ("few");
1073 ffebad_string ("many");
1074 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1075 ffebad_here (1, ffelex_token_where_line (g->t),
1076 ffelex_token_where_column (g->t));
1080 return TRUE; /* Don't replace the info we already have. */
1083 /* This is new info we can use in cross-checking future references
1084 and a possible future definition. */
1086 g->u.proc.n_args = n_args;
1087 g->u.proc.other_t = ffelex_token_use (t);
1089 /* Make this "the" place we found the global, since it has the most info. */
1092 ffelex_token_kill (g->t);
1093 g->t = ffelex_token_use (t);
1097 g->u.proc.arg_info = NULL;
1102 = (ffeglobalArgInfo_) malloc_new_ks (malloc_pool_image (),
1103 "ffeglobalArgInfo_",
1104 n_args * sizeof (g->u.proc.arg_info[0]));
1105 while (n_args-- > 0)
1106 g->u.proc.arg_info[n_args].t = NULL;
1111 /* Return a global for a promoted symbol (one that has heretofore
1112 been assumed to be local, but since discovered to be global). */
1115 ffeglobal_promoted (ffesymbol s)
1117 #if FFEGLOBAL_ENABLED
1121 assert (ffesymbol_global (s) == NULL);
1123 n = ffename_find (ffeglobal_filewide_, ffename_token (ffesymbol_name (s)));
1124 g = ffename_global (n);
1132 /* Register a reference to an intrinsic. Such a reference is always
1133 valid, though a warning might be in order if the same name has
1134 already been used for a global. */
1137 ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
1139 #if FFEGLOBAL_ENABLED
1143 if (ffesymbol_global (s) == NULL)
1145 n = ffename_find (ffeglobal_filewide_, t);
1146 g = ffename_global (n);
1150 g = ffesymbol_global (s);
1154 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
1157 if ((g != NULL) && (g->type != FFEGLOBAL_typeNONE))
1161 && ffe_is_warn_globals ())
1163 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
1164 ffebad_string (ffelex_token_text (t));
1165 ffebad_string ("intrinsic");
1166 ffebad_string ("global");
1167 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1168 ffebad_here (1, ffelex_token_where_line (g->t),
1169 ffelex_token_where_column (g->t));
1177 g = ffeglobal_new_ (n);
1178 g->tick = ffe_count_2;
1179 g->type = FFEGLOBAL_typeNONE;
1180 g->intrinsic = TRUE;
1181 g->explicit_intrinsic = explicit;
1182 g->t = ffelex_token_use (t);
1184 else if (g->intrinsic
1185 && (explicit != g->explicit_intrinsic)
1186 && (g->tick != ffe_count_2)
1187 && ffe_is_warn_globals ())
1189 ffebad_start (FFEBAD_INTRINSIC_EXPIMP);
1190 ffebad_string (ffelex_token_text (t));
1191 ffebad_string (explicit ? "explicit" : "implicit");
1192 ffebad_string (explicit ? "implicit" : "explicit");
1193 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1194 ffebad_here (1, ffelex_token_where_line (g->t),
1195 ffelex_token_where_column (g->t));
1200 g->intrinsic = TRUE;
1202 g->explicit_intrinsic = TRUE;
1204 ffesymbol_set_global (s, g);
1208 /* Register a reference to a global. Returns TRUE if the reference
1212 ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
1214 #if FFEGLOBAL_ENABLED
1218 /* It is never really _known_ that an EXTERNAL statement
1219 names a BLOCK DATA by just looking at the program unit,
1220 so override a different notion here. */
1221 if (type == FFEGLOBAL_typeBDATA)
1222 type = FFEGLOBAL_typeEXT;
1224 g = ffesymbol_global (s);
1227 n = ffename_find (ffeglobal_filewide_, t);
1228 g = ffename_global (n);
1230 ffesymbol_set_global (s, g);
1233 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
1237 && (g->type != FFEGLOBAL_typeNONE)
1238 && (g->type != type)
1239 && (g->type != FFEGLOBAL_typeEXT)
1240 && (type != FFEGLOBAL_typeEXT))
1242 if ((((type == FFEGLOBAL_typeBDATA)
1243 && (g->type != FFEGLOBAL_typeCOMMON))
1244 || ((g->type == FFEGLOBAL_typeBDATA)
1245 && (type != FFEGLOBAL_typeCOMMON)
1246 && ! g->u.proc.defined)))
1248 #if 0 /* This is likely to just annoy people. */
1249 if (ffe_is_warn_globals ())
1251 ffebad_start (FFEBAD_FILEWIDE_TIFF);
1252 ffebad_string (ffelex_token_text (t));
1253 ffebad_string (ffeglobal_type_string_[type]);
1254 ffebad_string (ffeglobal_type_string_[g->type]);
1255 ffebad_here (0, ffelex_token_where_line (t),
1256 ffelex_token_where_column (t));
1257 ffebad_here (1, ffelex_token_where_line (g->t),
1258 ffelex_token_where_column (g->t));
1263 else if (ffe_is_globals ())
1265 ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT);
1266 ffebad_string (ffelex_token_text (t));
1267 ffebad_string (ffeglobal_type_string_[type]);
1268 ffebad_string (ffeglobal_type_string_[g->type]);
1269 ffebad_here (0, ffelex_token_where_line (t),
1270 ffelex_token_where_column (t));
1271 ffebad_here (1, ffelex_token_where_line (g->t),
1272 ffelex_token_where_column (g->t));
1274 g->type = FFEGLOBAL_typeANY;
1277 else if (ffe_is_warn_globals ())
1279 ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT_W);
1280 ffebad_string (ffelex_token_text (t));
1281 ffebad_string (ffeglobal_type_string_[type]);
1282 ffebad_string (ffeglobal_type_string_[g->type]);
1283 ffebad_here (0, ffelex_token_where_line (t),
1284 ffelex_token_where_column (t));
1285 ffebad_here (1, ffelex_token_where_line (g->t),
1286 ffelex_token_where_column (g->t));
1288 g->type = FFEGLOBAL_typeANY;
1294 && (type == FFEGLOBAL_typeFUNC))
1296 /* If just filling in this function's type, do so. */
1297 if ((g->tick == ffe_count_2)
1298 && (ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
1299 && (ffesymbol_kindtype (s) != FFEINFO_kindtypeNONE))
1301 g->u.proc.bt = ffesymbol_basictype (s);
1302 g->u.proc.kt = ffesymbol_kindtype (s);
1303 g->u.proc.sz = ffesymbol_size (s);
1305 /* Else, make sure there is type agreement. */
1306 else if ((g->u.proc.bt != FFEINFO_basictypeNONE)
1307 && (ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
1308 && ((ffesymbol_basictype (s) != g->u.proc.bt)
1309 || (ffesymbol_kindtype (s) != g->u.proc.kt)
1310 || ((ffesymbol_size (s) != g->u.proc.sz)
1311 && g->u.proc.defined
1312 && (g->u.proc.sz != FFETARGET_charactersizeNONE))))
1314 if (ffe_is_globals ())
1316 ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH);
1317 ffebad_string (ffelex_token_text (t));
1318 ffebad_here (0, ffelex_token_where_line (t),
1319 ffelex_token_where_column (t));
1320 ffebad_here (1, ffelex_token_where_line (g->t),
1321 ffelex_token_where_column (g->t));
1323 g->type = FFEGLOBAL_typeANY;
1326 if (ffe_is_warn_globals ())
1328 ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
1329 ffebad_string (ffelex_token_text (t));
1330 ffebad_here (0, ffelex_token_where_line (t),
1331 ffelex_token_where_column (t));
1332 ffebad_here (1, ffelex_token_where_line (g->t),
1333 ffelex_token_where_column (g->t));
1336 g->type = FFEGLOBAL_typeANY;
1343 g = ffeglobal_new_ (n);
1344 g->t = ffelex_token_use (t);
1345 g->tick = ffe_count_2;
1346 g->intrinsic = FALSE;
1348 g->u.proc.defined = FALSE;
1349 g->u.proc.bt = ffesymbol_basictype (s);
1350 g->u.proc.kt = ffesymbol_kindtype (s);
1351 g->u.proc.sz = ffesymbol_size (s);
1352 g->u.proc.n_args = -1;
1353 ffesymbol_set_global (s, g);
1355 else if (g->intrinsic
1356 && !g->explicit_intrinsic
1357 && (g->tick != ffe_count_2)
1358 && ffe_is_warn_globals ())
1360 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
1361 ffebad_string (ffelex_token_text (t));
1362 ffebad_string ("global");
1363 ffebad_string ("intrinsic");
1364 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1365 ffebad_here (1, ffelex_token_where_line (g->t),
1366 ffelex_token_where_column (g->t));
1370 if ((g->type != type)
1371 && (type != FFEGLOBAL_typeEXT))
1373 /* We've learned more, so point to where we learned it. */
1374 g->t = ffelex_token_use (t);
1376 #ifdef FFECOM_globalHOOK
1377 g->hook = FFECOM_globalNULL; /* Discard previous _DECL. */
1379 g->u.proc.n_args = -1;
1386 /* ffeglobal_save_common -- Check SAVE status of common area
1388 ffesymbol s; // the common area
1389 bool save; // TRUE if SAVEd, FALSE otherwise
1390 ffeglobal_save_common(s,save,ffesymbol_where_line(s),
1391 ffesymbol_where_column(s));
1393 In global-enabled mode, make sure the save info agrees with any existing
1394 info established for the common area, otherwise complain.
1395 In global-disabled mode, do nothing. */
1398 ffeglobal_save_common (ffesymbol s, bool save, ffewhereLine wl,
1401 #if FFEGLOBAL_ENABLED
1404 g = ffesymbol_global (s);
1405 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
1406 return; /* Let someone else catch this! */
1407 if (g->type == FFEGLOBAL_typeANY)
1410 if (!g->u.common.have_save)
1412 g->u.common.have_save = TRUE;
1413 g->u.common.save = save;
1414 g->u.common.save_where_line = ffewhere_line_use (wl);
1415 g->u.common.save_where_col = ffewhere_column_use (wc);
1419 if ((g->u.common.save != save) && ffe_is_pedantic ())
1421 ffebad_start (FFEBAD_COMMON_DIFF_SAVE);
1422 ffebad_string (ffesymbol_text (s));
1423 ffebad_here (save ? 0 : 1, wl, wc);
1424 ffebad_here (save ? 1 : 0, g->u.common.pad_where_line, g->u.common.pad_where_col);
1431 /* ffeglobal_size_common -- Establish size of COMMON area
1433 ffesymbol s; // the common area
1434 ffetargetOffset size; // size in units
1435 if (ffeglobal_size_common(s,size)) // new size is largest seen
1437 In global-enabled mode, set the size if it current size isn't known or is
1438 smaller than new size, and for non-blank common, complain if old size
1439 is different from new. Return TRUE if the new size is the largest seen
1440 for this COMMON area (or if no size was known for it previously).
1441 In global-disabled mode, do nothing. */
1443 #if FFEGLOBAL_ENABLED
1445 ffeglobal_size_common (ffesymbol s, ffetargetOffset size)
1449 g = ffesymbol_global (s);
1450 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
1452 if (g->type == FFEGLOBAL_typeANY)
1455 if (!g->u.common.have_size)
1457 g->u.common.have_size = TRUE;
1458 g->u.common.size = size;
1462 if ((g->tick > 0) && (g->tick < ffe_count_2)
1463 && (g->u.common.size < size))
1468 /* Common block initialized in a previous program unit, which
1469 effectively freezes its size, but now the program is trying
1472 sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
1473 sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
1475 ffebad_start (FFEBAD_COMMON_ENLARGED);
1476 ffebad_string (ffesymbol_text (s));
1477 ffebad_string (oldsize);
1478 ffebad_string (newsize);
1479 ffebad_string ((g->u.common.size == 1)
1480 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1481 ffebad_string ((size == 1)
1482 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1483 ffebad_here (0, ffelex_token_where_line (g->u.common.initt),
1484 ffelex_token_where_column (g->u.common.initt));
1485 ffebad_here (1, ffesymbol_where_line (s),
1486 ffesymbol_where_column (s));
1489 else if ((g->u.common.size != size) && !g->u.common.blank)
1494 /* Warn about this even if not -pedantic, because putting all
1495 program units in a single source file is the only way to
1496 detect this. Apparently UNIX-model linkers neither handle
1497 nor report when they make a common unit smaller than
1498 requested, such as when the smaller-declared version is
1499 initialized and the larger-declared version is not. So
1500 if people complain about strange overwriting, we can tell
1501 them to put all their code in a single file and compile
1502 that way. Warnings about differing sizes must therefore
1503 always be issued. */
1505 sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
1506 sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
1508 ffebad_start (FFEBAD_COMMON_DIFF_SIZE);
1509 ffebad_string (ffesymbol_text (s));
1510 ffebad_string (oldsize);
1511 ffebad_string (newsize);
1512 ffebad_string ((g->u.common.size == 1)
1513 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1514 ffebad_string ((size == 1)
1515 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1516 ffebad_here (0, ffelex_token_where_line (g->t),
1517 ffelex_token_where_column (g->t));
1518 ffebad_here (1, ffesymbol_where_line (s),
1519 ffesymbol_where_column (s));
1523 if (size > g->u.common.size)
1525 g->u.common.size = size;
1534 ffeglobal_terminate_1 ()