OSDN Git Service

PR fortran/23677
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index 1e4c931..a048da5 100644 (file)
@@ -404,20 +404,34 @@ resolve_entries (gfc_namespace * ns)
        }
       else
        {
-         /* Otherwise the result will be passed through an union by
+         /* Otherwise the result will be passed through a union by
             reference.  */
          proc->attr.mixed_entry_master = 1;
          for (el = ns->entries; el; el = el->next)
            {
              sym = el->sym->result;
              if (sym->attr.dimension)
-               gfc_error ("%s result %s can't be an array in FUNCTION %s at %L",
-                          el == ns->entries ? "FUNCTION" : "ENTRY", sym->name,
-                          ns->entries->sym->name, &sym->declared_at);
+             {
+               if (el == ns->entries)
+                 gfc_error
+                 ("FUNCTION result %s can't be an array in FUNCTION %s at %L",
+                  sym->name, ns->entries->sym->name, &sym->declared_at);
+               else
+                 gfc_error
+                   ("ENTRY result %s can't be an array in FUNCTION %s at %L",
+                    sym->name, ns->entries->sym->name, &sym->declared_at);
+             }
              else if (sym->attr.pointer)
-               gfc_error ("%s result %s can't be a POINTER in FUNCTION %s at %L",
-                          el == ns->entries ? "FUNCTION" : "ENTRY", sym->name,
-                          ns->entries->sym->name, &sym->declared_at);
+             {
+               if (el == ns->entries)
+                 gfc_error
+                 ("FUNCTION result %s can't be a POINTER in FUNCTION %s at %L",
+                  sym->name, ns->entries->sym->name, &sym->declared_at);
+               else
+                 gfc_error
+                   ("ENTRY result %s can't be a POINTER in FUNCTION %s at %L",
+                    sym->name, ns->entries->sym->name, &sym->declared_at);
+             }
              else
                {
                  ts = &sym->ts;
@@ -450,10 +464,18 @@ resolve_entries (gfc_namespace * ns)
                      break;
                    }
                  if (sym)
-                   gfc_error ("%s result %s can't be of type %s in FUNCTION %s at %L",
-                              el == ns->entries ? "FUNCTION" : "ENTRY", sym->name,
-                              gfc_typename (ts), ns->entries->sym->name,
-                              &sym->declared_at);
+                 {
+                   if (el == ns->entries)
+                     gfc_error
+                       ("FUNCTION result %s can't be of type %s in FUNCTION %s at %L",
+                        sym->name, gfc_typename (ts), ns->entries->sym->name,
+                        &sym->declared_at);
+                   else
+                     gfc_error
+                       ("ENTRY result %s can't be of type %s in FUNCTION %s at %L",
+                        sym->name, gfc_typename (ts), ns->entries->sym->name,
+                        &sym->declared_at);
+                 }
                }
            }
        }
@@ -1417,7 +1439,7 @@ resolve_operator (gfc_expr * e)
          break;
        }
 
-      sprintf (msg, "Operand of unary numeric operator '%s' at %%L is %s",
+      sprintf (msg, _("Operand of unary numeric operator '%s' at %%L is %s"),
               gfc_op2string (e->value.op.operator), gfc_typename (&e->ts));
       goto bad_op;
 
@@ -1433,7 +1455,7 @@ resolve_operator (gfc_expr * e)
        }
 
       sprintf (msg,
-              "Operands of binary numeric operator '%s' at %%L are %s/%s",
+              _("Operands of binary numeric operator '%s' at %%L are %s/%s"),
               gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),
               gfc_typename (&op2->ts));
       goto bad_op;
@@ -1447,7 +1469,7 @@ resolve_operator (gfc_expr * e)
        }
 
       sprintf (msg,
-              "Operands of string concatenation operator at %%L are %s/%s",
+              _("Operands of string concatenation operator at %%L are %s/%s"),
               gfc_typename (&op1->ts), gfc_typename (&op2->ts));
       goto bad_op;
 
@@ -1466,7 +1488,7 @@ resolve_operator (gfc_expr * e)
          break;
        }
 
-      sprintf (msg, "Operands of logical operator '%s' at %%L are %s/%s",
+      sprintf (msg, _("Operands of logical operator '%s' at %%L are %s/%s"),
               gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),
               gfc_typename (&op2->ts));
 
@@ -1480,7 +1502,7 @@ 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;
 
