OSDN Git Service

2006-02-24 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index 1e4c931..63b2cd9 100644 (file)
@@ -1,5 +1,6 @@
 /* Perform type resolution on the various stuctures.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, 
+   Inc.
    Contributed by Andy Vaught
 
 This file is part of GCC.
@@ -24,7 +25,15 @@ Software Foundation, 51 Franklin Street, Fifth Floor,Boston, MA
 #include "system.h"
 #include "gfortran.h"
 #include "arith.h"  /* For gfc_compare_expr().  */
+#include "dependency.h"
 
+/* Types used in equivalence statements.  */
+
+typedef enum seq_type
+{
+  SEQ_NONDEFAULT, SEQ_NUMERIC, SEQ_CHARACTER, SEQ_MIXED
+}
+seq_type;
 
 /* Stack to push the current if we descend into a block during
    resolution.  See resolve_branch() and resolve_code().  */
@@ -39,10 +48,24 @@ code_stack;
 static code_stack *cs_base = NULL;
 
 
-/* Nonzero if we're inside a FORALL block */
+/* Nonzero if we're inside a FORALL block */
 
 static int forall_flag;
 
+/* Nonzero if we're inside a OpenMP WORKSHARE or PARALLEL WORKSHARE block.  */
+
+static int omp_workshare_flag;
+
+/* Nonzero if we are processing a formal arglist. The corresponding function
+   resets the flag each time that it is read.  */
+static int formal_arg_flag = 0;
+
+int
+gfc_is_formal_arg (void)
+{
+  return formal_arg_flag;
+}
+
 /* Resolve types of formal argument lists.  These have to be done early so that
    the formal argument lists of module procedures can be copied to the
    containing module before the individual procedures are resolved
@@ -71,6 +94,8 @@ resolve_formal_arglist (gfc_symbol * proc)
       || (sym->as && sym->as->rank > 0))
     proc->attr.always_explicit = 1;
 
+  formal_arg_flag = 1;
+
   for (f = proc->formal; f; f = f->next)
     {
       sym = f->sym;
@@ -117,16 +142,6 @@ resolve_formal_arglist (gfc_symbol * proc)
        {
          if (!sym->attr.function || sym->result == sym)
            gfc_set_default_type (sym, 1, sym->ns);
-         else
-           {
-              /* Set the type of the RESULT, then copy.  */
-             if (sym->result->ts.type == BT_UNKNOWN)
-               gfc_set_default_type (sym->result, 1, sym->result->ns);
-
-             sym->ts = sym->result->ts;
-             if (sym->as == NULL)
-               sym->as = gfc_copy_array_spec (sym->result->as);
-           }
        }
 
       gfc_resolve_array_spec (sym->as, 0);
@@ -217,6 +232,7 @@ resolve_formal_arglist (gfc_symbol * proc)
             }
         }
     }
+  formal_arg_flag = 0;
 }
 
 
@@ -274,6 +290,19 @@ resolve_contained_fntype (gfc_symbol * sym, gfc_namespace * ns)
          sym->attr.untyped = 1;
        }
     }
+
+  /*Fortran 95 Draft Standard, page 51, Section 5.1.1.5, on the Character type,
+    lists the only ways a character length value of * can be used: dummy arguments
+    of procedures, named constants, and function results in external functions.
+    Internal function results are not on that list; ergo, not permitted.  */
+
+  if (sym->ts.type == BT_CHARACTER)
+    {
+      gfc_charlen *cl = sym->ts.cl;
+      if (!cl || !cl->length)
+       gfc_error ("Character-valued internal function '%s' at %L must "
+                  "not be assumed length", sym->name, &sym->declared_at);
+    }
 }
 
 
@@ -404,20 +433,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 +493,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);
+                 }
                }
            }
        }
@@ -542,9 +593,18 @@ resolve_structure_cons (gfc_expr * expr)
 
       /* If we don't have the right type, try to convert it.  */
 
-      if (!gfc_compare_types (&cons->expr->ts, &comp->ts)
-         && gfc_convert_type (cons->expr, &comp->ts, 1) == FAILURE)
-       t = FAILURE;
+      if (!gfc_compare_types (&cons->expr->ts, &comp->ts))
+       {
+         t = FAILURE;
+         if (comp->pointer && cons->expr->ts.type != BT_UNKNOWN)
+           gfc_error ("The element in the derived type constructor at %L, "
+                      "for pointer component '%s', is %s but should be %s",
+                      &cons->expr->where, comp->name,
+                      gfc_basic_typename (cons->expr->ts.type),
+                      gfc_basic_typename (comp->ts.type));
+         else
+           t = gfc_convert_type (cons->expr, &comp->ts, 1);
+       }
     }
 
   return t;
@@ -640,6 +700,69 @@ procedure_kind (gfc_symbol * sym)
   return PTYPE_UNKNOWN;
 }
 
+/* Check references to assumed size arrays.  The flag need_full_assumed_size
+   is non-zero when matching actual arguments.  */
+
+static int need_full_assumed_size = 0;
+
+static bool
+check_assumed_size_reference (gfc_symbol * sym, gfc_expr * e)
+{
+  gfc_ref * ref;
+  int dim;
+  int last = 1;
+
+  if (need_full_assumed_size
+       || !(sym->as && sym->as->type == AS_ASSUMED_SIZE))
+      return false;
+
+  for (ref = e->ref; ref; ref = ref->next)
+    if (ref->type == REF_ARRAY)
+      for (dim = 0; dim < ref->u.ar.as->rank; dim++)
+       last = (ref->u.ar.end[dim] == NULL) && (ref->u.ar.type == DIMEN_ELEMENT);
+
+  if (last)
+    {
+      gfc_error ("The upper bound in the last dimension must "
+                "appear in the reference to the assumed size "
+                "array '%s' at %L.", sym->name, &e->where);
+      return true;
+    }
+  return false;
+}
+
+
+/* Look for bad assumed size array references in argument expressions
+  of elemental and array valued intrinsic procedures.  Since this is
+  called from procedure resolution functions, it only recurses at
+  operators.  */
+
+static bool
+resolve_assumed_size_actual (gfc_expr *e)
+{
+  if (e == NULL)
+   return false;
+
+  switch (e->expr_type)
+    {
+    case EXPR_VARIABLE:
+      if (e->symtree
+           && check_assumed_size_reference (e->symtree->n.sym, e))
+       return true;
+      break;
+
+    case EXPR_OP:
+      if (resolve_assumed_size_actual (e->value.op.op1)
+           || resolve_assumed_size_actual (e->value.op.op2))
+       return true;
+      break;
+
+    default:
+      break;
+    }
+  return false;
+}
+
 
 /* Resolve an actual argument list.  Most of the time, this is just
    resolving the expressions in the list.
@@ -690,11 +813,25 @@ resolve_actual_arglist (gfc_actual_arglist * arg)
          || sym->attr.external)
        {
 
-          if (sym->attr.proc == PROC_ST_FUNCTION)
-            {
-              gfc_error ("Statement function '%s' at %L is not allowed as an "
-                         "actual argument", sym->name, &e->where);
-            }
+         if (sym->attr.proc == PROC_ST_FUNCTION)
+           {
+             gfc_error ("Statement function '%s' at %L is not allowed as an "
+                        "actual argument", sym->name, &e->where);
+           }
+
+         if (sym->attr.contained && !sym->attr.use_assoc
+             && sym->ns->proc_name->attr.flavor != FL_MODULE)
+           {
+             gfc_error ("Internal procedure '%s' is not allowed as an "
+                        "actual argument at %L", sym->name, &e->where);
+           }
+
+         if (sym->attr.elemental && !sym->attr.intrinsic)
+           {
+             gfc_error ("ELEMENTAL non-INTRINSIC procedure '%s' is not "
+                        "allowed as an actual argument at %L", sym->name,
+                        &e->where);
+           }
 
          /* If the symbol is the function that names the current (or
             parent) scope, then we really have a variable reference.  */
@@ -749,6 +886,54 @@ resolve_actual_arglist (gfc_actual_arglist * arg)
 }
 
 
+/* Go through each actual argument in ACTUAL and see if it can be
+   implemented as an inlined, non-copying intrinsic.  FNSYM is the
+   function being called, or NULL if not known.  */
+
+static void
+find_noncopying_intrinsics (gfc_symbol * fnsym, gfc_actual_arglist * actual)
+{
+  gfc_actual_arglist *ap;
+  gfc_expr *expr;
+
+  for (ap = actual; ap; ap = ap->next)
+    if (ap->expr
+       && (expr = gfc_get_noncopying_intrinsic_argument (ap->expr))
+       && !gfc_check_fncall_dependency (expr, INTENT_IN, fnsym, actual))
+      ap->expr->inline_noncopying_intrinsic = 1;
+}
+
+/* This function does the checking of references to global procedures
+   as defined in sections 18.1 and 14.1, respectively, of the Fortran
+   77 and 95 standards.  It checks for a gsymbol for the name, making
+   one if it does not already exist.  If it already exists, then the
+   reference being resolved must correspond to the type of gsymbol.
+   Otherwise, the new symbol is equipped with the attributes of the 
+   reference.  The corresponding code that is called in creating
+   global entities is parse.c.  */
+
+static void
+resolve_global_procedure (gfc_symbol *sym, locus *where, int sub)
+{
+  gfc_gsymbol * gsym;
+  unsigned int type;
+
+  type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
+
+  gsym = gfc_get_gsymbol (sym->name);
+
+  if ((gsym->type != GSYM_UNKNOWN && gsym->type != type))
+    global_used (gsym, where);
+
+  if (gsym->type == GSYM_UNKNOWN)
+    {
+      gsym->type = type;
+      gsym->where = *where;
+    }
+
+  gsym->used = 1;
+}
+
 /************* Function resolution *************/
 
 /* Resolve a function call known to be generic.
@@ -1016,25 +1201,70 @@ static try
 resolve_function (gfc_expr * expr)
 {
   gfc_actual_arglist *arg;
+  gfc_symbol * sym;
   const char *name;
   try t;
+  int temp;
+
+  sym = NULL;
+  if (expr->symtree)
+    sym = expr->symtree->n.sym;
+
+  /* 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)
+    resolve_global_procedure (sym, &expr->where, 0);
+
+  /* Switch off assumed size checking and do this again for certain kinds
+     of procedure, once the procedure itself is resolved.  */
+  need_full_assumed_size++;
 
   if (resolve_actual_arglist (expr->value.function.actual) == FAILURE)
     return FAILURE;
 
