OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index b249f30..aa3c809 100644 (file)
@@ -594,6 +594,56 @@ resolve_entries (gfc_namespace *ns)
 }
 
 
+/* Resolve common blocks.  */
+static void
+resolve_common_blocks (gfc_symtree *common_root)
+{
+   gfc_symtree *symtree;
+   gfc_symbol *sym;
+
+   if (common_root == NULL)
+     return;
+
+   for (symtree = common_root; symtree->left; symtree = symtree->left);
+
+   for (; symtree; symtree = symtree->right)
+     {
+       gfc_find_symbol (symtree->name, gfc_current_ns, 0, &sym);
+       if (sym == NULL)
+         continue;
+
+       if (sym->attr.flavor == FL_PARAMETER)
+         {
+           gfc_error ("COMMON block '%s' at %L is used as PARAMETER at %L",
+                      sym->name, &symtree->n.common->where,
+                      &sym->declared_at);
+         }
+
+       if (sym->attr.intrinsic)
+         {
+           gfc_error ("COMMON block '%s' at %L is also an intrinsic "
+                      "procedure", sym->name,
+                      &symtree->n.common->where);
+         }
+       else if (sym->attr.result
+                ||(sym->attr.function && gfc_current_ns->proc_name == sym))
+         {
+           gfc_notify_std (GFC_STD_F2003, "Fortran 2003: COMMON block '%s' "
+                           "at %L that is also a function result", sym->name,
+                           &symtree->n.common->where);
+         }
+       else if (sym->attr.flavor == FL_PROCEDURE
+               && sym->attr.proc != PROC_INTERNAL
+               && sym->attr.proc != PROC_ST_FUNCTION)
+         {
+           gfc_notify_std (GFC_STD_F2003, "Fortran 2003: COMMON block '%s' "
+                           "at %L that is also a global procedure", sym->name,
+                           &symtree->n.common->where);
+         }
+     }
+}
+
+
 /* Resolve contained function types.  Because contained functions can call one
    another, they have to be worked out before any of the contained procedures
    can be resolved.
@@ -1502,6 +1552,22 @@ set_type:
 }
 
 
+/* Return true, if the symbol is an external procedure.  */
+static bool
+is_external_proc (gfc_symbol *sym)
+{
+  if (!sym->attr.dummy && !sym->attr.contained
+       && !(sym->attr.intrinsic
+             || gfc_intrinsic_name (sym->name, sym->attr.subroutine))
+       && sym->attr.proc != PROC_ST_FUNCTION
+       && !sym->attr.use_assoc
+       && sym->name)
+    return true;
+  else
+    return false;
+}
+
+
 /* Figure out if a function reference is pure or not.  Also set the name
    of the function for a potential error message.  Return nonzero if the
    function is PURE, zero if not.  */
@@ -1651,6 +1717,15 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
   try retval = SUCCESS;
   gfc_symbol *args_sym;
 
+  if (args->expr->expr_type == EXPR_CONSTANT
+      || args->expr->expr_type == EXPR_OP
+      || args->expr->expr_type == EXPR_NULL)
+    {
+      gfc_error ("Argument to '%s' at %L is not a variable",
+                sym->name, &(args->expr->where));
+      return FAILURE;
+    }
+
   args_sym = args->expr->symtree->n.sym;
    
   if (sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)
@@ -1843,12 +1918,8 @@ resolve_function (gfc_expr *expr)
       return FAILURE;
     }
 
-  /* If the procedure is not internal, a statement function or a module
-     procedure,it must be external and should be checked for usage.  */
-  if (sym && !sym->attr.dummy && !sym->attr.contained
-      && sym->attr.proc != PROC_ST_FUNCTION
-      && !sym->attr.use_assoc
-      && sym->name  )
+  /* If the procedure is external, check for usage.  */
+  if (sym && is_external_proc (sym))
     resolve_global_procedure (sym, &expr->where, 0);
 
   /* Switch off assumed size checking and do this again for certain kinds
@@ -2440,12 +2511,8 @@ resolve_call (gfc_code *c)
       return FAILURE;
     }
 
-  /* If the procedure is not internal or module, it must be external and
-     should be checked for usage.  */
-  if (c->symtree && c->symtree->n.sym
-      && !c->symtree->n.sym->attr.dummy
-      && !c->symtree->n.sym->attr.contained
-      && !c->symtree->n.sym->attr.use_assoc)
+  /* If external, check for usage.  */
+  if (c->symtree && is_external_proc (c->symtree->n.sym))
     resolve_global_procedure (c->symtree->n.sym, &c->loc, 1);
 
   /* Subroutines without the RECURSIVE attribution are not allowed to
@@ -2665,14 +2732,18 @@ resolve_operator (gfc_expr *e)
          break;
        }
 
-      sprintf (msg, _("Operand of .NOT. operator at %%L is %s"),
+      sprintf (msg, _("Operand of .not. operator at %%L is %s"),
               gfc_typename (&op1->ts));
       goto bad_op;
 
     case INTRINSIC_GT:
+    case INTRINSIC_GT_OS:
     case INTRINSIC_GE:
+    case INTRINSIC_GE_OS:
     case INTRINSIC_LT:
+    case INTRINSIC_LT_OS:
     case INTRINSIC_LE:
+    case INTRINSIC_LE_OS:
       if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX)
        {
          strcpy (msg, _("COMPLEX quantities cannot be compared at %L"));
@@ -2682,7 +2753,9 @@ resolve_operator (gfc_expr *e)
       /* Fall through...  */
 
     case INTRINSIC_EQ:
+    case INTRINSIC_EQ_OS:
     case INTRINSIC_NE:
+    case INTRINSIC_NE_OS:
       if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER)
        {
          e->ts.type = BT_LOGICAL;
@@ -2702,7 +2775,7 @@ resolve_operator (gfc_expr *e)
       if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)
        sprintf (msg,
                 _("Logicals at %%L must be compared with %s instead of %s"),
-                e->value.op.operator == INTRINSIC_EQ ? ".EQV." : ".NEQV.",
+                e->value.op.operator == INTRINSIC_EQ ? ".eqv." : ".neqv.",
                 gfc_op2string (e->value.op.operator));
       else
        sprintf (msg,
@@ -2749,11 +2822,17 @@ resolve_operator (gfc_expr *e)
     case INTRINSIC_EQV:
     case INTRINSIC_NEQV:
     case INTRINSIC_EQ:
+    case INTRINSIC_EQ_OS:
     case INTRINSIC_NE:
+    case INTRINSIC_NE_OS:
     case INTRINSIC_GT:
+    case INTRINSIC_GT_OS:
     case INTRINSIC_GE:
+    case INTRINSIC_GE_OS:
     case INTRINSIC_LT:
+    case INTRINSIC_LT_OS:
     case INTRINSIC_LE:
+    case INTRINSIC_LE_OS:
 
       if (op1->rank == 0 && op2->rank == 0)
        e->rank = 0;
@@ -3799,7 +3878,7 @@ gfc_resolve_expr (gfc_expr *e)
        }
 
       /* This provides the opportunity for the length of constructors with
-        character valued function elements to propogate the string length
+        character valued function elements to propagate the string length
         to the expression.  */
       if (e->ts.type == BT_CHARACTER)
        gfc_resolve_character_array_constructor (e);
@@ -6458,8 +6537,9 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
            }
        }
 
-      /* Also, they must not have the SAVE attribute.  */
-      if (flag && sym->attr.save)
+      /* Also, they must not have the SAVE attribute.
+        SAVE_IMPLICIT is checked below.  */
+      if (flag && sym->attr.save == SAVE_EXPLICIT)
        {
          gfc_error (auto_save_msg, sym->name, &sym->declared_at);
          return FAILURE;
@@ -6467,7 +6547,7 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
   }
 
   /* Reject illegal initializers.  */