@@ -1490,7 +1512,7 @@ resolve_operator (gfc_expr * e)
     case INTRINSIC_LE:
       if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX)
        {
-         strcpy (msg, "COMPLEX quantities cannot be compared at %L");
+         strcpy (msg, _("COMPLEX quantities cannot be compared at %L"));
          goto bad_op;
        }
 
@@ -1514,18 +1536,25 @@ resolve_operator (gfc_expr * e)
          break;
        }
 
-      sprintf (msg, "Operands of comparison operator '%s' at %%L are %s/%s",
-              gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),
-              gfc_typename (&op2->ts));
+      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.",
+                gfc_op2string (e->value.op.operator));
+      else
+       sprintf (msg,
+                _("Operands of comparison operator '%s' at %%L are %s/%s"),
+                gfc_op2string (e->value.op.operator), gfc_typename (&op1->ts),
+                gfc_typename (&op2->ts));
 
       goto bad_op;
 
     case INTRINSIC_USER:
       if (op2 == NULL)
-       sprintf (msg, "Operand of user operator '%s' at %%L is %s",
+       sprintf (msg, _("Operand of user operator '%s' at %%L is %s"),
                 e->value.op.uop->name, gfc_typename (&op1->ts));
       else
-       sprintf (msg, "Operands of user operator '%s' at %%L are %s/%s",
+       sprintf (msg, _("Operands of user operator '%s' at %%L are %s/%s"),
                 e->value.op.uop->name, gfc_typename (&op1->ts),
                 gfc_typename (&op2->ts));
 
@@ -1823,6 +1852,40 @@ gfc_resolve_index (gfc_expr * index, int check_scalar)
   return SUCCESS;
 }
 
+/* Resolve a dim argument to an intrinsic function.  */
+
+try
+gfc_resolve_dim_arg (gfc_expr *dim)
+{
+  if (dim == NULL)
+    return SUCCESS;
+
+  if (gfc_resolve_expr (dim) == FAILURE)
+    return FAILURE;
+
+  if (dim->rank != 0)
+    {
+      gfc_error ("Argument dim at %L must be scalar", &dim->where);
+      return FAILURE;
+  
+    }
+  if (dim->ts.type != BT_INTEGER)
+    {
+      gfc_error ("Argument dim at %L must be of INTEGER type", &dim->where);
+      return FAILURE;
+    }
+  if (dim->ts.kind != gfc_index_integer_kind)
+    {
+      gfc_typespec ts;
+
+      ts.type = BT_INTEGER;
+      ts.kind = gfc_index_integer_kind;
+
+      gfc_convert_type_warn (dim, &ts, 2, 0);
+    }
+
+  return SUCCESS;
+}
 
 /* Given an expression that contains array references, update those array
    references to point to the right array specifications.  While this is
@@ -2303,24 +2366,26 @@ gfc_resolve_expr (gfc_expr * e)
    INTEGER or (optionally) REAL type.  */
 
 static try
-gfc_resolve_iterator_expr (gfc_expr * expr, bool real_ok, const char * name)
+gfc_resolve_iterator_expr (gfc_expr * expr, bool real_ok,
+                          const char * name_msgid)
 {
   if (gfc_resolve_expr (expr) == FAILURE)
     return FAILURE;
 
   if (expr->rank != 0)
     {
-      gfc_error ("%s at %L must be a scalar", name, &expr->where);
+      gfc_error ("%s at %L must be a scalar", _(name_msgid), &expr->where);
       return FAILURE;
     }
 
   if (!(expr->ts.type == BT_INTEGER
        || (expr->ts.type == BT_REAL && real_ok)))
     {
-      gfc_error ("%s at %L must be INTEGER%s",
-                name,
-                &expr->where,
-                real_ok ? " or REAL" : "");
+      if (real_ok)
+       gfc_error ("%s at %L must be INTEGER or REAL", _(name_msgid),
+                  &expr->where);
+      else
+       gfc_error ("%s at %L must be INTEGER", _(name_msgid), &expr->where);
       return FAILURE;
     }
   return SUCCESS;
@@ -2453,6 +2518,29 @@ derived_pointer (gfc_symbol * sym)
 }
 
 
+/* Given a pointer to a symbol that is a derived type, see if it's
+   inaccessible, i.e. if it's defined in another module and the components are
+   PRIVATE.  The search is recursive if necessary.  Returns zero if no
+   inaccessible components are found, nonzero otherwise.  */
+
+static int
+derived_inaccessible (gfc_symbol *sym)
+{
+  gfc_component *c;
+
+  if (sym->attr.use_assoc && sym->component_access == ACCESS_PRIVATE)
+    return 1;
+
+  for (c = sym->components; c; c = c->next)
+    {
+        if (c->ts.type == BT_DERIVED && derived_inaccessible (c->ts.derived))
+          return 1;
+    }
+
+  return 0;
+}
+
+
 /* Resolve the argument of a deallocate expression.  The expression must be
    a pointer or a full array.  */
 
@@ -3119,7 +3207,8 @@ resolve_select (gfc_code * code)
 
 /* Resolve a transfer statement. This is making sure that:
    -- a derived type being transferred has only non-pointer components
-   -- a derived type being transferred doesn't have private components
+   -- a derived type being transferred doesn't have private components, unless 
+      it's being transferred from the module where the type was defined
    -- we're not trying to transfer a whole assumed size array.  */
 
 static void
@@ -3154,7 +3243,7 @@ resolve_transfer (gfc_code * code)
          return;
        }
 