+  /* Resume assumed_size checking. */
+  need_full_assumed_size--;
+
+  if (sym && sym->ts.type == BT_CHARACTER
+         && sym->ts.cl && sym->ts.cl->length == NULL)
+    {
+      if (sym->attr.if_source == IFSRC_IFBODY)
+       {
+         /* This follows from a slightly odd requirement at 5.1.1.5 in the
+            standard that allows assumed character length functions to be
+            declared in interfaces but not used.  Picking up the symbol here,
+            rather than resolve_symbol, accomplishes that.  */
+         gfc_error ("Function '%s' can be declared in an interface to "
+                    "return CHARACTER(*) but cannot be used at %L",
+                    sym->name, &expr->where);
+         return FAILURE;
+       }
+
+      /* Internal procedures are taken care of in resolve_contained_fntype.  */
+      if (!sym->attr.dummy && !sym->attr.contained)
+       {
+         gfc_error ("Function '%s' is declared CHARACTER(*) and cannot "
+                    "be used at %L since it is not a dummy argument",
+                    sym->name, &expr->where);
+         return FAILURE;
+       }
+    }
+
 /* See if function is already resolved.  */
 
   if (expr->value.function.name != NULL)
     {
       if (expr->ts.type == BT_UNKNOWN)
-       expr->ts = expr->symtree->n.sym->ts;
+       expr->ts = sym->ts;
       t = SUCCESS;
     }
   else
     {
       /* Apply the rules of section 14.1.2.  */
 
-      switch (procedure_kind (expr->symtree->n.sym))
+      switch (procedure_kind (sym))
        {
        case PTYPE_GENERIC:
          t = resolve_generic_f (expr);
@@ -1059,15 +1289,16 @@ resolve_function (gfc_expr * expr)
   if (expr->expr_type != EXPR_FUNCTION)
     return t;
 
+  temp = need_full_assumed_size;
+  need_full_assumed_size = 0;
+
   if (expr->value.function.actual != NULL
       && ((expr->value.function.esym != NULL
           && expr->value.function.esym->attr.elemental)
          || (expr->value.function.isym != NULL
              && expr->value.function.isym->elemental)))
     {
-
       /* The rank of an elemental is the rank of its array argument(s).  */
-
       for (arg = expr->value.function.actual; arg; arg = arg->next)
        {
          if (arg->expr != NULL && arg->expr->rank > 0)
@@ -1076,8 +1307,56 @@ resolve_function (gfc_expr * expr)
              break;
            }
        }
+
+      /* Being elemental, the last upper bound of an assumed size array
+        argument must be present.  */
+      for (arg = expr->value.function.actual; arg; arg = arg->next)
+       {
+         if (arg->expr != NULL
+               && arg->expr->rank > 0
+               && resolve_assumed_size_actual (arg->expr))
+           return FAILURE;
+       }
+    }
+  if (omp_workshare_flag
+      && expr->value.function.esym
+      && ! gfc_elemental (expr->value.function.esym))
+    {
+      gfc_error ("User defined non-ELEMENTAL function '%s' at %L not allowed"
+                " in WORKSHARE construct", expr->value.function.esym->name,
+                &expr->where);
+      t = FAILURE;
+    }
+
+  else if (expr->value.function.actual != NULL
+            && expr->value.function.isym != NULL
+            && expr->value.function.isym->generic_id != GFC_ISYM_LBOUND
+            && expr->value.function.isym->generic_id != GFC_ISYM_LOC
+            && expr->value.function.isym->generic_id != GFC_ISYM_PRESENT)
+    {
+      /* Array instrinsics must also have the last upper bound of an
+        asumed size array argument.  UBOUND and SIZE have to be
+        excluded from the check if the second argument is anything
+        than a constant.  */
+      int inquiry;
+      inquiry = expr->value.function.isym->generic_id == GFC_ISYM_UBOUND
+                 || expr->value.function.isym->generic_id == GFC_ISYM_SIZE;
+           
+      for (arg = expr->value.function.actual; arg; arg = arg->next)
+       {
+         if (inquiry && arg->next != NULL && arg->next->expr
+               && arg->next->expr->expr_type != EXPR_CONSTANT)
+           break;
+         
+         if (arg->expr != NULL
+               && arg->expr->rank > 0
+               && resolve_assumed_size_actual (arg->expr))
+           return FAILURE;
+       }
     }
 
+  need_full_assumed_size = temp;
+
   if (!pure_function (expr, &name))
     {
       if (forall_flag)
@@ -1095,6 +1374,19 @@ resolve_function (gfc_expr * expr)
        }
     }
 
+  /* Character lengths of use associated functions may contains references to
+     symbols not referenced from the current program unit otherwise.  Make sure
+     those symbols are marked as referenced.  */
+
+  if (expr->ts.type == BT_CHARACTER && expr->value.function.esym 
+      && expr->value.function.esym->attr.use_assoc)
+    {
+      gfc_expr_set_symbols_referenced (expr->ts.cl->length);
+    }
+
+  if (t == SUCCESS)
+    find_noncopying_intrinsics (expr->value.function.esym,
+                               expr->value.function.actual);
   return t;
 }
 
@@ -1314,30 +1606,71 @@ resolve_call (gfc_code * c)
 {
   try t;
 
+  if (c->symtree && c->symtree->n.sym
+       && c->symtree->n.sym->ts.type != BT_UNKNOWN)
+    {
+      gfc_error ("'%s' at %L has a type, which is not consistent with "
+                "the CALL at %L", c->symtree->n.sym->name,
+                &c->symtree->n.sym->declared_at, &c->loc);
+      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)
+    resolve_global_procedure (c->symtree->n.sym, &c->loc, 1);
+
+  /* Switch off assumed size checking and do this again for certain kinds
+     of procedure, once the procedure itself is resolved.  */
+  need_full_assumed_size++;
+
   if (resolve_actual_arglist (c->ext.actual) == FAILURE)
     return FAILURE;
 
-  if (c->resolved_sym != NULL)
-    return SUCCESS;
+  /* Resume assumed_size checking. */
+  need_full_assumed_size--;
 
-  switch (procedure_kind (c->symtree->n.sym))
-    {
-    case PTYPE_GENERIC:
-      t = resolve_generic_s (c);
-      break;
 
-    case PTYPE_SPECIFIC:
-      t = resolve_specific_s (c);
-      break;
+  t = SUCCESS;
+  if (c->resolved_sym == NULL)
+    switch (procedure_kind (c->symtree->n.sym))
+      {
+      case PTYPE_GENERIC:
+       t = resolve_generic_s (c);
+       break;
 
-    case PTYPE_UNKNOWN:
-      t = resolve_unknown_s (c);
-      break;
+      case PTYPE_SPECIFIC:
+       t = resolve_specific_s (c);
+       break;
 
-    default:
-      gfc_internal_error ("resolve_subroutine(): bad function type");
+      case PTYPE_UNKNOWN:
+       t = resolve_unknown_s (c);
+       break;
+
+      default:
+       gfc_internal_error ("resolve_subroutine(): bad function type");
+      }
+
+  if (c->ext.actual != NULL
+      && c->symtree->n.sym->attr.elemental)
+    {
+      gfc_actual_arglist * a;
+      /* Being elemental, the last upper bound of an assumed size array
+        argument must be present.  */
+      for (a = c->ext.actual; a; a = a->next)
+       {
+         if (a->expr != NULL
+               && a->expr->rank > 0
+               && resolve_assumed_size_actual (a->expr))
+           return FAILURE;
+       }
     }
 
+  if (t == SUCCESS)
+    find_noncopying_intrinsics (c->resolved_sym, c->ext.actual);
   return t;
 }
 
@@ -1395,6 +1728,7 @@ resolve_operator (gfc_expr * e)
     case INTRINSIC_NOT:
     case INTRINSIC_UPLUS:
     case INTRINSIC_UMINUS:
+    case INTRINSIC_PARENTHESES:
       if (gfc_resolve_expr (e->value.op.op1) == FAILURE)
        return FAILURE;
       break;
@@ -1417,7 +1751,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 +1767,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 +1781,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 +1800,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 +1814,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 +1824,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,23 +1848,33 @@ 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));
 
       goto bad_op;
 
+    case INTRINSIC_PARENTHESES:
+      break;
+
     default:
       gfc_internal_error ("resolve_operator(): Bad intrinsic");
     }