-  if (sym->value && flag)
+  if (!sym->mark && sym->value && flag)
     {
       if (sym->attr.allocatable)
        gfc_error ("Allocatable '%s' at %L cannot have an initializer",
@@ -6598,6 +6678,8 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
        && sym->ns->parent->proc_name->attr.flavor == FL_MODULE)
       && gfc_check_access(sym->attr.access, sym->ns->default_access))
     {
+      gfc_interface *iface;
+
       for (arg = sym->formal; arg; arg = arg->next)
        {
          if (arg->sym
@@ -6615,6 +6697,59 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
              return FAILURE;
            }
        }
+
+      /* PUBLIC interfaces may expose PRIVATE procedures that take types
+        PRIVATE to the containing module.  */
+      for (iface = sym->generic; iface; iface = iface->next)
+       {
+         for (arg = iface->sym->formal; arg; arg = arg->next)
+           {
+             if (arg->sym
+                 && arg->sym->ts.type == BT_DERIVED
+                 && !arg->sym->ts.derived->attr.use_assoc
+                 && !gfc_check_access (arg->sym->ts.derived->attr.access,
+                                       arg->sym->ts.derived->ns->default_access))
+               {
+                 gfc_error_now ("Procedure '%s' in PUBLIC interface '%s' at %L takes "
+                                "dummy arguments of '%s' which is PRIVATE",
+                                iface->sym->name, sym->name, &iface->sym->declared_at,
+                                gfc_typename(&arg->sym->ts));
+                 /* Stop this message from recurring.  */
+                 arg->sym->ts.derived->attr.access = ACCESS_PUBLIC;
+                 return FAILURE;
+               }
+            }
+       }
+
+      /* PUBLIC interfaces may expose PRIVATE procedures that take types
+        PRIVATE to the containing module.  */
+      for (iface = sym->generic; iface; iface = iface->next)
+       {
+         for (arg = iface->sym->formal; arg; arg = arg->next)
+           {
+             if (arg->sym
+                 && arg->sym->ts.type == BT_DERIVED
+                 && !arg->sym->ts.derived->attr.use_assoc
+                 && !gfc_check_access (arg->sym->ts.derived->attr.access,
+                                       arg->sym->ts.derived->ns->default_access))
+               {
+                 gfc_error_now ("Procedure '%s' in PUBLIC interface '%s' at %L takes "
+                                "dummy arguments of '%s' which is PRIVATE",
+                                iface->sym->name, sym->name, &iface->sym->declared_at,
+                                gfc_typename(&arg->sym->ts));
+                 /* Stop this message from recurring.  */
+                 arg->sym->ts.derived->attr.access = ACCESS_PUBLIC;
+                 return FAILURE;
+               }
+            }
+       }
+    }
+
+  if (sym->attr.function && sym->value && sym->attr.proc != PROC_ST_FUNCTION)
+    {
+      gfc_error ("Function '%s' at %L cannot have an initializer",
+                sym->name, &sym->declared_at);
+      return FAILURE;
     }
 
   /* An external symbol may not have an initializer because it is taken to be
@@ -6679,6 +6814,7 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
   if (sym->attr.is_bind_c && sym->attr.is_c_interop != 1)
     {
       gfc_formal_arglist *curr_arg;
+      int has_non_interop_arg = 0;
 
       if (verify_bind_c_sym (sym, &(sym->ts), sym->attr.in_common,
                              sym->common_block) == FAILURE)
@@ -6700,18 +6836,25 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
       while (curr_arg != NULL)
         {
           /* Skip implicitly typed dummy args here.  */
-          if (curr_arg->sym->attr.implicit_type == 0
-             && verify_c_interop_param (curr_arg->sym) == FAILURE)
-            {
-              /* If something is found to fail, mark the symbol for the
-                 procedure as not being BIND(C) to try and prevent multiple
-                 errors being reported.  */
-              sym->attr.is_c_interop = 0;
-              sym->ts.is_c_interop = 0;
-              sym->attr.is_bind_c = 0;
-            }
+         if (curr_arg->sym->attr.implicit_type == 0)
+           if (verify_c_interop_param (curr_arg->sym) == FAILURE)
+             /* If something is found to fail, record the fact so we
+                can mark the symbol for the procedure as not being
+                BIND(C) to try and prevent multiple errors being
+                reported.  */
+             has_non_interop_arg = 1;
+          
           curr_arg = curr_arg->next;
         }
+
+      /* See if any of the arguments were not interoperable and if so, clear
+        the procedure symbol to prevent duplicate error messages.  */
+      if (has_non_interop_arg != 0)
+       {
+         sym->attr.is_c_interop = 0;
+         sym->ts.is_c_interop = 0;
+         sym->attr.is_bind_c = 0;
+       }
     }
   
   return SUCCESS;
@@ -7237,7 +7380,7 @@ resolve_symbol (gfc_symbol *sym)
     gfc_resolve (sym->formal_ns);
 
   /* Check threadprivate restrictions.  */
-  if (sym->attr.threadprivate && !sym->attr.save
+  if (sym->attr.threadprivate && !sym->attr.save && !sym->ns->save_all
       && (!sym->attr.in_common
          && sym->module == NULL
          && (sym->ns->proc_name == NULL
@@ -7422,7 +7565,9 @@ check_data_variable (gfc_data_variable *var, locus *where)
          values.left -= 1;
          mpz_sub_ui (size, size, 1);
 
-         gfc_assign_data_value (var->expr, values.vnode->expr, offset);
+         t = gfc_assign_data_value (var->expr, values.vnode->expr, offset);
+         if (t == FAILURE)
+           break;
 
          if (mark == AR_FULL)
            mpz_add_ui (offset, offset, 1);
@@ -8197,6 +8342,8 @@ resolve_types (gfc_namespace *ns)
 
   resolve_entries (ns);
 
+  resolve_common_blocks (ns->common_root);
+
   resolve_contained_functions (ns);
 
   gfc_traverse_ns (ns, resolve_bind_c_derived_types);