* mklibgcc.in: Remove obsolete MAYBE_USE_COLLECT2.
[official-gcc.git] / gcc / f / global.c
blob8793f62c4a73ccc8ad02b4304e85a74e5dcba137
1 /* global.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1997, 2003 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
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)
10 any later version.
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
20 02111-1307, USA.
22 Related Modules:
24 Description:
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.
30 Modifications:
33 /* Include files. */
35 #include "proj.h"
36 #include "global.h"
37 #include "info.h"
38 #include "lex.h"
39 #include "malloc.h"
40 #include "name.h"
41 #include "symbol.h"
42 #include "top.h"
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. */
61 #if FFEGLOBAL_ENABLED
62 static ffenameSpace ffeglobal_filewide_ = NULL;
63 static const char *const 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?"
74 #endif
76 /* Static functions (internal). */
79 /* Internal macros. */
82 /* Call given fn with all globals
84 ffeglobal (*fn)(ffeglobal g);
85 ffeglobal_drive(fn); */
87 #if FFEGLOBAL_ENABLED
88 void
89 ffeglobal_drive (ffeglobal (*fn) (ffeglobal))
91 if (ffeglobal_filewide_ != NULL)
92 ffename_space_drive_global (ffeglobal_filewide_, fn);
95 #endif
96 /* ffeglobal_new_ -- Make new global
98 ffename n;
99 ffeglobal g;
100 g = ffeglobal_new_(n); */
102 #if FFEGLOBAL_ENABLED
103 static ffeglobal
104 ffeglobal_new_ (ffename n)
106 ffeglobal g;
108 assert (n != NULL);
110 g = malloc_new_ks (malloc_pool_image (), "FFEGLOBAL", sizeof (*g));
111 g->n = n;
112 g->hook = FFECOM_globalNULL;
113 g->tick = 0;
115 ffename_set_global (n, g);
117 return g;
120 #endif
121 /* ffeglobal_init_1 -- Initialize per file
123 ffeglobal_init_1(); */
125 void
126 ffeglobal_init_1 (void)
128 #if FFEGLOBAL_ENABLED
129 if (ffeglobal_filewide_ != NULL)
130 ffename_space_kill (ffeglobal_filewide_);
131 ffeglobal_filewide_ = ffename_space_new (malloc_pool_image ());
132 #endif
135 /* ffeglobal_init_common -- Initial value specified for common block
137 ffesymbol s; // the ffesymbol for the common block
138 ffelexToken t; // the token with the point of initialization
139 ffeglobal_init_common(s,t);
141 For back ends where file-wide global symbols are not maintained, does
142 nothing. Otherwise, makes sure this common block hasn't already been
143 initialized in a previous program unit, and flag that it's been
144 initialized in this one. */
146 void
147 ffeglobal_init_common (ffesymbol s, ffelexToken t)
149 #if FFEGLOBAL_ENABLED
150 ffeglobal g;
152 g = ffesymbol_global (s);
154 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
155 return;
156 if (g->type == FFEGLOBAL_typeANY)
157 return;
159 if (g->tick == ffe_count_2)
160 return;
162 if (g->tick != 0)
164 if (g->u.common.initt != NULL)
166 ffebad_start (FFEBAD_COMMON_ALREADY_INIT);
167 ffebad_string (ffesymbol_text (s));
168 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
169 ffebad_here (1, ffelex_token_where_line (g->u.common.initt),
170 ffelex_token_where_column (g->u.common.initt));
171 ffebad_finish ();
174 /* Complain about just one attempt to reinit per program unit, but
175 continue referring back to the first such successful attempt. */
177 else
179 if (g->u.common.blank)
181 /* Not supposed to initialize blank common, though it works. */
182 ffebad_start (FFEBAD_COMMON_BLANK_INIT);
183 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
184 ffebad_finish ();
187 g->u.common.initt = ffelex_token_use (t);
190 g->tick = ffe_count_2;
191 #endif
194 /* ffeglobal_new_common -- New common block
196 ffesymbol s; // the ffesymbol for the new common block
197 ffelexToken t; // the token with the name of the common block
198 bool blank; // TRUE if blank common
199 ffeglobal_new_common(s,t,blank);
201 For back ends where file-wide global symbols are not maintained, does
202 nothing. Otherwise, makes sure this symbol hasn't been seen before or
203 is known as a common block. */
205 void
206 ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
208 #if FFEGLOBAL_ENABLED
209 ffename n;
210 ffeglobal g;
212 if (ffesymbol_global (s) == NULL)
214 n = ffename_find (ffeglobal_filewide_, t);
215 g = ffename_global (n);
217 else
219 g = ffesymbol_global (s);
220 n = NULL;
223 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
224 return;
226 if ((g != NULL) && (g->type != FFEGLOBAL_typeNONE))
228 if (g->type == FFEGLOBAL_typeCOMMON)
230 /* The names match, so the "blankness" should match too! */
231 assert (g->u.common.blank == blank);
233 else
235 /* This global name has already been established,
236 but as something other than a common block. */
237 if (ffe_is_globals () || ffe_is_warn_globals ())
239 ffebad_start (ffe_is_globals ()
240 ? FFEBAD_FILEWIDE_ALREADY_SEEN
241 : FFEBAD_FILEWIDE_ALREADY_SEEN_W);
242 ffebad_string (ffelex_token_text (t));
243 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
244 ffebad_here (1, ffelex_token_where_line (g->t),
245 ffelex_token_where_column (g->t));
246 ffebad_finish ();
248 g->type = FFEGLOBAL_typeANY;
251 else
253 if (g == NULL)
255 g = ffeglobal_new_ (n);
256 g->intrinsic = FALSE;
258 else if (g->intrinsic
259 && !g->explicit_intrinsic
260 && ffe_is_warn_globals ())
262 /* Common name previously used as intrinsic. Though it works,
263 warn, because the intrinsic reference might have been intended
264 as a ref to an external procedure, but g77's vast list of
265 intrinsics happened to snarf the name. */
266 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
267 ffebad_string (ffelex_token_text (t));
268 ffebad_string ("common block");
269 ffebad_string ("intrinsic");
270 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
271 ffebad_here (1, ffelex_token_where_line (g->t),
272 ffelex_token_where_column (g->t));
273 ffebad_finish ();
275 g->t = ffelex_token_use (t);
276 g->type = FFEGLOBAL_typeCOMMON;
277 g->u.common.have_pad = FALSE;
278 g->u.common.have_save = FALSE;
279 g->u.common.have_size = FALSE;
280 g->u.common.blank = blank;
283 ffesymbol_set_global (s, g);
284 #endif
287 /* ffeglobal_new_progunit_ -- New program unit
289 ffesymbol s; // the ffesymbol for the new unit
290 ffelexToken t; // the token with the name of the unit
291 ffeglobalType type; // the type of the new unit
292 ffeglobal_new_progunit_(s,t,type);
294 For back ends where file-wide global symbols are not maintained, does
295 nothing. Otherwise, makes sure this symbol hasn't been seen before. */
297 void
298 ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
300 #if FFEGLOBAL_ENABLED
301 ffename n;
302 ffeglobal g;
304 n = ffename_find (ffeglobal_filewide_, t);
305 g = ffename_global (n);
306 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
307 return;
309 if ((g != NULL)
310 && ((g->type == FFEGLOBAL_typeMAIN)
311 || (g->type == FFEGLOBAL_typeSUBR)
312 || (g->type == FFEGLOBAL_typeFUNC)
313 || (g->type == FFEGLOBAL_typeBDATA))
314 && g->u.proc.defined)
316 /* This program unit has already been defined. */
317 if (ffe_is_globals () || ffe_is_warn_globals ())
319 ffebad_start (ffe_is_globals ()
320 ? FFEBAD_FILEWIDE_ALREADY_SEEN
321 : FFEBAD_FILEWIDE_ALREADY_SEEN_W);
322 ffebad_string (ffelex_token_text (t));
323 ffebad_here (0, ffelex_token_where_line (t),
324 ffelex_token_where_column (t));
325 ffebad_here (1, ffelex_token_where_line (g->t),
326 ffelex_token_where_column (g->t));
327 ffebad_finish ();
329 g->type = FFEGLOBAL_typeANY;
331 else if ((g != NULL)
332 && (g->type != FFEGLOBAL_typeNONE)
333 && (g->type != FFEGLOBAL_typeEXT)
334 && (g->type != type))
336 /* A reference to this program unit has been seen, but its
337 context disagrees about the new definition regarding
338 what kind of program unit it is. (E.g. `call foo' followed
339 by `function foo'.) But `external foo' alone doesn't mean
340 disagreement with either a function or subroutine, though
341 g77 normally interprets it as a request to force-load
342 a block data program unit by that name (to cope with libs). */
343 if (ffe_is_globals () || ffe_is_warn_globals ())
345 ffebad_start (ffe_is_globals ()
346 ? FFEBAD_FILEWIDE_DISAGREEMENT
347 : FFEBAD_FILEWIDE_DISAGREEMENT_W);
348 ffebad_string (ffelex_token_text (t));
349 ffebad_string (ffeglobal_type_string_[type]);
350 ffebad_string (ffeglobal_type_string_[g->type]);
351 ffebad_here (0, ffelex_token_where_line (t),
352 ffelex_token_where_column (t));
353 ffebad_here (1, ffelex_token_where_line (g->t),
354 ffelex_token_where_column (g->t));
355 ffebad_finish ();
357 g->type = FFEGLOBAL_typeANY;
359 else
361 if (g == NULL)
363 g = ffeglobal_new_ (n);
364 g->intrinsic = FALSE;
365 g->u.proc.n_args = -1;
366 g->u.proc.other_t = NULL;
368 else if ((ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
369 && (g->type == FFEGLOBAL_typeFUNC)
370 && ((ffesymbol_basictype (s) != g->u.proc.bt)
371 || (ffesymbol_kindtype (s) != g->u.proc.kt)
372 || ((ffesymbol_size (s) != FFETARGET_charactersizeNONE)
373 && (ffesymbol_size (s) != g->u.proc.sz))))
375 /* The previous reference and this new function definition
376 disagree about the type of the function. I (Burley) think
377 this rarely occurs, because when this code is reached,
378 the type info doesn't appear to be filled in yet. */
379 if (ffe_is_globals () || ffe_is_warn_globals ())
381 ffebad_start (ffe_is_globals ()
382 ? FFEBAD_FILEWIDE_TYPE_MISMATCH
383 : FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
384 ffebad_string (ffelex_token_text (t));
385 ffebad_here (0, ffelex_token_where_line (t),
386 ffelex_token_where_column (t));
387 ffebad_here (1, ffelex_token_where_line (g->t),
388 ffelex_token_where_column (g->t));
389 ffebad_finish ();
391 g->type = FFEGLOBAL_typeANY;
392 return;
394 if (g->intrinsic
395 && !g->explicit_intrinsic
396 && ffe_is_warn_globals ())
398 /* This name, previously used as an intrinsic, now is known
399 to also be a global procedure name. Warn, since the previous
400 use as an intrinsic might have been intended to refer to
401 this procedure. */
402 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
403 ffebad_string (ffelex_token_text (t));
404 ffebad_string ("global");
405 ffebad_string ("intrinsic");
406 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
407 ffebad_here (1, ffelex_token_where_line (g->t),
408 ffelex_token_where_column (g->t));
409 ffebad_finish ();
411 g->t = ffelex_token_use (t);
412 if ((g->tick == 0)
413 || (g->u.proc.bt == FFEINFO_basictypeNONE)
414 || (g->u.proc.kt == FFEINFO_kindtypeNONE))
416 g->u.proc.bt = ffesymbol_basictype (s);
417 g->u.proc.kt = ffesymbol_kindtype (s);
418 g->u.proc.sz = ffesymbol_size (s);
420 /* If there's a known disagreement about the kind of program
421 unit, then don't even bother tracking arglist argreement. */
422 if ((g->tick != 0)
423 && (g->type != type))
424 g->u.proc.n_args = -1;
425 g->tick = ffe_count_2;
426 g->type = type;
427 g->u.proc.defined = TRUE;
430 ffesymbol_set_global (s, g);
431 #endif
434 /* ffeglobal_pad_common -- Check initial padding of common area
436 ffesymbol s; // the common area
437 ffetargetAlign pad; // the initial padding
438 ffeglobal_pad_common(s,pad,ffesymbol_where_line(s),
439 ffesymbol_where_column(s));
441 In global-enabled mode, make sure the padding agrees with any existing
442 padding established for the common area, otherwise complain.
443 In global-disabled mode, warn about nonzero padding. */
445 void
446 ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
447 ffewhereColumn wc)
449 #if FFEGLOBAL_ENABLED
450 ffeglobal g;
452 g = ffesymbol_global (s);
453 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
454 return; /* Let someone else catch this! */
455 if (g->type == FFEGLOBAL_typeANY)
456 return;
458 if (!g->u.common.have_pad)
460 g->u.common.have_pad = TRUE;
461 g->u.common.pad = pad;
462 g->u.common.pad_where_line = ffewhere_line_use (wl);
463 g->u.common.pad_where_col = ffewhere_column_use (wc);
465 if (pad != 0)
467 char padding[20];
469 sprintf (&padding[0], "%" ffetargetAlign_f "u", pad);
470 ffebad_start (FFEBAD_COMMON_INIT_PAD);
471 ffebad_string (ffesymbol_text (s));
472 ffebad_string (padding);
473 ffebad_string ((pad == 1)
474 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
475 ffebad_here (0, wl, wc);
476 ffebad_finish ();
479 else
481 if (g->u.common.pad != pad)
483 char padding_1[20];
484 char padding_2[20];
486 sprintf (&padding_1[0], "%" ffetargetAlign_f "u", pad);
487 sprintf (&padding_2[0], "%" ffetargetAlign_f "u", g->u.common.pad);
488 ffebad_start (FFEBAD_COMMON_DIFF_PAD);
489 ffebad_string (ffesymbol_text (s));
490 ffebad_string (padding_1);
491 ffebad_here (0, wl, wc);
492 ffebad_string (padding_2);
493 ffebad_string ((pad == 1)
494 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
495 ffebad_string ((g->u.common.pad == 1)
496 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
497 ffebad_here (1, g->u.common.pad_where_line, g->u.common.pad_where_col);
498 ffebad_finish ();
501 if (g->u.common.pad < pad)
503 g->u.common.pad = pad;
504 g->u.common.pad_where_line = ffewhere_line_use (wl);
505 g->u.common.pad_where_col = ffewhere_column_use (wc);
508 #endif
511 /* Collect info for a global's argument. */
513 void
514 ffeglobal_proc_def_arg (ffesymbol s, int argno, const char *name, ffeglobalArgSummary as,
515 ffeinfoBasictype bt, ffeinfoKindtype kt,
516 bool array)
518 ffeglobal g = ffesymbol_global (s);
519 ffeglobalArgInfo_ ai;
521 assert (g != NULL);
523 if (g->type == FFEGLOBAL_typeANY)
524 return;
526 assert (g->u.proc.n_args >= 0);
528 if (argno >= g->u.proc.n_args)
529 return; /* Already complained about this discrepancy. */
531 ai = &g->u.proc.arg_info[argno];
533 /* Maybe warn about previous references. */
535 if ((ai->t != NULL)
536 && ffe_is_warn_globals ())
538 const char *refwhy = NULL;
539 const char *defwhy = NULL;
540 bool warn = FALSE;
542 switch (as)
544 case FFEGLOBAL_argsummaryREF:
545 if ((ai->as != FFEGLOBAL_argsummaryREF)
546 && (ai->as != FFEGLOBAL_argsummaryNONE)
547 && ((ai->as != FFEGLOBAL_argsummaryDESCR) /* Choose better message. */
548 || (ai->bt != FFEINFO_basictypeCHARACTER)
549 || (ai->bt == bt)))
551 warn = TRUE;
552 refwhy = "passed by reference";
554 break;
556 case FFEGLOBAL_argsummaryDESCR:
557 if ((ai->as != FFEGLOBAL_argsummaryDESCR)
558 && (ai->as != FFEGLOBAL_argsummaryNONE)
559 && ((ai->as != FFEGLOBAL_argsummaryREF) /* Choose better message. */
560 || (bt != FFEINFO_basictypeCHARACTER)
561 || (ai->bt == bt)))
563 warn = TRUE;
564 refwhy = "passed by descriptor";
566 break;
568 case FFEGLOBAL_argsummaryPROC:
569 if ((ai->as != FFEGLOBAL_argsummaryPROC)
570 && (ai->as != FFEGLOBAL_argsummarySUBR)
571 && (ai->as != FFEGLOBAL_argsummaryFUNC)
572 && (ai->as != FFEGLOBAL_argsummaryNONE))
574 warn = TRUE;
575 refwhy = "a procedure";
577 break;
579 case FFEGLOBAL_argsummarySUBR:
580 if ((ai->as != FFEGLOBAL_argsummaryPROC)
581 && (ai->as != FFEGLOBAL_argsummarySUBR)
582 && (ai->as != FFEGLOBAL_argsummaryNONE))
584 warn = TRUE;
585 refwhy = "a subroutine";
587 break;
589 case FFEGLOBAL_argsummaryFUNC:
590 if ((ai->as != FFEGLOBAL_argsummaryPROC)
591 && (ai->as != FFEGLOBAL_argsummaryFUNC)
592 && (ai->as != FFEGLOBAL_argsummaryNONE))
594 warn = TRUE;
595 refwhy = "a function";
597 break;
599 case FFEGLOBAL_argsummaryALTRTN:
600 if ((ai->as != FFEGLOBAL_argsummaryALTRTN)
601 && (ai->as != FFEGLOBAL_argsummaryNONE))
603 warn = TRUE;
604 refwhy = "an alternate-return label";
606 break;
608 default:
609 break;
612 if ((refwhy != NULL) && (defwhy == NULL))
614 /* Fill in the def info. */
616 switch (ai->as)
618 case FFEGLOBAL_argsummaryNONE:
619 defwhy = "omitted";
620 break;
622 case FFEGLOBAL_argsummaryVAL:
623 defwhy = "passed by value";
624 break;
626 case FFEGLOBAL_argsummaryREF:
627 defwhy = "passed by reference";
628 break;
630 case FFEGLOBAL_argsummaryDESCR:
631 defwhy = "passed by descriptor";
632 break;
634 case FFEGLOBAL_argsummaryPROC:
635 defwhy = "a procedure";
636 break;
638 case FFEGLOBAL_argsummarySUBR:
639 defwhy = "a subroutine";
640 break;
642 case FFEGLOBAL_argsummaryFUNC:
643 defwhy = "a function";
644 break;
646 case FFEGLOBAL_argsummaryALTRTN:
647 defwhy = "an alternate-return label";
648 break;
650 #if 0
651 case FFEGLOBAL_argsummaryPTR:
652 defwhy = "a pointer";
653 break;
654 #endif
656 default:
657 defwhy = "???";
658 break;
662 if (!warn
663 && (bt != FFEINFO_basictypeHOLLERITH)
664 && (bt != FFEINFO_basictypeTYPELESS)
665 && (bt != FFEINFO_basictypeNONE)
666 && (ai->bt != FFEINFO_basictypeHOLLERITH)
667 && (ai->bt != FFEINFO_basictypeTYPELESS)
668 && (ai->bt != FFEINFO_basictypeNONE))
670 /* Check types. */
672 if ((bt != ai->bt)
673 && ((bt != FFEINFO_basictypeREAL)
674 || (ai->bt != FFEINFO_basictypeCOMPLEX))
675 && ((bt != FFEINFO_basictypeCOMPLEX)
676 || (ai->bt != FFEINFO_basictypeREAL)))
678 warn = TRUE; /* We can cope with these differences. */
679 refwhy = "one type";
680 defwhy = "some other type";
683 if (!warn && (kt != ai->kt))
685 warn = TRUE;
686 refwhy = "one precision";
687 defwhy = "some other precision";
691 if (warn)
693 char num[60];
695 if (name == NULL)
696 sprintf (&num[0], "%d", argno + 1);
697 else
699 if (strlen (name) < 30)
700 sprintf (&num[0], "%d (named `%s')", argno + 1, name);
701 else
702 sprintf (&num[0], "%d (named `%.*s...')", argno + 1, 30, name);
704 ffebad_start (FFEBAD_FILEWIDE_ARG_W);
705 ffebad_string (ffesymbol_text (s));
706 ffebad_string (num);
707 ffebad_string (refwhy);
708 ffebad_string (defwhy);
709 ffebad_here (0, ffelex_token_where_line (g->t), ffelex_token_where_column (g->t));
710 ffebad_here (1, ffelex_token_where_line (ai->t), ffelex_token_where_column (ai->t));
711 ffebad_finish ();
715 /* Define this argument. */
717 if (ai->t != NULL)
718 ffelex_token_kill (ai->t);
719 if ((as != FFEGLOBAL_argsummaryPROC)
720 || (ai->t == NULL))
721 ai->as = as; /* Otherwise leave SUBR/FUNC info intact. */
722 ai->t = ffelex_token_use (g->t);
723 if (name == NULL)
724 ai->name = NULL;
725 else
727 ai->name = malloc_new_ks (malloc_pool_image (),
728 "ffeglobalArgInfo_ name",
729 strlen (name) + 1);
730 strcpy (ai->name, name);
732 ai->bt = bt;
733 ai->kt = kt;
734 ai->array = array;
737 /* Collect info on #args a global accepts. */
739 void
740 ffeglobal_proc_def_nargs (ffesymbol s, int n_args)
742 ffeglobal g = ffesymbol_global (s);
744 assert (g != NULL);
746 if (g->type == FFEGLOBAL_typeANY)
747 return;
749 if (g->u.proc.n_args >= 0)
751 if (g->u.proc.n_args == n_args)
752 return;
754 if (ffe_is_warn_globals ())
756 ffebad_start (FFEBAD_FILEWIDE_NARGS_W);
757 ffebad_string (ffesymbol_text (s));
758 if (g->u.proc.n_args > n_args)
759 ffebad_string ("few");
760 else
761 ffebad_string ("many");
762 ffebad_here (0, ffelex_token_where_line (g->u.proc.other_t),
763 ffelex_token_where_column (g->u.proc.other_t));
764 ffebad_here (1, ffelex_token_where_line (g->t),
765 ffelex_token_where_column (g->t));
766 ffebad_finish ();
770 /* This is new info we can use in cross-checking future references
771 and a possible future definition. */
773 g->u.proc.n_args = n_args;
774 g->u.proc.other_t = NULL; /* No other reference yet. */
776 if (n_args == 0)
778 g->u.proc.arg_info = NULL;
779 return;
782 g->u.proc.arg_info = malloc_new_ks (malloc_pool_image (),
783 "ffeglobalArgInfo_",
784 n_args * sizeof (g->u.proc.arg_info[0]));
785 while (n_args-- > 0)
786 g->u.proc.arg_info[n_args].t = NULL;
789 /* Verify that the info for a global's argument is valid. */
791 bool
792 ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
793 ffeinfoBasictype bt, ffeinfoKindtype kt,
794 bool array, ffelexToken t)
796 ffeglobal g = ffesymbol_global (s);
797 ffeglobalArgInfo_ ai;
799 assert (g != NULL);
801 if (g->type == FFEGLOBAL_typeANY)
802 return FALSE;
804 assert (g->u.proc.n_args >= 0);
806 if (argno >= g->u.proc.n_args)
807 return TRUE; /* Already complained about this discrepancy. */
809 ai = &g->u.proc.arg_info[argno];
811 /* Warn about previous references. */
813 if (ai->t != NULL)
815 const char *refwhy = NULL;
816 const char *defwhy = NULL;
817 bool fail = FALSE;
818 bool warn = FALSE;
820 switch (as)
822 case FFEGLOBAL_argsummaryNONE:
823 if (g->u.proc.defined)
825 fail = TRUE;
826 refwhy = "omitted";
827 defwhy = "not optional";
829 break;
831 case FFEGLOBAL_argsummaryVAL:
832 if (ai->as != FFEGLOBAL_argsummaryVAL)
834 fail = TRUE;
835 refwhy = "passed by value";
837 break;
839 case FFEGLOBAL_argsummaryREF:
840 if ((ai->as != FFEGLOBAL_argsummaryREF)
841 && (ai->as != FFEGLOBAL_argsummaryNONE)
842 && ((ai->as != FFEGLOBAL_argsummaryDESCR) /* Choose better message. */
843 || (ai->bt != FFEINFO_basictypeCHARACTER)
844 || (ai->bt == bt)))
846 fail = TRUE;
847 refwhy = "passed by reference";
849 break;
851 case FFEGLOBAL_argsummaryDESCR:
852 if ((ai->as != FFEGLOBAL_argsummaryDESCR)
853 && (ai->as != FFEGLOBAL_argsummaryNONE)
854 && ((ai->as != FFEGLOBAL_argsummaryREF) /* Choose better message. */
855 || (bt != FFEINFO_basictypeCHARACTER)
856 || (ai->bt == bt)))
858 fail = TRUE;
859 refwhy = "passed by descriptor";
861 break;
863 case FFEGLOBAL_argsummaryPROC:
864 if ((ai->as != FFEGLOBAL_argsummaryPROC)
865 && (ai->as != FFEGLOBAL_argsummarySUBR)
866 && (ai->as != FFEGLOBAL_argsummaryFUNC)
867 && (ai->as != FFEGLOBAL_argsummaryNONE))
869 fail = TRUE;
870 refwhy = "a procedure";
872 break;
874 case FFEGLOBAL_argsummarySUBR:
875 if ((ai->as != FFEGLOBAL_argsummaryPROC)
876 && (ai->as != FFEGLOBAL_argsummarySUBR)
877 && (ai->as != FFEGLOBAL_argsummaryNONE))
879 fail = TRUE;
880 refwhy = "a subroutine";
882 break;
884 case FFEGLOBAL_argsummaryFUNC:
885 if ((ai->as != FFEGLOBAL_argsummaryPROC)
886 && (ai->as != FFEGLOBAL_argsummaryFUNC)
887 && (ai->as != FFEGLOBAL_argsummaryNONE))
889 fail = TRUE;
890 refwhy = "a function";
892 break;
894 case FFEGLOBAL_argsummaryALTRTN:
895 if ((ai->as != FFEGLOBAL_argsummaryALTRTN)
896 && (ai->as != FFEGLOBAL_argsummaryNONE))
898 fail = TRUE;
899 refwhy = "an alternate-return label";
901 break;
903 #if 0
904 case FFEGLOBAL_argsummaryPTR:
905 if ((ai->as != FFEGLOBAL_argsummaryPTR)
906 && (ai->as != FFEGLOBAL_argsummaryNONE))
908 fail = TRUE;
909 refwhy = "a pointer";
911 break;
912 #endif
914 default:
915 break;
918 if ((refwhy != NULL) && (defwhy == NULL))
920 /* Fill in the def info. */
922 switch (ai->as)
924 case FFEGLOBAL_argsummaryNONE:
925 defwhy = "omitted";
926 break;
928 case FFEGLOBAL_argsummaryVAL:
929 defwhy = "passed by value";
930 break;
932 case FFEGLOBAL_argsummaryREF:
933 defwhy = "passed by reference";
934 break;
936 case FFEGLOBAL_argsummaryDESCR:
937 defwhy = "passed by descriptor";
938 break;
940 case FFEGLOBAL_argsummaryPROC:
941 defwhy = "a procedure";
942 break;
944 case FFEGLOBAL_argsummarySUBR:
945 defwhy = "a subroutine";
946 break;
948 case FFEGLOBAL_argsummaryFUNC:
949 defwhy = "a function";
950 break;
952 case FFEGLOBAL_argsummaryALTRTN:
953 defwhy = "an alternate-return label";
954 break;
956 #if 0
957 case FFEGLOBAL_argsummaryPTR:
958 defwhy = "a pointer";
959 break;
960 #endif
962 default:
963 defwhy = "???";
964 break;
968 if (!fail && !warn
969 && (bt != FFEINFO_basictypeHOLLERITH)
970 && (bt != FFEINFO_basictypeTYPELESS)
971 && (bt != FFEINFO_basictypeNONE)
972 && (ai->bt != FFEINFO_basictypeHOLLERITH)
973 && (ai->bt != FFEINFO_basictypeNONE)
974 && (ai->bt != FFEINFO_basictypeTYPELESS))
976 /* Check types. */
978 if ((bt != ai->bt)
979 && ((bt != FFEINFO_basictypeREAL)
980 || (ai->bt != FFEINFO_basictypeCOMPLEX))
981 && ((bt != FFEINFO_basictypeCOMPLEX)
982 || (ai->bt != FFEINFO_basictypeREAL)))
984 if (((bt == FFEINFO_basictypeINTEGER)
985 && (ai->bt == FFEINFO_basictypeLOGICAL))
986 || ((bt == FFEINFO_basictypeLOGICAL)
987 && (ai->bt == FFEINFO_basictypeINTEGER)))
988 warn = TRUE; /* We can cope with these differences. */
989 else
990 fail = TRUE;
991 refwhy = "one type";
992 defwhy = "some other type";
995 if (!fail && !warn && (kt != ai->kt))
997 fail = TRUE;
998 refwhy = "one precision";
999 defwhy = "some other precision";
1003 if (fail && ! g->u.proc.defined)
1005 /* No point failing if we're worried only about invocations. */
1006 fail = FALSE;
1007 warn = TRUE;
1010 if (fail && ! ffe_is_globals ())
1012 warn = TRUE;
1013 fail = FALSE;
1016 if (fail || (warn && ffe_is_warn_globals ()))
1018 char num[60];
1020 if (ai->name == NULL)
1021 sprintf (&num[0], "%d", argno + 1);
1022 else
1024 if (strlen (ai->name) < 30)
1025 sprintf (&num[0], "%d (named `%s')", argno + 1, ai->name);
1026 else
1027 sprintf (&num[0], "%d (named `%.*s...')", argno + 1, 30, ai->name);
1029 ffebad_start (fail ? FFEBAD_FILEWIDE_ARG : FFEBAD_FILEWIDE_ARG_W);
1030 ffebad_string (ffesymbol_text (s));
1031 ffebad_string (num);
1032 ffebad_string (refwhy);
1033 ffebad_string (defwhy);
1034 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1035 ffebad_here (1, ffelex_token_where_line (ai->t), ffelex_token_where_column (ai->t));
1036 ffebad_finish ();
1037 return (fail ? FALSE : TRUE);
1040 if (warn)
1041 return TRUE;
1044 /* Define this argument. */
1046 if (ai->t != NULL)
1047 ffelex_token_kill (ai->t);
1048 if ((as != FFEGLOBAL_argsummaryPROC)
1049 || (ai->t == NULL))
1050 ai->as = as;
1051 ai->t = ffelex_token_use (g->t);
1052 ai->name = NULL;
1053 ai->bt = bt;
1054 ai->kt = kt;
1055 ai->array = array;
1056 return TRUE;
1059 bool
1060 ffeglobal_proc_ref_nargs (ffesymbol s, int n_args, ffelexToken t)
1062 ffeglobal g = ffesymbol_global (s);
1064 assert (g != NULL);
1066 if (g->type == FFEGLOBAL_typeANY)
1067 return FALSE;
1069 if (g->u.proc.n_args >= 0)
1071 if (g->u.proc.n_args == n_args)
1072 return TRUE;
1074 if (g->u.proc.defined && ffe_is_globals ())
1076 ffebad_start (FFEBAD_FILEWIDE_NARGS);
1077 ffebad_string (ffesymbol_text (s));
1078 if (g->u.proc.n_args > n_args)
1079 ffebad_string ("few");
1080 else
1081 ffebad_string ("many");
1082 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1083 ffebad_here (1, ffelex_token_where_line (g->t),
1084 ffelex_token_where_column (g->t));
1085 ffebad_finish ();
1086 return FALSE;
1089 if (ffe_is_warn_globals ())
1091 ffebad_start (FFEBAD_FILEWIDE_NARGS_W);
1092 ffebad_string (ffesymbol_text (s));
1093 if (g->u.proc.n_args > n_args)
1094 ffebad_string ("few");
1095 else
1096 ffebad_string ("many");
1097 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1098 ffebad_here (1, ffelex_token_where_line (g->t),
1099 ffelex_token_where_column (g->t));
1100 ffebad_finish ();
1103 return TRUE; /* Don't replace the info we already have. */
1106 /* This is new info we can use in cross-checking future references
1107 and a possible future definition. */
1109 g->u.proc.n_args = n_args;
1110 g->u.proc.other_t = ffelex_token_use (t);
1112 /* Make this "the" place we found the global, since it has the most info. */
1114 if (g->t != NULL)
1115 ffelex_token_kill (g->t);
1116 g->t = ffelex_token_use (t);
1118 if (n_args == 0)
1120 g->u.proc.arg_info = NULL;
1121 return TRUE;
1124 g->u.proc.arg_info = malloc_new_ks (malloc_pool_image (),
1125 "ffeglobalArgInfo_",
1126 n_args * sizeof (g->u.proc.arg_info[0]));
1127 while (n_args-- > 0)
1128 g->u.proc.arg_info[n_args].t = NULL;
1130 return TRUE;
1133 /* Return a global for a promoted symbol (one that has heretofore
1134 been assumed to be local, but since discovered to be global). */
1136 ffeglobal
1137 ffeglobal_promoted (ffesymbol s)
1139 #if FFEGLOBAL_ENABLED
1140 ffename n;
1141 ffeglobal g;
1143 assert (ffesymbol_global (s) == NULL);
1145 n = ffename_find (ffeglobal_filewide_, ffename_token (ffesymbol_name (s)));
1146 g = ffename_global (n);
1148 return g;
1149 #else
1150 return NULL;
1151 #endif
1154 /* Register a reference to an intrinsic. Such a reference is always
1155 valid, though a warning might be in order if the same name has
1156 already been used for a global. */
1158 void
1159 ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
1161 #if FFEGLOBAL_ENABLED
1162 ffename n;
1163 ffeglobal g;
1165 if (ffesymbol_global (s) == NULL)
1167 n = ffename_find (ffeglobal_filewide_, t);
1168 g = ffename_global (n);
1170 else
1172 g = ffesymbol_global (s);
1173 n = NULL;
1176 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
1177 return;
1179 if ((g != NULL) && (g->type != FFEGLOBAL_typeNONE))
1181 if (! explicit
1182 && ! g->intrinsic
1183 && ffe_is_warn_globals ())
1185 /* This name, previously used as a global, now is used
1186 for an intrinsic. Warn, since this new use as an
1187 intrinsic might have been intended to refer to
1188 the global procedure. */
1189 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
1190 ffebad_string (ffelex_token_text (t));
1191 ffebad_string ("intrinsic");
1192 ffebad_string ("global");
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));
1196 ffebad_finish ();
1199 else
1201 if (g == NULL)
1203 g = ffeglobal_new_ (n);
1204 g->tick = ffe_count_2;
1205 g->type = FFEGLOBAL_typeNONE;
1206 g->intrinsic = TRUE;
1207 g->explicit_intrinsic = explicit;
1208 g->t = ffelex_token_use (t);
1210 else if (g->intrinsic
1211 && (explicit != g->explicit_intrinsic)
1212 && (g->tick != ffe_count_2)
1213 && ffe_is_warn_globals ())
1215 /* An earlier reference to this intrinsic disagrees with
1216 this reference vis-a-vis explicit `intrinsic foo',
1217 which suggests that the one relying on implicit
1218 intrinsicacity might have actually intended to refer
1219 to a global of the same name. */
1220 ffebad_start (FFEBAD_INTRINSIC_EXPIMP);
1221 ffebad_string (ffelex_token_text (t));
1222 ffebad_string (explicit ? "explicit" : "implicit");
1223 ffebad_string (explicit ? "implicit" : "explicit");
1224 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1225 ffebad_here (1, ffelex_token_where_line (g->t),
1226 ffelex_token_where_column (g->t));
1227 ffebad_finish ();
1231 g->intrinsic = TRUE;
1232 if (explicit)
1233 g->explicit_intrinsic = TRUE;
1235 ffesymbol_set_global (s, g);
1236 #endif
1239 /* Register a reference to a global. Returns TRUE if the reference
1240 is valid. */
1242 bool
1243 ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
1245 #if FFEGLOBAL_ENABLED
1246 ffename n = NULL;
1247 ffeglobal g;
1249 /* It is never really _known_ that an EXTERNAL statement
1250 names a BLOCK DATA by just looking at the program unit,
1251 so override a different notion here. */
1252 if (type == FFEGLOBAL_typeBDATA)
1253 type = FFEGLOBAL_typeEXT;
1255 g = ffesymbol_global (s);
1256 if (g == NULL)
1258 n = ffename_find (ffeglobal_filewide_, t);
1259 g = ffename_global (n);
1260 if (g != NULL)
1261 ffesymbol_set_global (s, g);
1264 if ((g != NULL) && (g->type == FFEGLOBAL_typeANY))
1265 return TRUE;
1267 if ((g != NULL)
1268 && (g->type != FFEGLOBAL_typeNONE)
1269 && (g->type != FFEGLOBAL_typeEXT)
1270 && (g->type != type)
1271 && (type != FFEGLOBAL_typeEXT))
1273 /* Disagreement about (fully refined) class of program unit
1274 (main, subroutine, function, block data). Treat EXTERNAL/
1275 COMMON disagreements distinctly. */
1276 if ((((type == FFEGLOBAL_typeBDATA)
1277 && (g->type != FFEGLOBAL_typeCOMMON))
1278 || ((g->type == FFEGLOBAL_typeBDATA)
1279 && (type != FFEGLOBAL_typeCOMMON)
1280 && ! g->u.proc.defined)))
1282 #if 0 /* This is likely to just annoy people. */
1283 if (ffe_is_warn_globals ())
1285 /* Warn about EXTERNAL of a COMMON name, though it works. */
1286 ffebad_start (FFEBAD_FILEWIDE_TIFF);
1287 ffebad_string (ffelex_token_text (t));
1288 ffebad_string (ffeglobal_type_string_[type]);
1289 ffebad_string (ffeglobal_type_string_[g->type]);
1290 ffebad_here (0, ffelex_token_where_line (t),
1291 ffelex_token_where_column (t));
1292 ffebad_here (1, ffelex_token_where_line (g->t),
1293 ffelex_token_where_column (g->t));
1294 ffebad_finish ();
1296 #endif
1298 else if (ffe_is_globals () || ffe_is_warn_globals ())
1300 ffebad_start (ffe_is_globals ()
1301 ? FFEBAD_FILEWIDE_DISAGREEMENT
1302 : FFEBAD_FILEWIDE_DISAGREEMENT_W);
1303 ffebad_string (ffelex_token_text (t));
1304 ffebad_string (ffeglobal_type_string_[type]);
1305 ffebad_string (ffeglobal_type_string_[g->type]);
1306 ffebad_here (0, ffelex_token_where_line (t),
1307 ffelex_token_where_column (t));
1308 ffebad_here (1, ffelex_token_where_line (g->t),
1309 ffelex_token_where_column (g->t));
1310 ffebad_finish ();
1311 g->type = FFEGLOBAL_typeANY;
1312 return (! ffe_is_globals ());
1316 if ((g != NULL)
1317 && (type == FFEGLOBAL_typeFUNC))
1319 /* If just filling in this function's type, do so. */
1320 if ((g->tick == ffe_count_2)
1321 && (ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
1322 && (ffesymbol_kindtype (s) != FFEINFO_kindtypeNONE))
1324 g->u.proc.bt = ffesymbol_basictype (s);
1325 g->u.proc.kt = ffesymbol_kindtype (s);
1326 g->u.proc.sz = ffesymbol_size (s);
1328 /* Make sure there is type agreement. */
1329 if (g->type == FFEGLOBAL_typeFUNC
1330 && g->u.proc.bt != FFEINFO_basictypeNONE
1331 && ffesymbol_basictype (s) != FFEINFO_basictypeNONE
1332 && (ffesymbol_basictype (s) != g->u.proc.bt
1333 || ffesymbol_kindtype (s) != g->u.proc.kt
1334 /* CHARACTER*n disagreements matter only once a
1335 definition is involved, since the definition might
1336 be CHARACTER*(*), which accepts all references. */
1337 || (g->u.proc.defined
1338 && ffesymbol_size (s) != g->u.proc.sz
1339 && ffesymbol_size (s) != FFETARGET_charactersizeNONE
1340 && g->u.proc.sz != FFETARGET_charactersizeNONE)))
1342 int error;
1344 /* Type mismatch between function reference/definition and
1345 this subsequent reference (which might just be the filling-in
1346 of type info for the definition, but we can't reach here
1347 if that's the case and there was a previous definition).
1349 It's an error given a previous definition, since that
1350 implies inlining can crash the compiler, unless the user
1351 asked for no such inlining. */
1352 error = (g->tick != ffe_count_2
1353 && g->u.proc.defined
1354 && ffe_is_globals ());
1355 if (error || ffe_is_warn_globals ())
1357 ffebad_start (error
1358 ? FFEBAD_FILEWIDE_TYPE_MISMATCH
1359 : FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
1360 ffebad_string (ffelex_token_text (t));
1361 if (g->tick == ffe_count_2)
1363 /* Current reference fills in type info for definition.
1364 The current token doesn't necessarily point to the actual
1365 definition of the function, so use the definition pointer
1366 and the pointer to the pre-definition type info. */
1367 ffebad_here (0, ffelex_token_where_line (g->t),
1368 ffelex_token_where_column (g->t));
1369 ffebad_here (1, ffelex_token_where_line (g->u.proc.other_t),
1370 ffelex_token_where_column (g->u.proc.other_t));
1372 else
1374 /* Current reference is not a filling-in of a current
1375 definition. The current token is fine, as is
1376 the previous-mention token. */
1377 ffebad_here (0, ffelex_token_where_line (t),
1378 ffelex_token_where_column (t));
1379 ffebad_here (1, ffelex_token_where_line (g->t),
1380 ffelex_token_where_column (g->t));
1382 ffebad_finish ();
1383 if (error)
1384 g->type = FFEGLOBAL_typeANY;
1385 return FALSE;
1390 if (g == NULL)
1392 g = ffeglobal_new_ (n);
1393 g->t = ffelex_token_use (t);
1394 g->tick = ffe_count_2;
1395 g->intrinsic = FALSE;
1396 g->type = type;
1397 g->u.proc.defined = FALSE;
1398 g->u.proc.bt = ffesymbol_basictype (s);
1399 g->u.proc.kt = ffesymbol_kindtype (s);
1400 g->u.proc.sz = ffesymbol_size (s);
1401 g->u.proc.n_args = -1;
1402 ffesymbol_set_global (s, g);
1404 else if (g->intrinsic
1405 && !g->explicit_intrinsic
1406 && (g->tick != ffe_count_2)
1407 && ffe_is_warn_globals ())
1409 /* Now known as a global, this name previously was seen as an
1410 intrinsic. Warn, in case the previous reference was intended
1411 for the same global. */
1412 ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
1413 ffebad_string (ffelex_token_text (t));
1414 ffebad_string ("global");
1415 ffebad_string ("intrinsic");
1416 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1417 ffebad_here (1, ffelex_token_where_line (g->t),
1418 ffelex_token_where_column (g->t));
1419 ffebad_finish ();
1422 if ((g->type != type)
1423 && (type != FFEGLOBAL_typeEXT))
1425 /* We've learned more, so point to where we learned it. */
1426 g->t = ffelex_token_use (t);
1427 g->type = type;
1428 g->hook = FFECOM_globalNULL; /* Discard previous _DECL. */
1429 g->u.proc.n_args = -1;
1432 return TRUE;
1433 #endif
1436 /* ffeglobal_save_common -- Check SAVE status of common area
1438 ffesymbol s; // the common area
1439 bool save; // TRUE if SAVEd, FALSE otherwise
1440 ffeglobal_save_common(s,save,ffesymbol_where_line(s),
1441 ffesymbol_where_column(s));
1443 In global-enabled mode, make sure the save info agrees with any existing
1444 info established for the common area, otherwise complain.
1445 In global-disabled mode, do nothing. */
1447 void
1448 ffeglobal_save_common (ffesymbol s, bool save, ffewhereLine wl,
1449 ffewhereColumn wc)
1451 #if FFEGLOBAL_ENABLED
1452 ffeglobal g;
1454 g = ffesymbol_global (s);
1455 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
1456 return; /* Let someone else catch this! */
1457 if (g->type == FFEGLOBAL_typeANY)
1458 return;
1460 if (!g->u.common.have_save)
1462 g->u.common.have_save = TRUE;
1463 g->u.common.save = save;
1464 g->u.common.save_where_line = ffewhere_line_use (wl);
1465 g->u.common.save_where_col = ffewhere_column_use (wc);
1467 else
1469 if ((g->u.common.save != save) && ffe_is_pedantic ())
1471 ffebad_start (FFEBAD_COMMON_DIFF_SAVE);
1472 ffebad_string (ffesymbol_text (s));
1473 ffebad_here (save ? 0 : 1, wl, wc);
1474 ffebad_here (save ? 1 : 0, g->u.common.pad_where_line, g->u.common.pad_where_col);
1475 ffebad_finish ();
1478 #endif
1481 /* ffeglobal_size_common -- Establish size of COMMON area
1483 ffesymbol s; // the common area
1484 ffetargetOffset size; // size in units
1485 if (ffeglobal_size_common(s,size)) // new size is largest seen
1487 In global-enabled mode, set the size if it current size isn't known or is
1488 smaller than new size, and for non-blank common, complain if old size
1489 is different from new. Return TRUE if the new size is the largest seen
1490 for this COMMON area (or if no size was known for it previously).
1491 In global-disabled mode, do nothing. */
1493 #if FFEGLOBAL_ENABLED
1494 bool
1495 ffeglobal_size_common (ffesymbol s, ffetargetOffset size)
1497 ffeglobal g;
1499 g = ffesymbol_global (s);
1500 if ((g == NULL) || (g->type != FFEGLOBAL_typeCOMMON))
1501 return FALSE;
1502 if (g->type == FFEGLOBAL_typeANY)
1503 return FALSE;
1505 if (!g->u.common.have_size)
1507 g->u.common.have_size = TRUE;
1508 g->u.common.size = size;
1509 return TRUE;
1512 if ((g->tick > 0) && (g->tick < ffe_count_2)
1513 && (g->u.common.size < size))
1515 char oldsize[40];
1516 char newsize[40];
1518 /* Common block initialized in a previous program unit, which
1519 effectively freezes its size, but now the program is trying
1520 to enlarge it. */
1522 sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
1523 sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
1525 ffebad_start (FFEBAD_COMMON_ENLARGED);
1526 ffebad_string (ffesymbol_text (s));
1527 ffebad_string (oldsize);
1528 ffebad_string (newsize);
1529 ffebad_string ((g->u.common.size == 1)
1530 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1531 ffebad_string ((size == 1)
1532 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1533 ffebad_here (0, ffelex_token_where_line (g->u.common.initt),
1534 ffelex_token_where_column (g->u.common.initt));
1535 ffebad_here (1, ffesymbol_where_line (s),
1536 ffesymbol_where_column (s));
1537 ffebad_finish ();
1539 else if ((g->u.common.size != size) && !g->u.common.blank)
1541 char oldsize[40];
1542 char newsize[40];
1544 /* Warn about this even if not -pedantic, because putting all
1545 program units in a single source file is the only way to
1546 detect this. Apparently UNIX-model linkers neither handle
1547 nor report when they make a common unit smaller than
1548 requested, such as when the smaller-declared version is
1549 initialized and the larger-declared version is not. So
1550 if people complain about strange overwriting, we can tell
1551 them to put all their code in a single file and compile
1552 that way. Warnings about differing sizes must therefore
1553 always be issued. */
1555 sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
1556 sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
1558 ffebad_start (FFEBAD_COMMON_DIFF_SIZE);
1559 ffebad_string (ffesymbol_text (s));
1560 ffebad_string (oldsize);
1561 ffebad_string (newsize);
1562 ffebad_string ((g->u.common.size == 1)
1563 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1564 ffebad_string ((size == 1)
1565 ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
1566 ffebad_here (0, ffelex_token_where_line (g->t),
1567 ffelex_token_where_column (g->t));
1568 ffebad_here (1, ffesymbol_where_line (s),
1569 ffesymbol_where_column (s));
1570 ffebad_finish ();
1573 if (size > g->u.common.size)
1575 g->u.common.size = size;
1576 return TRUE;
1579 return FALSE;
1582 #endif
1583 void
1584 ffeglobal_terminate_1 (void)