-      if (ts->derived->component_access == ACCESS_PRIVATE)
+      if (derived_inaccessible (ts->derived))
        {
          gfc_error ("Data transfer element at %L cannot have "
                     "PRIVATE components",&code->loc);
@@ -3948,6 +4037,7 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
        case EXEC_BACKSPACE:
        case EXEC_ENDFILE:
        case EXEC_REWIND:
+       case EXEC_FLUSH:
          if (gfc_resolve_filepos (code->ext.filepos) == FAILURE)
            break;
 
@@ -4031,9 +4121,34 @@ resolve_symbol (gfc_symbol * sym)
   int i;
   const char *whynot;
   gfc_namelist *nl;
+  gfc_symtree * symtree;
+  gfc_symtree * this_symtree;
+  gfc_namespace * ns;
 
   if (sym->attr.flavor == FL_UNKNOWN)
     {
+
+    /* If we find that a flavorless symbol is an interface in one of the
+       parent namespaces, find its symtree in this namespace, free the
+       symbol and set the symtree to point to the interface symbol.  */
+      for (ns = gfc_current_ns->parent; ns; ns = ns->parent)
+       {
+         symtree = gfc_find_symtree (ns->sym_root, sym->name);
+         if (symtree && symtree->n.sym->generic)
+           {
+             this_symtree = gfc_find_symtree (gfc_current_ns->sym_root,
+                                              sym->name);
+             sym->refs--;
+             if (!sym->refs)
+               gfc_free_symbol (sym);
+             symtree->n.sym->refs++;
+             this_symtree->n.sym = symtree->n.sym;
+             return;
+           }
+       }
+
+      /* Otherwise give it a flavor according to such attributes as
+        it has.  */
       if (sym->attr.external == 0 && sym->attr.intrinsic == 0)
        sym->attr.flavor = FL_VARIABLE;
       else
@@ -4082,9 +4197,12 @@ resolve_symbol (gfc_symbol * sym)
          || sym->as->type == AS_ASSUMED_SHAPE)
       && sym->attr.dummy == 0)
     {
-      gfc_error ("Assumed %s array at %L must be a dummy argument",
-                sym->as->type == AS_ASSUMED_SIZE ? "size" : "shape",
-                 &sym->declared_at);
+      if (sym->as->type == AS_ASSUMED_SIZE)
+       gfc_error ("Assumed size array at %L must be a dummy argument",
+                  &sym->declared_at);
+      else
+       gfc_error ("Assumed shape array at %L must be a dummy argument",
+                  &sym->declared_at);
       return;
     }
 
@@ -4200,15 +4318,15 @@ resolve_symbol (gfc_symbol * sym)
       /* Can the sybol have an initializer?  */
       whynot = NULL;
       if (sym->attr.allocatable)
-       whynot = "Allocatable";
+       whynot = _("Allocatable");
       else if (sym->attr.external)
-       whynot = "External";
+       whynot = _("External");
       else if (sym->attr.dummy)
-       whynot = "Dummy";
+       whynot = _("Dummy");
       else if (sym->attr.intrinsic)
-       whynot = "Intrinsic";
+       whynot = _("Intrinsic");
       else if (sym->attr.result)
-       whynot = "Function Result";
+       whynot = _("Function Result");
       else if (sym->attr.dimension && !sym->attr.pointer)
        {
          /* Don't allow initialization of automatic arrays.  */
@@ -4219,7 +4337,7 @@ resolve_symbol (gfc_symbol * sym)
                  || sym->as->upper[i] == NULL
                  || sym->as->upper[i]->expr_type != EXPR_CONSTANT)
                {
-                 whynot = "Automatic array";
+                 whynot = _("Automatic array");
                  break;
                }
            }