@@ -1607,6 +1951,7 @@ resolve_operator (gfc_expr * e)
     case INTRINSIC_NOT:
     case INTRINSIC_UPLUS:
     case INTRINSIC_UMINUS:
+    case INTRINSIC_PARENTHESES:
       e->rank = op1->rank;
 
       if (e->shape == NULL)
@@ -1814,6 +2159,7 @@ gfc_resolve_index (gfc_expr * index, int check_scalar)
   if (index->ts.kind != gfc_index_integer_kind
       || index->ts.type != BT_INTEGER)
     {
+      gfc_clear_ts (&ts);
       ts.type = BT_INTEGER;
       ts.kind = gfc_index_integer_kind;
 
@@ -1823,6 +2169,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
@@ -1842,7 +2222,6 @@ find_array_spec (gfc_expr * e)
   gfc_ref *ref;
 
   as = e->symtree->n.sym->as;
-  c = e->symtree->n.sym->components;
 
   for (ref = e->ref; ref; ref = ref->next)
     switch (ref->type)
@@ -1856,7 +2235,7 @@ find_array_spec (gfc_expr * e)
        break;
 
       case REF_COMPONENT:
-       for (; c; c = c->next)
+       for (c = e->symtree->n.sym->ts.derived->components; c; c = c->next)
          if (c == ref->u.c.component)
            break;
 
@@ -1870,7 +2249,6 @@ find_array_spec (gfc_expr * e)
            as = c->as;
          }
 
-       c = c->ts.derived->components;
        break;
 
       case REF_SUBSTRING:
@@ -1932,7 +2310,7 @@ resolve_array_ref (gfc_array_ref * ar)
          }
     }
 
-  if (compare_spec_to_ref (ar) == FAILURE)
+  if (!ar->as->cray_pointee && compare_spec_to_ref (ar) == FAILURE)
     return FAILURE;
 
   return SUCCESS;
@@ -2223,6 +2601,9 @@ resolve_variable (gfc_expr * e)
       e->ts = sym->ts;
     }
 
+  if (check_assumed_size_reference (sym, e))
+    return FAILURE;
+
   return SUCCESS;
 }
 
@@ -2303,24 +2684,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;
@@ -2392,7 +2775,9 @@ gfc_resolve_iterator (gfc_iterator * iter, bool real_ok)
 }
 
 
-/* Resolve a list of FORALL iterators.  */
+/* Resolve a list of FORALL iterators.  The FORALL index-name is constrained
+   to be a scalar INTEGER variable.  The subscripts and stride are scalar
+   INTEGERs, and if stride is a constant it must be nonzero.  */
 
 static void
 resolve_forall_iterators (gfc_forall_iterator * iter)
@@ -2401,28 +2786,35 @@ resolve_forall_iterators (gfc_forall_iterator * iter)
   while (iter)
     {
       if (gfc_resolve_expr (iter->var) == SUCCESS
-         && iter->var->ts.type != BT_INTEGER)
-       gfc_error ("FORALL Iteration variable at %L must be INTEGER",
+         && (iter->var->ts.type != BT_INTEGER || iter->var->rank != 0))
+       gfc_error ("FORALL index-name at %L must be a scalar INTEGER",
                   &iter->var->where);
 
       if (gfc_resolve_expr (iter->start) == SUCCESS
-         && iter->start->ts.type != BT_INTEGER)
-       gfc_error ("FORALL start expression at %L must be INTEGER",
+         && (iter->start->ts.type != BT_INTEGER || iter->start->rank != 0))
+       gfc_error ("FORALL start expression at %L must be a scalar INTEGER",
                   &iter->start->where);
       if (iter->var->ts.kind != iter->start->ts.kind)
        gfc_convert_type (iter->start, &iter->var->ts, 2);
 
       if (gfc_resolve_expr (iter->end) == SUCCESS
-         && iter->end->ts.type != BT_INTEGER)
-       gfc_error ("FORALL end expression at %L must be INTEGER",
+         && (iter->end->ts.type != BT_INTEGER || iter->end->rank != 0))
+       gfc_error ("FORALL end expression at %L must be a scalar INTEGER",
                   &iter->end->where);
       if (iter->var->ts.kind != iter->end->ts.kind)
        gfc_convert_type (iter->end, &iter->var->ts, 2);
 
-      if (gfc_resolve_expr (iter->stride) == SUCCESS
-         && iter->stride->ts.type != BT_INTEGER)
-       gfc_error ("FORALL Stride expression at %L must be INTEGER",
-                  &iter->stride->where);
+      if (gfc_resolve_expr (iter->stride) == SUCCESS)
+       {
+         if (iter->stride->ts.type != BT_INTEGER || iter->stride->rank != 0)
+           gfc_error ("FORALL stride expression at %L must be a scalar %s",
+                       &iter->stride->where, "INTEGER");
+
+         if (iter->stride->expr_type == EXPR_CONSTANT
+             && mpz_cmp_ui(iter->stride->value.integer, 0) == 0)
+           gfc_error ("FORALL stride expression at %L cannot be zero",
+                      &iter->stride->where);
+       }
       if (iter->var->ts.kind != iter->stride->ts.kind)
        gfc_convert_type (iter->stride, &iter->var->ts, 2);
 
@@ -2453,6 +2845,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.  */
 
@@ -2503,17 +2918,49 @@ resolve_deallocate_expr (gfc_expr * e)
 }
 
 
+/* Given the expression node e for an allocatable/pointer of derived type to be
+   allocated, get the expression node to be initialized afterwards (needed for
+   derived types with default initializers).  */
+
+static gfc_expr *
+expr_to_initialize (gfc_expr * e)
+{
+  gfc_expr *result;
+  gfc_ref *ref;
+  int i;
+
+  result = gfc_copy_expr (e);
+
+  /* Change the last array reference from AR_ELEMENT to AR_FULL.  */
+  for (ref = result->ref; ref; ref = ref->next)
+    if (ref->type == REF_ARRAY && ref->next == NULL)
+      {
+        ref->u.ar.type = AR_FULL;
+
+        for (i = 0; i < ref->u.ar.dimen; i++)
+          ref->u.ar.start[i] = ref->u.ar.end[i] = ref->u.ar.stride[i] = NULL;
+
+        result->rank = ref->u.ar.dimen; 
+        break;
+      }
+
+  return result;
+}
+
+
 /* Resolve the expression in an ALLOCATE statement, doing the additional
    checks to see whether the expression is OK or not.  The expression must
    have a trailing array reference that gives the size of the array.  */
 
 static try
-resolve_allocate_expr (gfc_expr * e)
+resolve_allocate_expr (gfc_expr * e, gfc_code * code)
 {
   int i, pointer, allocatable, dimension;
   symbol_attribute attr;
   gfc_ref *ref, *ref2;
   gfc_array_ref *ar;
+  gfc_code *init_st;
+  gfc_expr *init_e;
 
   if (gfc_resolve_expr (e) == FAILURE)
     return FAILURE;
@@ -2568,6 +3015,19 @@ resolve_allocate_expr (gfc_expr * e)
       return FAILURE;
     }
 
+  /* Add default initializer for those derived types that need them.  */
+  if (e->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&e->ts)))
+    {
+        init_st = gfc_get_code ();
+        init_st->loc = code->loc;
+        init_st->op = EXEC_ASSIGN;
+        init_st->expr = expr_to_initialize (e);
+        init_st->expr2 = init_e;
+
+        init_st->next = code->next;
+        code->next = init_st;
+    }
+
   if (pointer && dimension == 0)
     return SUCCESS;
 
@@ -3119,7 +3579,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 +3615,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);
@@ -3237,9 +3698,12 @@ resolve_branch (gfc_st_label * label, gfc_code * code)
 
   if (found == NULL)
     {
-      /* still nothing, so illegal.  */
-      gfc_error_now ("Label at %L is not in the same block as the "
-                    "GOTO statement at %L", &lp->where, &code->loc);
+      /* The label is not in an enclosing block, so illegal.  This was
+        allowed in Fortran 66, so we allow it as extension.  We also 
+        forego further checks if we run into this.  */
+      gfc_notify_std (GFC_STD_LEGACY,
+                     "Label at %L is not in the same block as the "
+                     "GOTO statement at %L", &lp->where, &code->loc);
       return;
     }
 
@@ -3585,7 +4049,7 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr)
           gfc_resolve_assign_in_forall (c, nvar, var_expr);
           break;
 
-        /* Because the resolve_blocks() will handle the nested FORALL,
+        /* Because the gfc_resolve_blocks() will handle the nested FORALL,
            there is no need to handle it here.  */
         case EXEC_FORALL:
           break;
@@ -3604,8 +4068,6 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr)
 /* Given a FORALL construct, first resolve the FORALL iterator, then call
    gfc_resolve_forall_body to resolve the FORALL body.  */
 
