OSDN Git Service

2001-07-20 Toon Moene <toon@moene.indiv.nluug.nl>
[pf3gnuchains/gcc-fork.git] / gcc / f / global.c
index a2251b7..85311f1 100644 (file)
@@ -1,6 +1,6 @@
 /* global.c -- Implementation File (module.c template V1.0)
    Copyright (C) 1995, 1997 Free Software Foundation, Inc.
-   Contributed by James Craig Burley (burley@gnu.org).
+   Contributed by James Craig Burley.
 
 This file is part of GNU Fortran.
 
@@ -60,7 +60,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #if FFEGLOBAL_ENABLED
 static ffenameSpace ffeglobal_filewide_ = NULL;
-static char *ffeglobal_type_string_[] =
+static const char *ffeglobal_type_string_[] =
 {
   [FFEGLOBAL_typeNONE] "??",
   [FFEGLOBAL_typeMAIN] "main program",
@@ -86,7 +86,7 @@ static char *ffeglobal_type_string_[] =
 
 #if FFEGLOBAL_ENABLED
 void
-ffeglobal_drive (ffeglobal (*fn) ())
+ffeglobal_drive (ffeglobal (*fn) (ffeglobal))
 {
   if (ffeglobal_filewide_ != NULL)
     ffename_space_drive_global (ffeglobal_filewide_, fn);
@@ -181,6 +181,7 @@ ffeglobal_init_common (ffesymbol s, ffelexToken t)
     {
       if (g->u.common.blank)
        {
+         /* Not supposed to initialize blank common, though it works.  */
          ffebad_start (FFEBAD_COMMON_BLANK_INIT);
          ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
          ffebad_finish ();