@@ -4234,7 +4352,8 @@ resolve_symbol (gfc_symbol * sym)
        }
 
       /* Assign default initializer.  */
-      if (sym->ts.type == BT_DERIVED && !(sym->value || whynot))
+      if (sym->ts.type == BT_DERIVED && !(sym->value || whynot)
+          && !sym->attr.pointer)
        sym->value = gfc_default_initializer (&sym->ts);
       break;
 
@@ -4727,7 +4846,7 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e)
    sequence derived type containing a pointer at any level of component
    selection, an automatic object, a function name, an entry name, a result
    name, a named constant, a structure component, or a subobject of any of
-   the preceding objects.  */
+   the preceding objects.  A substring shall not have length zero.  */
 
 static void
 resolve_equivalence (gfc_equiv *eq)
@@ -4740,6 +4859,69 @@ resolve_equivalence (gfc_equiv *eq)
   for (; eq; eq = eq->eq)
     {
       e = eq->expr;
+
+      e->ts = e->symtree->n.sym->ts;
+      /* match_varspec might not know yet if it is seeing
+        array reference or substring reference, as it doesn't
+        know the types.  */
+      if (e->ref && e->ref->type == REF_ARRAY)
+       {
+         gfc_ref *ref = e->ref;
+         sym = e->symtree->n.sym;
+
+         if (sym->attr.dimension)
+           {
+             ref->u.ar.as = sym->as;
+             ref = ref->next;
+           }
+
+         /* For substrings, convert REF_ARRAY into REF_SUBSTRING.  */
+         if (e->ts.type == BT_CHARACTER
+             && ref
+             && ref->type == REF_ARRAY
+             && ref->u.ar.dimen == 1
+             && ref->u.ar.dimen_type[0] == DIMEN_RANGE
+             && ref->u.ar.stride[0] == NULL)
+           {
+             gfc_expr *start = ref->u.ar.start[0];
+             gfc_expr *end = ref->u.ar.end[0];
+             void *mem = NULL;
+
+             /* Optimize away the (:) reference.  */
+             if (start == NULL && end == NULL)
+               {
+                 if (e->ref == ref)
+                   e->ref = ref->next;
+                 else
+                   e->ref->next = ref->next;
+                 mem = ref;
+               }
+             else
+               {
+                 ref->type = REF_SUBSTRING;
+                 if (start == NULL)
+                   start = gfc_int_expr (1);
+                 ref->u.ss.start = start;
+                 if (end == NULL && e->ts.cl)
+                   end = gfc_copy_expr (e->ts.cl->length);
+                 ref->u.ss.end = end;
+                 ref->u.ss.length = e->ts.cl;
+                 e->ts.cl = NULL;
+               }
+             ref = ref->next;
+             gfc_free (mem);
+           }
+
+         /* Any further ref is an error.  */
+         if (ref)
+           {
+             gcc_assert (ref->type == REF_ARRAY);
+             gfc_error ("Syntax error in EQUIVALENCE statement at %L",
+                        &ref->u.ar.where);
+             continue;
+           }
+       }
+
       if (gfc_resolve_expr (e) == FAILURE)
         continue;
 
@@ -4802,19 +4984,30 @@ resolve_equivalence (gfc_equiv *eq)
           continue;
         }
 
-      /* Shall not be a structure component.  */
       r = e->ref;
       while (r)
         {
-          if (r->type == REF_COMPONENT)
-            {
-              gfc_error ("Structure component '%s' at %L cannot be an "
-                         "EQUIVALENCE object",
-                         r->u.c.component->name, &e->where);
-              break;
-            }
-          r = r->next;
-        }
+         /* Shall not be a structure component.  */
+         if (r->type == REF_COMPONENT)
+           {
+             gfc_error ("Structure component '%s' at %L cannot be an "
+                        "EQUIVALENCE object",
+                        r->u.c.component->name, &e->where);
+             break;
+           }
+
+         /* A substring shall not have length zero.  */
+         if (r->type == REF_SUBSTRING)
+           {
+             if (compare_bound (r->u.ss.start, r->u.ss.end) == CMP_GT)
+               {
+                 gfc_error ("Substring at %L has length zero",
+                            &r->u.ss.start->where);
+                 break;
+               }
+           }
+         r = r->next;
+       }
     }    
 }