-static void resolve_blocks (gfc_code *, gfc_namespace *);
-
 static void
 gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
 {
@@ -3671,7 +4133,7 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
   gfc_resolve_forall_body (code, nvar, var_expr);
 
   /* May call gfc_resolve_forall to resolve the inner FORALL loop.  */
-  resolve_blocks (code->block, ns);
+  gfc_resolve_blocks (code->block, ns);
 
   /* Free VAR_EXPR after the whole FORALL construct resolved.  */
   for (i = 0; i < total_var; i++)
@@ -3688,8 +4150,8 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
 
 static void resolve_code (gfc_code *, gfc_namespace *);
 
-static void
-resolve_blocks (gfc_code * b, gfc_namespace * ns)
+void
+gfc_resolve_blocks (gfc_code * b, gfc_namespace * ns)
 {
   try t;
 
@@ -3727,6 +4189,23 @@ resolve_blocks (gfc_code * b, gfc_namespace * ns)
        case EXEC_FORALL:
        case EXEC_DO:
        case EXEC_DO_WHILE:
+       case EXEC_READ:
+       case EXEC_WRITE:
+       case EXEC_IOLENGTH:
+         break;
+
+       case EXEC_OMP_ATOMIC:
+       case EXEC_OMP_CRITICAL:
+       case EXEC_OMP_DO:
+       case EXEC_OMP_MASTER:
+       case EXEC_OMP_ORDERED:
+       case EXEC_OMP_PARALLEL:
+       case EXEC_OMP_PARALLEL_DO:
+       case EXEC_OMP_PARALLEL_SECTIONS:
+       case EXEC_OMP_PARALLEL_WORKSHARE:
+       case EXEC_OMP_SECTIONS:
+       case EXEC_OMP_SINGLE:
+       case EXEC_OMP_WORKSHARE:
          break;
 
        default:
@@ -3744,7 +4223,7 @@ resolve_blocks (gfc_code * b, gfc_namespace * ns)
 static void
 resolve_code (gfc_code * code, gfc_namespace * ns)
 {
-  int forall_save = 0;
+  int omp_workshare_save;
   code_stack frame;
   gfc_alloc *a;
   try t;
@@ -3759,15 +4238,44 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
 
       if (code->op == EXEC_FORALL)
        {
-         forall_save = forall_flag;
+         int forall_save = forall_flag;
+
          forall_flag = 1;
-          gfc_resolve_forall (code, ns, forall_save);
-        }
-      else
-        resolve_blocks (code->block, ns);
+         gfc_resolve_forall (code, ns, forall_save);
+         forall_flag = forall_save;
+       }
+      else if (code->block)
+       {
+         omp_workshare_save = -1;
+         switch (code->op)
+           {
+           case EXEC_OMP_PARALLEL_WORKSHARE:
+             omp_workshare_save = omp_workshare_flag;
+             omp_workshare_flag = 1;
+             gfc_resolve_omp_parallel_blocks (code, ns);
+             break;
+           case EXEC_OMP_PARALLEL:
+           case EXEC_OMP_PARALLEL_DO:
+           case EXEC_OMP_PARALLEL_SECTIONS:
+             omp_workshare_save = omp_workshare_flag;
+             omp_workshare_flag = 0;
+             gfc_resolve_omp_parallel_blocks (code, ns);
+             break;
+           case EXEC_OMP_DO:
+             gfc_resolve_omp_do_blocks (code, ns);
+             break;
+           case EXEC_OMP_WORKSHARE:
+             omp_workshare_save = omp_workshare_flag;
+             omp_workshare_flag = 1;
+             /* FALLTHROUGH */
+           default:
+             gfc_resolve_blocks (code->block, ns);
+             break;
+           }
 
-      if (code->op == EXEC_FORALL)
-       forall_flag = forall_save;
+         if (omp_workshare_save != -1)
+           omp_workshare_flag = omp_workshare_save;
+       }
 
       t = gfc_resolve_expr (code->expr);
       if (gfc_resolve_expr (code->expr2) == FAILURE)
@@ -3815,7 +4323,16 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
            break;
 
          if (gfc_extend_assign (code, ns) == SUCCESS)
-           goto call;
+           {
+             if (gfc_pure (NULL) && !gfc_pure (code->symtree->n.sym))
+               {
+                 gfc_error ("Subroutine '%s' called instead of assignment at "
+                            "%L must be PURE", code->symtree->n.sym->name,
+                            &code->loc);
+                 break;
+               }
+             goto call;
+           }
 
          if (gfc_pure (NULL))
            {
@@ -3895,7 +4412,11 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
 
        case EXEC_DO:
          if (code->ext.iterator != NULL)
-           gfc_resolve_iterator (code->ext.iterator, true);
+           {
+             gfc_iterator *iter = code->ext.iterator;
+             if (gfc_resolve_iterator (iter, true) != FAILURE)
+               gfc_resolve_do_iterator (code, iter->var->symtree->n.sym);
+           }
          break;
 
        case EXEC_DO_WHILE:
@@ -3915,7 +4436,7 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
                       "of type INTEGER", &code->expr->where);
 
          for (a = code->ext.alloc_list; a; a = a->next)
-           resolve_allocate_expr (a->expr);
+           resolve_allocate_expr (a->expr, code);
 
          break;
 
@@ -3948,6 +4469,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;
 
@@ -3992,6 +4514,29 @@ resolve_code (gfc_code * code, gfc_namespace * ns)
               &code->expr->where);
          break;
 
+       case EXEC_OMP_ATOMIC:
+       case EXEC_OMP_BARRIER:
+       case EXEC_OMP_CRITICAL:
+       case EXEC_OMP_FLUSH:
+       case EXEC_OMP_DO:
+       case EXEC_OMP_MASTER:
+       case EXEC_OMP_ORDERED:
+       case EXEC_OMP_SECTIONS:
+       case EXEC_OMP_SINGLE:
+       case EXEC_OMP_WORKSHARE:
+         gfc_resolve_omp_directive (code, ns);
+         break;
+
+       case EXEC_OMP_PARALLEL:
+       case EXEC_OMP_PARALLEL_DO:
+       case EXEC_OMP_PARALLEL_SECTIONS:
+       case EXEC_OMP_PARALLEL_WORKSHARE:
+         omp_workshare_save = omp_workshare_flag;
+         omp_workshare_flag = 0;
+         gfc_resolve_omp_directive (code, ns);
+         omp_workshare_flag = omp_workshare_save;
+         break;
+
        default:
          gfc_internal_error ("resolve_code(): Bad statement code");
        }
@@ -4018,6 +4563,501 @@ resolve_values (gfc_symbol * sym)
 }
 
 