@@ -229,10 +230,13 @@ ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
     {
       if (g->type == FFEGLOBAL_typeCOMMON)
        {
+         /* The names match, so the "blankness" should match too!  */
          assert (g->u.common.blank == blank);
        }
       else
        {
+         /* This global name has already been established,
+            but as something other than a common block.  */
          if (ffe_is_globals () || ffe_is_warn_globals ())
            {
              ffebad_start (ffe_is_globals ()
@@ -258,6 +262,10 @@ ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
               && !g->explicit_intrinsic
               && ffe_is_warn_globals ())
        {
+         /* Common name previously used as intrinsic.  Though it works,
+            warn, because the intrinsic reference might have been intended
+            as a ref to an external procedure, but g77's vast list of
+            intrinsics happened to snarf the name.  */
          ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
          ffebad_string (ffelex_token_text (t));
          ffebad_string ("common block");
@@ -308,6 +316,7 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
          || (g->type == FFEGLOBAL_typeBDATA))
       && g->u.proc.defined)
     {
+      /* This program unit has already been defined.  */
       if (ffe_is_globals () || ffe_is_warn_globals ())
        {
          ffebad_start (ffe_is_globals ()
@@ -327,6 +336,13 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
           && (g->type != FFEGLOBAL_typeEXT)
           && (g->type != type))
     {
+      /* A reference to this program unit has been seen, but its
+        context disagrees about the new definition regarding
+        what kind of program unit it is.  (E.g. `call foo' followed
+        by `function foo'.)  But `external foo' alone doesn't mean
+        disagreement with either a function or subroutine, though
+        g77 normally interprets it as a request to force-load
+        a block data program unit by that name (to cope with libs).  */
       if (ffe_is_globals () || ffe_is_warn_globals ())
        {
          ffebad_start (ffe_is_globals ()
@@ -353,11 +369,16 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
          g->u.proc.other_t = NULL;
        }
       else if ((ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
+              && (g->type == FFEGLOBAL_typeFUNC)
               && ((ffesymbol_basictype (s) != g->u.proc.bt)
                   || (ffesymbol_kindtype (s) != g->u.proc.kt)
                   || ((ffesymbol_size (s) != FFETARGET_charactersizeNONE)
                       && (ffesymbol_size (s) != g->u.proc.sz))))
        {
+         /* The previous reference and this new function definition
+            disagree about the type of the function.  I (Burley) think
+            this rarely occurs, because when this code is reached,
+            the type info doesn't appear to be filled in yet.  */
          if (ffe_is_globals () || ffe_is_warn_globals ())
            {
              ffebad_start (ffe_is_globals ()
@@ -377,6 +398,10 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
          && !g->explicit_intrinsic
          && ffe_is_warn_globals ())
        {
+         /* This name, previously used as an intrinsic, now is known
+            to also be a global procedure name.  Warn, since the previous
+            use as an intrinsic might have been intended to refer to
+            this procedure.  */
          ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
          ffebad_string (ffelex_token_text (t));
          ffebad_string ("global");
@@ -395,10 +420,12 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
          g->u.proc.kt = ffesymbol_kindtype (s);
          g->u.proc.sz = ffesymbol_size (s);
        }
-      g->tick = ffe_count_2;
+      /* If there's a known disagreement about the kind of program
+        unit, then don't even bother tracking arglist argreement.  */
       if ((g->tick != 0)
          && (g->type != type))
        g->u.proc.n_args = -1;
+      g->tick = ffe_count_2;
       g->type = type;
       g->u.proc.defined = TRUE;
     }
@@ -437,6 +464,20 @@ ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
       g->u.common.pad = pad;
       g->u.common.pad_where_line = ffewhere_line_use (wl);
       g->u.common.pad_where_col = ffewhere_column_use (wc);
+
+      if (pad != 0)
+       {
+         char padding[20];
+
+         sprintf (&padding[0], "%" ffetargetAlign_f "u", pad);
+         ffebad_start (FFEBAD_COMMON_INIT_PAD);
+         ffebad_string (ffesymbol_text (s));
+         ffebad_string (padding);
+         ffebad_string ((pad == 1)
+                        ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
+         ffebad_here (0, wl, wc);
+         ffebad_finish ();
+       }
     }
   else
     {
@@ -459,28 +500,21 @@ ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
          ffebad_here (1, g->u.common.pad_where_line, g->u.common.pad_where_col);
          ffebad_finish ();
        }
-    }
-#endif
-
-  if (pad != 0)
-    {                          /* Warn about initial padding in common area. */
-      char padding[20];
 
-      sprintf (&padding[0], "%" ffetargetAlign_f "u", pad);
-      ffebad_start (FFEBAD_COMMON_INIT_PAD);
-      ffebad_string (ffesymbol_text (s));
-      ffebad_string (padding);
-      ffebad_string ((pad == 1)
-                    ? FFECOM_SIZE_UNIT : FFECOM_SIZE_UNITS);
-      ffebad_here (0, wl, wc);
-      ffebad_finish ();
+      if (g->u.common.pad < pad)
+       {
+         g->u.common.pad = pad;
+         g->u.common.pad_where_line = ffewhere_line_use (wl);
+         g->u.common.pad_where_col = ffewhere_column_use (wc);
+       }
     }
+#endif
 }
 
 /* Collect info for a global's argument.  */
 
 void
-ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary as,
+ffeglobal_proc_def_arg (ffesymbol s, int argno, const char *name, ffeglobalArgSummary as,
                        ffeinfoBasictype bt, ffeinfoKindtype kt,
                        bool array)
 {
@@ -504,8 +538,8 @@ ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary
   if ((ai->t != NULL)
       && ffe_is_warn_globals ())
     {
-      char *refwhy = NULL;
-      char *defwhy = NULL;
+      const char *refwhy = NULL;
+      const char *defwhy = NULL;
       bool warn = FALSE;
 
       switch (as)
@@ -616,9 +650,11 @@ ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary
              defwhy = "an alternate-return label";
              break;
 
+#if 0
            case FFEGLOBAL_argsummaryPTR:
              defwhy = "a pointer";
              break;
+#endif
 
            default:
              defwhy = "???";
@@ -780,8 +816,8 @@ ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
 
   if (ai->t != NULL)
     {
-      char *refwhy = NULL;
-      char *defwhy = NULL;
+      const char *refwhy = NULL;
+      const char *defwhy = NULL;
       bool fail = FALSE;
       bool warn = FALSE;
 
@@ -868,6 +904,7 @@ ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
            }
          break;
 
+#if 0
        case FFEGLOBAL_argsummaryPTR:
          if ((ai->as != FFEGLOBAL_argsummaryPTR)
              && (ai->as != FFEGLOBAL_argsummaryNONE))
@@ -876,6 +913,7 @@ ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
              refwhy = "a pointer";
            }
          break;
+#endif
 
        default:
          break;
@@ -919,9 +957,11 @@ ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
              defwhy = "an alternate-return label";
              break;
 
+#if 0
            case FFEGLOBAL_argsummaryPTR:
              defwhy = "a pointer";
              break;
+#endif
 
            default:
              defwhy = "???";
@@ -1147,6 +1187,10 @@ ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
          && ! g->intrinsic
          && ffe_is_warn_globals ())
        {
+         /* This name, previously used as a global, now is used
+            for an intrinsic.  Warn, since this new use as an
+            intrinsic might have been intended to refer to
+            the global procedure.  */
          ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
          ffebad_string (ffelex_token_text (t));
          ffebad_string ("intrinsic");
@@ -1173,6 +1217,11 @@ ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
               && (g->tick != ffe_count_2)
               && ffe_is_warn_globals ())
        {
+         /* An earlier reference to this intrinsic disagrees with
+            this reference vis-a-vis explicit `intrinsic foo',
+            which suggests that the one relying on implicit
+            intrinsicacity might have actually intended to refer
+            to a global of the same name.  */
          ffebad_start (FFEBAD_INTRINSIC_EXPIMP);
          ffebad_string (ffelex_token_text (t));
          ffebad_string (explicit ? "explicit" : "implicit");
@@ -1222,10 +1271,13 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
 
   if ((g != NULL)
       && (g->type != FFEGLOBAL_typeNONE)
-      && (g->type != type)
       && (g->type != FFEGLOBAL_typeEXT)
+      && (g->type != type)
       && (type != FFEGLOBAL_typeEXT))
     {
+      /* Disagreement about (fully refined) class of program unit
+        (main, subroutine, function, block data).  Treat EXTERNAL/
+        COMMON disagreements distinctly.  */
       if ((((type == FFEGLOBAL_typeBDATA)
            && (g->type != FFEGLOBAL_typeCOMMON))
           || ((g->type == FFEGLOBAL_typeBDATA)
@@ -1235,6 +1287,7 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
 #if 0  /* This is likely to just annoy people. */
          if (ffe_is_warn_globals ())
            {
+             /* Warn about EXTERNAL of a COMMON name, though it works.  */
              ffebad_start (FFEBAD_FILEWIDE_TIFF);
              ffebad_string (ffelex_token_text (t));
              ffebad_string (ffeglobal_type_string_[type]);
@@ -1247,23 +1300,11 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
            }
 #endif
        }
-      else if (ffe_is_globals ())
+      else if (ffe_is_globals () || ffe_is_warn_globals ())
        {
-         ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT);
-         ffebad_string (ffelex_token_text (t));
-         ffebad_string (ffeglobal_type_string_[type]);
-         ffebad_string (ffeglobal_type_string_[g->type]);
-         ffebad_here (0, ffelex_token_where_line (t),
-                      ffelex_token_where_column (t));
-         ffebad_here (1, ffelex_token_where_line (g->t),
-                      ffelex_token_where_column (g->t));
-         ffebad_finish ();
-         g->type = FFEGLOBAL_typeANY;
-         return FALSE;
-       }
-      else if (ffe_is_warn_globals ())
-       {
-         ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT_W);
+         ffebad_start (ffe_is_globals ()
+                       ? FFEBAD_FILEWIDE_DISAGREEMENT
+                       : FFEBAD_FILEWIDE_DISAGREEMENT_W);
          ffebad_string (ffelex_token_text (t));
          ffebad_string (ffeglobal_type_string_[type]);
          ffebad_string (ffeglobal_type_string_[g->type]);
@@ -1273,7 +1314,7 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
                       ffelex_token_where_column (g->t));
          ffebad_finish ();
          g->type = FFEGLOBAL_typeANY;
-         return TRUE;
+         return (! ffe_is_globals ());
        }
     }
 
@@ -1289,39 +1330,65 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
          g->u.proc.kt = ffesymbol_kindtype (s);
          g->u.proc.sz = ffesymbol_size (s);
        }
-      /* Else, make sure there is type agreement.  */
-      else if ((g->u.proc.bt != FFEINFO_basictypeNONE)
-              && (ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
-              && ((ffesymbol_basictype (s) != g->u.proc.bt)
-                  || (ffesymbol_kindtype (s) != g->u.proc.kt)
-                  || ((ffesymbol_size (s) != g->u.proc.sz)
-                      && g->u.proc.defined
-                      && (g->u.proc.sz != FFETARGET_charactersizeNONE))))
+      /* Make sure there is type agreement.  */
+      if (g->type == FFEGLOBAL_typeFUNC
+         && g->u.proc.bt != FFEINFO_basictypeNONE
+         && ffesymbol_basictype (s) != FFEINFO_basictypeNONE
+         && (ffesymbol_basictype (s) != g->u.proc.bt
+             || ffesymbol_kindtype (s) != g->u.proc.kt
+             /* CHARACTER*n disagreements matter only once a
+                definition is involved, since the definition might
+                be CHARACTER*(*), which accepts all references.  */
+             || (g->u.proc.defined
+                 && ffesymbol_size (s) != g->u.proc.sz
+                 && ffesymbol_size (s) != FFETARGET_charactersizeNONE
+                 && g->u.proc.sz != FFETARGET_charactersizeNONE)))
        {
-         if (ffe_is_globals ())
+         int error;
+
+         /* Type mismatch between function reference/definition and
+            this subsequent reference (which might just be the filling-in
+            of type info for the definition, but we can't reach here
+            if that's the case and there was a previous definition).
+
+            It's an error given a previous definition, since that
+            implies inlining can crash the compiler, unless the user
+            asked for no such inlining.  */
+         error = (g->tick != ffe_count_2
+                  && g->u.proc.defined
+                  && ffe_is_globals ());
+         if (error || ffe_is_warn_globals ())
            {
-             ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH);
+             ffebad_start (error
+                           ? FFEBAD_FILEWIDE_TYPE_MISMATCH
+                           : FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
              ffebad_string (ffelex_token_text (t));
-             ffebad_here (0, ffelex_token_where_line (t),
-                          ffelex_token_where_column (t));
-             ffebad_here (1, ffelex_token_where_line (g->t),
-                          ffelex_token_where_column (g->t));
+             if (g->tick == ffe_count_2)
+               {
+                 /* Current reference fills in type info for definition.
+                    The current token doesn't necessarily point to the actual
+                    definition of the function, so use the definition pointer
+                    and the pointer to the pre-definition type info.  */
+                 ffebad_here (0, ffelex_token_where_line (g->t),
+                              ffelex_token_where_column (g->t));
+                 ffebad_here (1, ffelex_token_where_line (g->u.proc.other_t),
+                              ffelex_token_where_column (g->u.proc.other_t));
+               }
+             else
+               {
+                 /* Current reference is not a filling-in of a current
+                    definition.  The current token is fine, as is
+                    the previous-mention token.  */
+                 ffebad_here (0, ffelex_token_where_line (t),
+                              ffelex_token_where_column (t));
+                 ffebad_here (1, ffelex_token_where_line (g->t),
+                              ffelex_token_where_column (g->t));
+               }
              ffebad_finish ();
-             g->type = FFEGLOBAL_typeANY;
+             if (error)
+               g->type = FFEGLOBAL_typeANY;
              return FALSE;
            }
-         if (ffe_is_warn_globals ())
-           {
-             ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
-             ffebad_string (ffelex_token_text (t));
-             ffebad_here (0, ffelex_token_where_line (t),
-                          ffelex_token_where_column (t));
-             ffebad_here (1, ffelex_token_where_line (g->t),
-                          ffelex_token_where_column (g->t));
-             ffebad_finish ();
-           }
-         g->type = FFEGLOBAL_typeANY;
-         return TRUE;
        }
     }
 
@@ -1344,6 +1411,9 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
           && (g->tick != ffe_count_2)
           && ffe_is_warn_globals ())
     {
+      /* Now known as a global, this name previously was seen as an
+        intrinsic.  Warn, in case the previous reference was intended
+        for the same global.  */
       ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
       ffebad_string (ffelex_token_text (t));
       ffebad_string ("global");
@@ -1418,7 +1488,7 @@ ffeglobal_save_common (ffesymbol s, bool save, ffewhereLine wl,
 /* ffeglobal_size_common -- Establish size of COMMON area
 
    ffesymbol s;         // the common area
-   long size;  // size in units
+   ffetargetOffset size;  // size in units
    if (ffeglobal_size_common(s,size))  // new size is largest seen
 
    In global-enabled mode, set the size if it current size isn't known or is
@@ -1429,7 +1499,7 @@ ffeglobal_save_common (ffesymbol s, bool save, ffewhereLine wl,
 
 #if FFEGLOBAL_ENABLED
 bool
-ffeglobal_size_common (ffesymbol s, long size)
+ffeglobal_size_common (ffesymbol s, ffetargetOffset size)
 {
   ffeglobal g;
 
@@ -1446,13 +1516,18 @@ ffeglobal_size_common (ffesymbol s, long size)
       return TRUE;
     }
 
-  if ((g->u.common.size < size) && (g->tick > 0) && (g->tick < ffe_count_2))
+  if ((g->tick > 0) && (g->tick < ffe_count_2)
+      && (g->u.common.size < size))
     {
       char oldsize[40];
       char newsize[40];
 
-      sprintf (&oldsize[0], "%ld", g->u.common.size);
-      sprintf (&newsize[0], "%ld", size);
+      /* Common block initialized in a previous program unit, which
+        effectively freezes its size, but now the program is trying
+        to enlarge it.  */
+
+      sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
+      sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
 
       ffebad_start (FFEBAD_COMMON_ENLARGED);
       ffebad_string (ffesymbol_text (s));
@@ -1484,8 +1559,8 @@ ffeglobal_size_common (ffesymbol s, long size)
         that way.  Warnings about differing sizes must therefore
         always be issued.  */
 
-      sprintf (&oldsize[0], "%ld", g->u.common.size);
-      sprintf (&newsize[0], "%ld", size);
+      sprintf (&oldsize[0], "%" ffetargetOffset_f "d", g->u.common.size);
+      sprintf (&newsize[0], "%" ffetargetOffset_f "d", size);
 
       ffebad_start (FFEBAD_COMMON_DIFF_SIZE);
       ffebad_string (ffesymbol_text (s));
@@ -1507,6 +1582,7 @@ ffeglobal_size_common (ffesymbol s, long size)
       g->u.common.size = size;
       return TRUE;
     }
+
   return FALSE;
 }