+/* Resolve an index expression.  */
+
+static try
+resolve_index_expr (gfc_expr * e)
+{
+
+  if (gfc_resolve_expr (e) == FAILURE)
+    return FAILURE;
+
+  if (gfc_simplify_expr (e, 0) == FAILURE)
+    return FAILURE;
+
+  if (gfc_specification_expr (e) == FAILURE)
+    return FAILURE;
+
+  return SUCCESS;
+}
+
+/* Resolve a charlen structure.  */
+
+static try
+resolve_charlen (gfc_charlen *cl)
+{
+  if (cl->resolved)
+    return SUCCESS;
+
+  cl->resolved = 1;
+
+  if (resolve_index_expr (cl->length) == FAILURE)
+    return FAILURE;
+
+  return SUCCESS;
+}
+
+
+/* Test for non-constant shape arrays. */
+
+static bool
+is_non_constant_shape_array (gfc_symbol *sym)
+{
+  gfc_expr *e;
+  int i;
+
+  if (sym->as != NULL)
+    {
+      /* Unfortunately, !gfc_is_compile_time_shape hits a legal case that
+        has not been simplified; parameter array references.  Do the
+        simplification now.  */
+      for (i = 0; i < sym->as->rank; i++)
+       {
+         e = sym->as->lower[i];
+         if (e && (resolve_index_expr (e) == FAILURE
+               || !gfc_is_constant_expr (e)))
+           return true;
+
+         e = sym->as->upper[i];
+         if (e && (resolve_index_expr (e) == FAILURE
+               || !gfc_is_constant_expr (e)))
+           return true;
+       }
+    }
+  return false;
+}
+
+/* Resolution of common features of flavors variable and procedure. */
+
+static try
+resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag)
+{
+  /* Constraints on deferred shape variable.  */
+  if (sym->as == NULL || sym->as->type != AS_DEFERRED)
+    {
+      if (sym->attr.allocatable)
+       {
+         if (sym->attr.dimension)
+           gfc_error ("Allocatable array '%s' at %L must have "
+                      "a deferred shape", sym->name, &sym->declared_at);
+         else
+           gfc_error ("Scalar object '%s' at %L may not be ALLOCATABLE",
+                      sym->name, &sym->declared_at);
+           return FAILURE;
+       }
+
+      if (sym->attr.pointer && sym->attr.dimension)
+       {
+         gfc_error ("Array pointer '%s' at %L must have a deferred shape",
+                    sym->name, &sym->declared_at);
+         return FAILURE;
+       }
+
+    }
+  else
+    {
+      if (!mp_flag && !sym->attr.allocatable
+            && !sym->attr.pointer && !sym->attr.dummy)
+       {
+         gfc_error ("Array '%s' at %L cannot have a deferred shape",
+                    sym->name, &sym->declared_at);
+         return FAILURE;
+        }
+    }
+  return SUCCESS;
+}
+
+/* Resolve symbols with flavor variable.  */
+
+static try
+resolve_fl_variable (gfc_symbol *sym, int mp_flag)
+{
+  int flag;
+  int i;
+  gfc_expr *e;
+  gfc_expr *constructor_expr;
+
+  if (resolve_fl_var_and_proc (sym, mp_flag) == FAILURE)
+    return FAILURE;
+
+  /* The shape of a main program or module array needs to be constant.  */
+  if (sym->ns->proc_name
+       && (sym->ns->proc_name->attr.flavor == FL_MODULE
+            || sym->ns->proc_name->attr.is_main_program)
+       && !sym->attr.use_assoc
+       && !sym->attr.allocatable
+       && !sym->attr.pointer
+       && is_non_constant_shape_array (sym))
+    {
+       gfc_error ("The module or main program array '%s' at %L must "
+                    "have constant shape", sym->name, &sym->declared_at);
+         return FAILURE;
+    }
+
+  if (sym->ts.type == BT_CHARACTER)
+    {
+      /* Make sure that character string variables with assumed length are
+        dummy arguments.  */
+      e = sym->ts.cl->length;
+      if (e == NULL && !sym->attr.dummy && !sym->attr.result)
+       {
+         gfc_error ("Entity with assumed character length at %L must be a "
+                    "dummy argument or a PARAMETER", &sym->declared_at);
+         return FAILURE;
+       }
+
+      if (!gfc_is_constant_expr (e)
+           && !(e->expr_type == EXPR_VARIABLE
+           && e->symtree->n.sym->attr.flavor == FL_PARAMETER)
+           && sym->ns->proc_name
+           && (sym->ns->proc_name->attr.flavor == FL_MODULE
+                 || sym->ns->proc_name->attr.is_main_program)
+           && !sym->attr.use_assoc)
+       {
+         gfc_error ("'%s' at %L must have constant character length "
+                    "in this context", sym->name, &sym->declared_at);
+         return FAILURE;
+       }
+    }
+
+  /* Can the symbol have an initializer?  */
+  flag = 0;
+  if (sym->attr.allocatable || sym->attr.external || sym->attr.dummy
+       || sym->attr.intrinsic || sym->attr.result)
+    flag = 1;
+  else if (sym->attr.dimension && !sym->attr.pointer)
+    {
+      /* Don't allow initialization of automatic arrays.  */
+      for (i = 0; i < sym->as->rank; i++)
+       {
+         if (sym->as->lower[i] == NULL
+               || sym->as->lower[i]->expr_type != EXPR_CONSTANT
+               || sym->as->upper[i] == NULL
+               || sym->as->upper[i]->expr_type != EXPR_CONSTANT)
+           {
+             flag = 1;
+             break;
+           }
+       }
+  }
+
+  /* Reject illegal initializers.  */
+  if (sym->value && flag)
+    {
+      if (sym->attr.allocatable)
+       gfc_error ("Allocatable '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      else if (sym->attr.external)
+       gfc_error ("External '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      else if (sym->attr.dummy)
+       gfc_error ("Dummy '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      else if (sym->attr.intrinsic)
+       gfc_error ("Intrinsic '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      else if (sym->attr.result)
+       gfc_error ("Function result '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      else
+       gfc_error ("Automatic array '%s' at %L cannot have an initializer",
+                  sym->name, &sym->declared_at);
+      return FAILURE;
+    }
+
+  /* 4th constraint in section 11.3:  "If an object of a type for which
+     component-initialization is specified (R429) appears in the
+     specification-part of a module and does not have the ALLOCATABLE
+     or POINTER attribute, the object shall have the SAVE attribute."  */
+
+  constructor_expr = NULL;
+  if (sym->ts.type == BT_DERIVED && !(sym->value || flag))
+       constructor_expr = gfc_default_initializer (&sym->ts);
+
+  if (sym->ns->proc_name
+       && sym->ns->proc_name->attr.flavor == FL_MODULE
+       && constructor_expr
+       && !sym->ns->save_all && !sym->attr.save
+       && !sym->attr.pointer && !sym->attr.allocatable)
+    {
+      gfc_error("Object '%s' at %L must have the SAVE attribute %s",
+               sym->name, &sym->declared_at,
+               "for default initialization of a component");
+      return FAILURE;
+    }
+
+  /* Assign default initializer.  */
+  if (sym->ts.type == BT_DERIVED && !(sym->value || flag)
+       && !sym->attr.pointer)
+    sym->value = gfc_default_initializer (&sym->ts);
+
+  return SUCCESS;
+}
+
+
+/* Resolve a procedure.  */
+
+static try
+resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
+{
+  gfc_formal_arglist *arg;
+
+  if (sym->attr.function
+       && resolve_fl_var_and_proc (sym, mp_flag) == FAILURE)
+    return FAILURE;
+
+  if (sym->attr.proc == PROC_ST_FUNCTION)
+    {
+      if (sym->ts.type == BT_CHARACTER)
+        {
+          gfc_charlen *cl = sym->ts.cl;
+          if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT)
+            {
+              gfc_error ("Character-valued statement function '%s' at %L must "
+                         "have constant length", sym->name, &sym->declared_at);
+              return FAILURE;
+            }
+        }
+    }
+
+  /* Ensure that derived type formal arguments of a public procedure
+     are not of a private type.  */
+  if (gfc_check_access(sym->attr.access, sym->ns->default_access))
+    {
+      for (arg = 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 ("'%s' is of a PRIVATE type and cannot be "
+                            "a dummy argument of '%s', which is "
+                            "PUBLIC at %L", arg->sym->name, sym->name,
+                            &sym->declared_at);
+             /* Stop this message from recurring.  */
+             arg->sym->ts.derived->attr.access = ACCESS_PUBLIC;
+             return FAILURE;
+           }
+       }
+    }
+
+  /* An external symbol may not have an intializer because it is taken to be
+     a procedure.  */
+  if (sym->attr.external && sym->value)
+    {
+      gfc_error ("External object '%s' at %L may not have an initializer",
+                sym->name, &sym->declared_at);
+      return FAILURE;
+    }
+
+  /* 5.1.1.5 of the Standard: A function name declared with an asterisk
+     char-len-param shall not be array-valued, pointer-valued, recursive
+     or pure.  ....snip... A character value of * may only be used in the
+     following ways: (i) Dummy arg of procedure - dummy associates with
+     actual length; (ii) To declare a named constant; or (iii) External
+     function - but length must be declared in calling scoping unit.  */
+  if (sym->attr.function
+       && sym->ts.type == BT_CHARACTER
+       && sym->ts.cl && sym->ts.cl->length == NULL)
+    {
+      if ((sym->as && sym->as->rank) || (sym->attr.pointer)
+            || (sym->attr.recursive) || (sym->attr.pure))
+       {
+         if (sym->as && sym->as->rank)
+           gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                      "array-valued", sym->name, &sym->declared_at);
+
+         if (sym->attr.pointer)
+           gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                      "pointer-valued", sym->name, &sym->declared_at);
+
+         if (sym->attr.pure)
+           gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                      "pure", sym->name, &sym->declared_at);
+
+         if (sym->attr.recursive)
+           gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
+                      "recursive", sym->name, &sym->declared_at);
+
+         return FAILURE;
+       }
+
+      /* Appendix B.2 of the standard.  Contained functions give an
+        error anyway.  Fixed-form is likely to be F77/legacy.  */
+      if (!sym->attr.contained && gfc_current_form != FORM_FIXED)
+       gfc_notify_std (GFC_STD_F95_OBS, "CHARACTER(*) function "
+                       "'%s' at %L is obsolescent in fortran 95",
+                       sym->name, &sym->declared_at);
+    }
+  return SUCCESS;
+}
+
+
+/* Resolve the components of a derived type.  */
+
+static try
+resolve_fl_derived (gfc_symbol *sym)
+{
+  gfc_component *c;
+  gfc_dt_list * dt_list;
+  int i;
+
+  for (c = sym->components; c != NULL; c = c->next)
+    {
+      if (c->ts.type == BT_CHARACTER)
+       {
+        if (c->ts.cl->length == NULL
+            || (resolve_charlen (c->ts.cl) == FAILURE)
+            || !gfc_is_constant_expr (c->ts.cl->length))
+          {
+            gfc_error ("Character length of component '%s' needs to "
+                       "be a constant specification expression at %L.",
+                       c->name,
+                       c->ts.cl->length ? &c->ts.cl->length->where : &c->loc);
+            return FAILURE;
+          }
+       }
+
+      if (c->ts.type == BT_DERIVED
+           && sym->component_access != ACCESS_PRIVATE
+           && gfc_check_access(sym->attr.access, sym->ns->default_access)
+           && !c->ts.derived->attr.use_assoc
+           && !gfc_check_access(c->ts.derived->attr.access,
+                                c->ts.derived->ns->default_access))
+       {
+         gfc_error ("The component '%s' is a PRIVATE type and cannot be "
+                    "a component of '%s', which is PUBLIC at %L",
+                     c->name, sym->name, &sym->declared_at);
+         return FAILURE;
+       }
+
+      if (c->pointer || c->as == NULL)
+       continue;
+
+      for (i = 0; i < c->as->rank; i++)
+       {
+         if (c->as->lower[i] == NULL
+               || !gfc_is_constant_expr (c->as->lower[i])
+               || (resolve_index_expr (c->as->lower[i]) == FAILURE)
+               || c->as->upper[i] == NULL
+               || (resolve_index_expr (c->as->upper[i]) == FAILURE)
+               || !gfc_is_constant_expr (c->as->upper[i]))
+           {
+             gfc_error ("Component '%s' of '%s' at %L must have "
+                        "constant array bounds.",
+                        c->name, sym->name, &c->loc);
+             return FAILURE;
+           }
+       }
+    }
+    
+  /* Add derived type to the derived type list.  */
+  dt_list = gfc_get_dt_list ();
+  dt_list->next = sym->ns->derived_types;
+  dt_list->derived = sym;
+  sym->ns->derived_types = dt_list;
+
+  return SUCCESS;
+}
+
+
+static try
+resolve_fl_namelist (gfc_symbol *sym)
+{
+  gfc_namelist *nl;
+  gfc_symbol *nlsym;
+
+  /* Reject PRIVATE objects in a PUBLIC namelist.  */
+  if (gfc_check_access(sym->attr.access, sym->ns->default_access))
+    {
+      for (nl = sym->namelist; nl; nl = nl->next)
+       {
+         if (!nl->sym->attr.use_assoc
+               && !(sym->ns->parent == nl->sym->ns)
+                      && !gfc_check_access(nl->sym->attr.access,
+                                           nl->sym->ns->default_access))
+           {
+             gfc_error ("PRIVATE symbol '%s' cannot be member of "
+                        "PUBLIC namelist at %L", nl->sym->name,
+                        &sym->declared_at);
+             return FAILURE;
+           }
+       }
+    }
+
+    /* Reject namelist arrays that are not constant shape.  */
+    for (nl = sym->namelist; nl; nl = nl->next)
+      {
+       if (is_non_constant_shape_array (nl->sym))
+         {
+           gfc_error ("The array '%s' must have constant shape to be "
+                      "a NAMELIST object at %L", nl->sym->name,
+                      &sym->declared_at);
+           return FAILURE;
+         }
+    }
+
+  /* 14.1.2 A module or internal procedure represent local entities
+     of the same type as a namelist member and so are not allowed.
+     Note that this is sometimes caught by check_conflict so the
+     same message has been used.  */
+  for (nl = sym->namelist; nl; nl = nl->next)
+    {
+      nlsym = NULL;
+       if (sym->ns->parent && nl->sym && nl->sym->name)
+         gfc_find_symbol (nl->sym->name, sym->ns->parent, 0, &nlsym);
+       if (nlsym && nlsym->attr.flavor == FL_PROCEDURE)
+         {
+           gfc_error ("PROCEDURE attribute conflicts with NAMELIST "
+                      "attribute in '%s' at %L", nlsym->name,
+                      &sym->declared_at);
+           return FAILURE;
+         }
+    }
+
+  return SUCCESS;
+}
+
+
+static try
+resolve_fl_parameter (gfc_symbol *sym)
+{
+  /* A parameter array's shape needs to be constant.  */
+  if (sym->as != NULL && !gfc_is_compile_time_shape (sym->as))
+    {
+      gfc_error ("Parameter array '%s' at %L cannot be automatic "
+                "or assumed shape", sym->name, &sym->declared_at);
+      return FAILURE;
+    }
+
+  /* Make sure a parameter that has been implicitly typed still
+     matches the implicit type, since PARAMETER statements can precede
+     IMPLICIT statements.  */
+  if (sym->attr.implicit_type
+       && !gfc_compare_types (&sym->ts,
+                              gfc_get_default_type (sym, sym->ns)))
+    {
+      gfc_error ("Implicitly typed PARAMETER '%s' at %L doesn't match a "
+                "later IMPLICIT type", sym->name, &sym->declared_at);
+      return FAILURE;
+    }
+
+  /* Make sure the types of derived parameters are consistent.  This
+     type checking is deferred until resolution because the type may
+     refer to a derived type from the host.  */
+  if (sym->ts.type == BT_DERIVED
+       && !gfc_compare_types (&sym->ts, &sym->value->ts))
+    {
+      gfc_error ("Incompatible derived type in PARAMETER at %L",
+                &sym->value->where);
+      return FAILURE;
+    }
+  return SUCCESS;
+}
+
+
 /* Do anything necessary to resolve a symbol.  Right now, we just
    assume that an otherwise unknown symbol is a variable.  This sort
    of thing commonly happens for symbols in module.  */
@@ -4028,12 +5068,35 @@ resolve_symbol (gfc_symbol * sym)
   /* Zero if we are checking a formal namespace.  */
   static int formal_ns_flag = 1;
   int formal_ns_save, check_constant, mp_flag;
-  int i;
-  const char *whynot;
-  gfc_namelist *nl;
+  gfc_symtree *symtree;
+  gfc_symtree *this_symtree;
+  gfc_namespace *ns;
+  gfc_component *c;
 
   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
@@ -4044,6 +5107,9 @@ resolve_symbol (gfc_symbol * sym)
        }
     }
 
+  if (sym->attr.flavor == FL_DERIVED && resolve_fl_derived (sym) == FAILURE)
+    return;
+
   /* Symbols that are module procedures with results (functions) have
      the types and array specification copied for type checking in
      procedures that call them, as well as for saving to a module
@@ -4059,8 +5125,10 @@ resolve_symbol (gfc_symbol * sym)
 
       if (sym->attr.flavor == FL_PROCEDURE && sym->attr.function)
        {
+         /* The specific case of an external procedure should emit an error
+            in the case that there is no implicit type.  */
          if (!mp_flag)
-           gfc_set_default_type (sym, 0, NULL);
+           gfc_set_default_type (sym, sym->attr.external, NULL);
          else
            {
               /* Result may be in another namespace.  */
@@ -4082,59 +5150,20 @@ 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);
-      return;
-    }
-
-  /* A parameter array's shape needs to be constant.  */
-
-  if (sym->attr.flavor == FL_PARAMETER && sym->as != NULL 
-      && !gfc_is_compile_time_shape (sym->as))
-    {
-      gfc_error ("Parameter array '%s' at %L cannot be automatic "
-                "or assumed shape", sym->name, &sym->declared_at);
-         return;
-    }
-
-  /* Make sure that character string variables with assumed length are
-     dummy arguments.  */
-
-  if (sym->attr.flavor == FL_VARIABLE && !sym->attr.result
-      && sym->ts.type == BT_CHARACTER
-      && sym->ts.cl->length == NULL && sym->attr.dummy == 0)
-    {
-      gfc_error ("Entity with assumed character length at %L must be a "
-                "dummy argument or a PARAMETER", &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;
     }
 
-  /* Make sure a parameter that has been implicitly typed still
-     matches the implicit type, since PARAMETER statements can precede
-     IMPLICIT statements.  */
-
-  if (sym->attr.flavor == FL_PARAMETER
-      && sym->attr.implicit_type
-      && !gfc_compare_types (&sym->ts, gfc_get_default_type (sym, sym->ns)))
-    gfc_error ("Implicitly typed PARAMETER '%s' at %L doesn't match a "
-              "later IMPLICIT type", sym->name, &sym->declared_at);
-
-  /* Make sure the types of derived parameters are consistent.  This
-     type checking is deferred until resolution because the type may
-     refer to a derived type from the host.  */
-
-  if (sym->attr.flavor == FL_PARAMETER
-      && sym->ts.type == BT_DERIVED
-      && !gfc_compare_types (&sym->ts, &sym->value->ts))
-    gfc_error ("Incompatible derived type in PARAMETER at %L",
-              &sym->value->where);
-
   /* Make sure symbols with known intent or optional are really dummy
      variable.  Because of ENTRY statement, this has to be deferred
      until resolution time.  */
 
-  if (! sym->attr.dummy
+  if (!sym->attr.dummy
       && (sym->attr.optional
          || sym->attr.intent != INTENT_UNKNOWN))
     {
@@ -4142,53 +5171,39 @@ resolve_symbol (gfc_symbol * sym)
       return;
     }
 
-  if (sym->attr.proc == PROC_ST_FUNCTION)
+  /* If a derived type symbol has reached this point, without its
+     type being declared, we have an error.  Notice that most
+     conditions that produce undefined derived types have already
+     been dealt with.  However, the likes of:
+     implicit type(t) (t) ..... call foo (t) will get us here if
+     the type is not declared in the scope of the implicit
+     statement. Change the type to BT_UNKNOWN, both because it is so
+     and to prevent an ICE.  */
+  if (sym->ts.type == BT_DERIVED
+       && sym->ts.derived->components == NULL)
     {
-      if (sym->ts.type == BT_CHARACTER)
-        {
-          gfc_charlen *cl = sym->ts.cl;
-          if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT)
-            {
-              gfc_error ("Character-valued statement function '%s' at %L must "
-                         "have constant length", sym->name, &sym->declared_at);
-              return;
-            }
-        }
+      gfc_error ("The derived type '%s' at %L is of type '%s', "
+                "which has not been defined.", sym->name,
+                 &sym->declared_at, sym->ts.derived->name);
+      sym->ts.type = BT_UNKNOWN;
+      return;
     }
 
-  /* Constraints on deferred shape variable.  */
-  if (sym->attr.flavor == FL_VARIABLE
-      || (sym->attr.flavor == FL_PROCEDURE
-         && sym->attr.function))
+  /* An assumed-size array with INTENT(OUT) shall not be of a type for which
+     default initialization is defined (5.1.2.4.4).  */
+  if (sym->ts.type == BT_DERIVED
+       && sym->attr.dummy
+       && sym->attr.intent == INTENT_OUT
+       && sym->as
+       && sym->as->type == AS_ASSUMED_SIZE)
     {
-      if (sym->as == NULL || sym->as->type != AS_DEFERRED)
-       {
-         if (sym->attr.allocatable)
-           {
-             if (sym->attr.dimension)
-               gfc_error ("Allocatable array at %L must have a deferred shape",
-                          &sym->declared_at);
-             else
-               gfc_error ("Object at %L may not be ALLOCATABLE",
-                          &sym->declared_at);
-             return;
-           }
-
-         if (sym->attr.pointer && sym->attr.dimension)
-           {
-             gfc_error ("Pointer to array at %L must have a deferred shape",
-                        &sym->declared_at);
-             return;
-           }
-
-       }
-      else
+      for (c = sym->ts.derived->components; c; c = c->next)
        {
-         if (!mp_flag && !sym->attr.allocatable
-             && !sym->attr.pointer && !sym->attr.dummy)
+         if (c->initializer)
            {
-             gfc_error ("Array at %L cannot have a deferred shape",
-                        &sym->declared_at);
+             gfc_error ("The INTENT(OUT) dummy argument '%s' at %L is "
+                        "ASSUMED SIZE and so cannot have a default initializer",
+                        sym->name, &sym->declared_at);
              return;
            }
        }
@@ -4197,67 +5212,31 @@ resolve_symbol (gfc_symbol * sym)
   switch (sym->attr.flavor)
     {
     case FL_VARIABLE:
-      /* Can the sybol have an initializer?  */
-      whynot = NULL;
-      if (sym->attr.allocatable)
-       whynot = "Allocatable";
-      else if (sym->attr.external)
-       whynot = "External";
-      else if (sym->attr.dummy)
-       whynot = "Dummy";
-      else if (sym->attr.intrinsic)
-       whynot = "Intrinsic";
-      else if (sym->attr.result)
-       whynot = "Function Result";
-      else if (sym->attr.dimension && !sym->attr.pointer)
-       {
-         /* Don't allow initialization of automatic arrays.  */
-         for (i = 0; i < sym->as->rank; i++)
-           {
-             if (sym->as->lower[i] == NULL
-                 || sym->as->lower[i]->expr_type != EXPR_CONSTANT
-                 || sym->as->upper[i] == NULL
-                 || sym->as->upper[i]->expr_type != EXPR_CONSTANT)
-               {
-                 whynot = "Automatic array";
-                 break;
-               }
-           }
-       }
-
-      /* Reject illegal initializers.  */
-      if (sym->value && whynot)
-       {
-         gfc_error ("%s '%s' at %L cannot have an initializer",
-                    whynot, sym->name, &sym->declared_at);
-         return;
-       }
+      if (resolve_fl_variable (sym, mp_flag) == FAILURE)
+       return;
+      break;
 
-      /* Assign default initializer.  */
-      if (sym->ts.type == BT_DERIVED && !(sym->value || whynot))
-       sym->value = gfc_default_initializer (&sym->ts);
+    case FL_PROCEDURE:
+      if (resolve_fl_procedure (sym, mp_flag) == FAILURE)
+       return;
       break;
 
     case FL_NAMELIST:
-      /* Reject PRIVATE objects in a PUBLIC namelist.  */
-      if (gfc_check_access(sym->attr.access, sym->ns->default_access))
-       {
-         for (nl = sym->namelist; nl; nl = nl->next)
-           {
-             if (!gfc_check_access(nl->sym->attr.access,
-                                   nl->sym->ns->default_access))
-               gfc_error ("PRIVATE symbol '%s' cannot be member of "
-                          "PUBLIC namelist at %L", nl->sym->name,
-                          &sym->declared_at);
-           }
-       }
+      if (resolve_fl_namelist (sym) == FAILURE)
+       return;
+      break;
+
+    case FL_PARAMETER:
+      if (resolve_fl_parameter (sym) == FAILURE)
+       return;
+
       break;
 
     default:
+
       break;
     }
 
-
   /* Make sure that intrinsic exist */
   if (sym->attr.intrinsic
       && ! gfc_intrinsic_name(sym->name, 0)
@@ -4279,6 +5258,14 @@ resolve_symbol (gfc_symbol * sym)
       gfc_resolve (sym->formal_ns);
       formal_ns_flag = formal_ns_save;
     }
+
+  /* Check threadprivate restrictions.  */
+  if (sym->attr.threadprivate && !sym->attr.save
+      && (!sym->attr.in_common
+          && sym->module == NULL
+          && (sym->ns->proc_name == NULL
+              || sym->ns->proc_name->attr.flavor != FL_MODULE)))
+    gfc_error ("Threadprivate at %L isn't SAVEd", &sym->declared_at);
 }
 
 
@@ -4334,6 +5321,13 @@ check_data_variable (gfc_data_variable * var, locus * where)
   if (e->expr_type != EXPR_VARIABLE)
     gfc_internal_error ("check_data_variable(): Bad expression");
 
+  if (e->symtree->n.sym->ns->is_block_data
+       && !e->symtree->n.sym->attr.in_common)
+    {
+      gfc_error ("BLOCK DATA element '%s' at %L must be in COMMON",
+                e->symtree->n.sym->name, &e->symtree->n.sym->declared_at);
+    }
+
   if (e->rank == 0)
     {
       mpz_init_set_ui (size, 1);
@@ -4648,38 +5642,92 @@ gfc_elemental (gfc_symbol * sym)
 /* Warn about unused labels.  */
 
 static void
-warn_unused_label (gfc_namespace * ns)
+warn_unused_label (gfc_st_label * label)
 {
-  gfc_st_label *l;
-
-  l = ns->st_labels;
-  if (l == NULL)
+  if (label == NULL)
     return;
 
-  while (l->next)
-    l = l->next;
+  warn_unused_label (label->left);
 
-  for (; l; l = l->prev)
-    {
-      if (l->defined == ST_LABEL_UNKNOWN)
-       continue;
+  if (label->defined == ST_LABEL_UNKNOWN)
+    return;
 
-      switch (l->referenced)
-       {
-       case ST_LABEL_UNKNOWN:
-         gfc_warning ("Label %d at %L defined but not used", l->value,
-                      &l->where);
-         break;
+  switch (label->referenced)
+    {
+    case ST_LABEL_UNKNOWN:
+      gfc_warning ("Label %d at %L defined but not used", label->value,
+                  &label->where);
+      break;
 
-       case ST_LABEL_BAD_TARGET:
-         gfc_warning ("Label %d at %L defined but cannot be used", l->value,
-                      &l->where);
-         break;
+    case ST_LABEL_BAD_TARGET:
+      gfc_warning ("Label %d at %L defined but cannot be used",
+                  label->value, &label->where);
+      break;
 
-       default:
-         break;
-       }
+    default:
+      break;
     }
+
+  warn_unused_label (label->right);
+}
+
+
+/* Returns the sequence type of a symbol or sequence.  */
+
+static seq_type
+sequence_type (gfc_typespec ts)
+{
+  seq_type result;
+  gfc_component *c;
+
+  switch (ts.type)
+  {
+    case BT_DERIVED:
+
+      if (ts.derived->components == NULL)
+       return SEQ_NONDEFAULT;
+
+      result = sequence_type (ts.derived->components->ts);
+      for (c = ts.derived->components->next; c; c = c->next)
+       if (sequence_type (c->ts) != result)
+         return SEQ_MIXED;
+
+      return result;
+
+    case BT_CHARACTER:
+      if (ts.kind != gfc_default_character_kind)
+         return SEQ_NONDEFAULT;
+
+      return SEQ_CHARACTER;
+
+    case BT_INTEGER:
+      if (ts.kind != gfc_default_integer_kind)
+         return SEQ_NONDEFAULT;
+
+      return SEQ_NUMERIC;
+
+    case BT_REAL:
+      if (!(ts.kind == gfc_default_real_kind
+            || ts.kind == gfc_default_double_kind))
+         return SEQ_NONDEFAULT;
+
+      return SEQ_NUMERIC;
+
+    case BT_COMPLEX:
+      if (ts.kind != gfc_default_complex_kind)
+         return SEQ_NONDEFAULT;
+
+      return SEQ_NUMERIC;
+
+    case BT_LOGICAL:
+      if (ts.kind != gfc_default_logical_kind)
+         return SEQ_NONDEFAULT;
+
+      return SEQ_NUMERIC;
+
+    default:
+      return SEQ_NONDEFAULT;
+  }
 }
 
 
@@ -4712,7 +5760,14 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e)
          in the structure.  */
       if (c->pointer)
         {
-          gfc_error ("Derived type variable '%s' at %L has pointer componet(s) "
+          gfc_error ("Derived type variable '%s' at %L with pointer component(s) "
+                     "cannot be an EQUIVALENCE object", sym->name, &e->where);
+          return FAILURE;
+        }
+
+      if (c->initializer)
+        {
+          gfc_error ("Derived type variable '%s' at %L with default initializer "
                      "cannot be an EQUIVALENCE object", sym->name, &e->where);
           return FAILURE;
         }
@@ -4722,62 +5777,134 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e)
 
 
 /* Resolve equivalence object. 
-   An EQUIVALENCE object shall not be a dummy argument, a pointer, an
-   allocatable array, an object of nonsequence derived type, an object of
+   An EQUIVALENCE object shall not be a dummy argument, a pointer, a target,
+   an allocatable array, an object of nonsequence derived type, an object of
    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.  A
+   derived type shall not have components with default initialization nor
+   shall two objects of an equivalence group be initialized.
+   The simple constraints are done in symbol.c(check_conflict) and the rest
+   are implemented here.  */
 
 static void
 resolve_equivalence (gfc_equiv *eq)
 {
   gfc_symbol *sym;
   gfc_symbol *derived;
+  gfc_symbol *first_sym;
   gfc_expr *e;
   gfc_ref *r;
+  locus *last_where = NULL;
+  seq_type eq_type, last_eq_type;
+  gfc_typespec *last_ts;
+  int object;
+  const char *value_name;
+  const char *msg;
+
+  value_name = NULL;
+  last_ts = &eq->expr->symtree->n.sym->ts;
 
-  for (; eq; eq = eq->eq)
+  first_sym = eq->expr->symtree->n.sym;
+
+  for (object = 1; eq; eq = eq->eq, object++)
     {
       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;
 
       sym = e->symtree->n.sym;
-     
-      /* Shall not be a dummy argument.  */
-      if (sym->attr.dummy)
-        {
-          gfc_error ("Dummy argument '%s' at %L cannot be an EQUIVALENCE "
-                     "object", sym->name, &e->where);
-          continue;
-        }
 
-      /* Shall not be an allocatable array.  */
-      if (sym->attr.allocatable)
-        {
-          gfc_error ("Allocatable array '%s' at %L cannot be an EQUIVALENCE "
-                     "object", sym->name, &e->where);
-          continue;
-        }
+      /* An equivalence statement cannot have more than one initialized
+        object.  */
+      if (sym->value)
+       {
+         if (value_name != NULL)
+           {
+             gfc_error ("Initialized objects '%s' and '%s'  cannot both "
+                        "be in the EQUIVALENCE statement at %L",
+                        value_name, sym->name, &e->where);
+             continue;
+           }
+         else
+           value_name = sym->name;
+       }
 
-      /* Shall not be a pointer.  */
-      if (sym->attr.pointer)
-        {
-          gfc_error ("Pointer '%s' at %L cannot be an EQUIVALENCE object",
-                     sym->name, &e->where);
-          continue;
-        }
-      
-      /* Shall not be a function name, ...  */
-      if (sym->attr.function || sym->attr.result || sym->attr.entry
-          || sym->attr.subroutine)
+      /* Shall not equivalence common block variables in a PURE procedure.  */
+      if (sym->ns->proc_name 
+           && sym->ns->proc_name->attr.pure
+           && sym->attr.in_common)
         {
-          gfc_error ("Entity '%s' at %L cannot be an EQUIVALENCE object",
-                     sym->name, &e->where);
-          continue;
+          gfc_error ("Common block member '%s' at %L cannot be an EQUIVALENCE "
+                    "object in the pure procedure '%s'",
+                    sym->name, &e->where, sym->ns->proc_name->name);
+          break;
         }
-
       /* Shall not be a named constant.  */      
       if (e->expr_type == EXPR_CONSTANT)
         {
@@ -4790,6 +5917,69 @@ resolve_equivalence (gfc_equiv *eq)
       if (derived && resolve_equivalence_derived (derived, sym, e) == FAILURE)
         continue;
 
+      /* Check that the types correspond correctly:
+        Note 5.28:
+        A numeric sequence structure may be equivalenced to another sequence
+        structure, an object of default integer type, default real type, double
+        precision real type, default logical type such that components of the
+        structure ultimately only become associated to objects of the same
+        kind. A character sequence structure may be equivalenced to an object
+        of default character kind or another character sequence structure.
+        Other objects may be equivalenced only to objects of the same type and
+        kind parameters.  */
+
+      /* Identical types are unconditionally OK.  */
+      if (object == 1 || gfc_compare_types (last_ts, &sym->ts))
+       goto identical_types;
+
+      last_eq_type = sequence_type (*last_ts);
+      eq_type = sequence_type (sym->ts);
+
+      /* Since the pair of objects is not of the same type, mixed or
+        non-default sequences can be rejected.  */
+
+      msg = "Sequence %s with mixed components in EQUIVALENCE "
+           "statement at %L with different type objects";
+      if ((object ==2
+              && last_eq_type == SEQ_MIXED
+              && gfc_notify_std (GFC_STD_GNU, msg, first_sym->name,
+                                 last_where) == FAILURE)
+          ||  (eq_type == SEQ_MIXED
+              && gfc_notify_std (GFC_STD_GNU, msg,sym->name,
+                                 &e->where) == FAILURE))
+       continue;
+
+      msg = "Non-default type object or sequence %s in EQUIVALENCE "
+           "statement at %L with objects of different type";
+      if ((object ==2
+              && last_eq_type == SEQ_NONDEFAULT
+              && gfc_notify_std (GFC_STD_GNU, msg, first_sym->name,
+                                 last_where) == FAILURE)
+          ||  (eq_type == SEQ_NONDEFAULT
+              && gfc_notify_std (GFC_STD_GNU, msg, sym->name,
+                                 &e->where) == FAILURE))
+       continue;
+
+      msg ="Non-CHARACTER object '%s' in default CHARACTER "
+          "EQUIVALENCE statement at %L";
+      if (last_eq_type == SEQ_CHARACTER
+           && eq_type != SEQ_CHARACTER
+           && gfc_notify_std (GFC_STD_GNU, msg, sym->name,
+                                 &e->where) == FAILURE)
+               continue;
+
+      msg ="Non-NUMERIC object '%s' in default NUMERIC "
+          "EQUIVALENCE statement at %L";
+      if (last_eq_type == SEQ_NUMERIC
+           && eq_type != SEQ_NUMERIC
+           && gfc_notify_std (GFC_STD_GNU, msg, sym->name,
+                                 &e->where) == FAILURE)
+               continue;
+
+  identical_types:
+      last_ts =&sym->ts;
+      last_where = &e->where;
+
       if (!e->ref)
         continue;
 
@@ -4802,19 +5992,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;
+       }
     }    
 }      
 
@@ -4846,6 +6047,15 @@ resolve_fntype (gfc_namespace * ns)
       sym->attr.untyped = 1;
     }
 
+  if (sym->ts.type == BT_DERIVED && !sym->ts.derived->attr.use_assoc
+      && !gfc_check_access (sym->ts.derived->attr.access,
+                            sym->ts.derived->ns->default_access)
+      && gfc_check_access (sym->attr.access, sym->ns->default_access))
+    {
+      gfc_error ("PUBLIC function '%s' at %L cannot be of PRIVATE type '%s'",
+                 sym->name, &sym->declared_at, sym->ts.derived->name);
+    }
+
   if (ns->entries)
     for (el = ns->entries->next; el; el = el->next)
       {
@@ -4862,21 +6072,20 @@ resolve_fntype (gfc_namespace * ns)
 }
 
 
-/* This function is called after a complete program unit has been compiled.
-   Its purpose is to examine all of the expressions associated with a program
-   unit, assign types to all intermediate expressions, make sure that all
-   assignments are to compatible types and figure out which names refer to
-   which functions or subroutines.  */
+/* Examine all of the expressions associated with a program unit,
+   assign types to all intermediate expressions, make sure that all
+   assignments are to compatible types and figure out which names
+   refer to which functions or subroutines.  It doesn't check code
+   block, which is handled by resolve_code.  */
 
-void
-gfc_resolve (gfc_namespace * ns)
+static void
+resolve_types (gfc_namespace * ns)
 {
-  gfc_namespace *old_ns, *n;
+  gfc_namespace *n;
   gfc_charlen *cl;
   gfc_data *d;
   gfc_equiv *eq;
 
-  old_ns = gfc_current_ns;
   gfc_current_ns = ns;
 
   resolve_entries (ns);
@@ -4894,23 +6103,14 @@ gfc_resolve (gfc_namespace * ns)
                   "also be PURE", n->proc_name->name,
                   &n->proc_name->declared_at);
 
-      gfc_resolve (n);
+      resolve_types (n);
     }
 
   forall_flag = 0;
   gfc_check_interfaces (ns);
 
   for (cl = ns->cl_list; cl; cl = cl->next)
-    {
-      if (cl->length == NULL || gfc_resolve_expr (cl->length) == FAILURE)
-       continue;
-
-      if (gfc_simplify_expr (cl->length, 0) == FAILURE)
-       continue;
-
-      if (gfc_specification_expr (cl->length) == FAILURE)
-       continue;
-    }
+    resolve_charlen (cl);
 
   gfc_traverse_ns (ns, resolve_values);
 
@@ -4927,12 +6127,43 @@ gfc_resolve (gfc_namespace * ns)
   for (eq = ns->equiv; eq; eq = eq->next)
     resolve_equivalence (eq);
 
+  /* Warn about unused labels.  */
+  if (gfc_option.warn_unused_labels)
+    warn_unused_label (ns->st_labels);
+}
+
+
+/* Call resolve_code recursively.  */
+
+static void
+resolve_codes (gfc_namespace * ns)
+{
+  gfc_namespace *n;
+
+  for (n = ns->contained; n; n = n->sibling)
+    resolve_codes (n);
+
+  gfc_current_ns = ns;
   cs_base = NULL;
   resolve_code (ns->code, ns);
+}
 
-  /* Warn about unused labels.  */
-  if (gfc_option.warn_unused_labels)
-    warn_unused_label (ns);
+
+/* This function is called after a complete program unit has been compiled.
+   Its purpose is to examine all of the expressions associated with a program
+   unit, assign types to all intermediate expressions, make sure that all
+   assignments are to compatible types and figure out which names refer to
+   which functions or subroutines.  */
+
+void
+gfc_resolve (gfc_namespace * ns)
+{
+  gfc_namespace *old_ns;
+
+  old_ns = gfc_current_ns;
+
+  resolve_types (ns);
+  resolve_codes (ns);
 
   gfc_current_ns = old_ns;
 }