OSDN Git Service

2010-06-09 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index fb72b93..2ee82af 100644 (file)
@@ -1,5 +1,5 @@
 /* Perform type resolution on the various structures.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dependency.h"
 #include "data.h"
 #include "target-memory.h" /* for gfc_simplify_transfer */
+#include "constructor.h"
 
 /* Types used in equivalence statements.  */
 
@@ -77,6 +78,9 @@ static int current_entry_id;
 /* We use bitmaps to determine if a branch target is valid.  */
 static bitmap_obstack labels_obstack;
 
+/* True when simplifying a EXPR_VARIABLE argument to an inquiry function.  */
+static bool inquiry_argument = false;
+
 int
 gfc_is_formal_arg (void)
 {
@@ -224,7 +228,8 @@ resolve_formal_arglist (gfc_symbol *proc)
        {
          sym->as->type = AS_ASSUMED_SHAPE;
          for (i = 0; i < sym->as->rank; i++)
-           sym->as->lower[i] = gfc_int_expr (1);
+           sym->as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind,
+                                                 NULL, 1);
        }
 
       if ((sym->as && sym->as->rank > 0 && sym->as->type == AS_ASSUMED_SHAPE)
@@ -258,6 +263,14 @@ resolve_formal_arglist (gfc_symbol *proc)
 
       if (gfc_elemental (proc))
        {
+         /* F2008, C1289.  */
+         if (sym->attr.codimension)
+           {
+             gfc_error ("Coarray dummy argument '%s' at %L to elemental "
+                        "procedure", sym->name, &sym->declared_at);
+             continue;
+           }
+
          if (sym->as != NULL)
            {
              gfc_error ("Argument '%s' of elemental procedure at %L must "
@@ -367,15 +380,26 @@ resolve_contained_fntype (gfc_symbol *sym, gfc_namespace *ns)
   /* 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.  */
+     in external functions.  Internal function results and results of module
+     procedures are not on this list, ergo, not permitted.  */
 
   if (sym->result->ts.type == BT_CHARACTER)
     {
       gfc_charlen *cl = sym->result->ts.u.cl;
       if (!cl || !cl->length)
-       gfc_error ("Character-valued internal function '%s' at %L must "
-                  "not be assumed length", sym->name, &sym->declared_at);
+       {
+         /* See if this is a module-procedure and adapt error message
+            accordingly.  */
+         bool module_proc;
+         gcc_assert (ns->parent && ns->parent->proc_name);
+         module_proc = (ns->parent->proc_name->attr.flavor == FL_MODULE);
+
+         gfc_error ("Character-valued %s '%s' at %L must not be"
+                    " assumed length",
+                    module_proc ? _("module procedure")
+                                : _("internal function"),
+                    sym->name, &sym->declared_at);
+       }
     }
 }
 
@@ -679,21 +703,6 @@ resolve_entries (gfc_namespace *ns)
 }
 
 
-static bool
-has_default_initializer (gfc_symbol *der)
-{
-  gfc_component *c;
-
-  gcc_assert (der->attr.flavor == FL_DERIVED);
-  for (c = der->components; c; c = c->next)
-    if ((c->ts.type != BT_DERIVED && c->initializer)
-       || (c->ts.type == BT_DERIVED
-           && (!c->attr.pointer && has_default_initializer (c->ts.u.derived))))
-      break;
-
-  return c != NULL;
-}
-
 /* Resolve common variables.  */
 static void
 resolve_common_vars (gfc_symbol *sym, bool named_common)
@@ -727,7 +736,7 @@ resolve_common_vars (gfc_symbol *sym, bool named_common)
        gfc_error_now ("Derived type variable '%s' in COMMON at %L "
                       "has an ultimate component that is "
                       "allocatable", csym->name, &csym->declared_at);
-      if (has_default_initializer (csym->ts.u.derived))
+      if (gfc_has_default_initializer (csym->ts.u.derived))
        gfc_error_now ("Derived type variable '%s' in COMMON at %L "
                       "may not have default initializer", csym->name,
                       &csym->declared_at);
@@ -765,7 +774,7 @@ resolve_common_blocks (gfc_symtree *common_root)
     gfc_error ("COMMON block '%s' at %L is also an intrinsic procedure",
               sym->name, &common_root->n.common->where);
   else if (sym->attr.result
-          ||(sym->attr.function && gfc_current_ns->proc_name == sym))
+          || gfc_is_function_return_value (sym, gfc_current_ns))
     gfc_notify_std (GFC_STD_F2003, "Fortran 2003: COMMON block '%s' at %L "
                    "that is also a function result", sym->name,
                    &common_root->n.common->where);
@@ -819,7 +828,7 @@ resolve_structure_cons (gfc_expr *expr)
   symbol_attribute a;
 
   t = SUCCESS;
-  cons = expr->value.constructor;
+  cons = gfc_constructor_first (expr->value.constructor);
   /* A constructor may have references if it is the result of substituting a
      parameter variable.  In this case we just pull out the component we
      want.  */
@@ -831,14 +840,21 @@ resolve_structure_cons (gfc_expr *expr)
   /* See if the user is trying to invoke a structure constructor for one of
      the iso_c_binding derived types.  */
   if (expr->ts.type == BT_DERIVED && expr->ts.u.derived
-      && expr->ts.u.derived->ts.is_iso_c && cons && cons->expr != NULL)
+      && expr->ts.u.derived->ts.is_iso_c && cons
+      && (cons->expr == NULL || cons->expr->expr_type != EXPR_NULL))
     {
       gfc_error ("Components of structure constructor '%s' at %L are PRIVATE",
                 expr->ts.u.derived->name, &(expr->where));
       return FAILURE;
     }
 
-  for (; comp; comp = comp->next, cons = cons->next)
+  /* Return if structure constructor is c_null_(fun)prt.  */
+  if (expr->ts.type == BT_DERIVED && expr->ts.u.derived
+      && expr->ts.u.derived->ts.is_iso_c && cons
+      && cons->expr && cons->expr->expr_type == EXPR_NULL)
+    return SUCCESS;
+
+  for (; comp && cons; comp = comp->next, cons = gfc_constructor_next (cons))
     {
       int rank;
 
@@ -867,7 +883,15 @@ resolve_structure_cons (gfc_expr *expr)
       if (!gfc_compare_types (&cons->expr->ts, &comp->ts))
        {
          t = FAILURE;
-         if (comp->attr.pointer && cons->expr->ts.type != BT_UNKNOWN)
+         if (strcmp (comp->name, "$extends") == 0)
+           {
+             /* Can afford to be brutal with the $extends initializer.
+                The derived type can get lost because it is PRIVATE
+                but it is not usage constrained by the standard.  */
+             cons->expr->ts = comp->ts;
+             t = SUCCESS;
+           }
+         else if (comp->attr.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,
@@ -879,7 +903,10 @@ resolve_structure_cons (gfc_expr *expr)
 
       if (cons->expr->expr_type == EXPR_NULL
          && !(comp->attr.pointer || comp->attr.allocatable
-              || comp->attr.proc_pointer))
+              || comp->attr.proc_pointer
+              || (comp->ts.type == BT_CLASS
+                  && (CLASS_DATA (comp)->attr.pointer
+                      || CLASS_DATA (comp)->attr.allocatable))))
        {
          t = FAILURE;
          gfc_error ("The NULL in the derived type constructor at %L is "
@@ -900,6 +927,17 @@ resolve_structure_cons (gfc_expr *expr)
                     "for pointer component '%s' should be a POINTER or "
                     "a TARGET", &cons->expr->where, comp->name);
        }
+
+      /* F2003, C1272 (3).  */
+      if (gfc_pure (NULL) && cons->expr->expr_type == EXPR_VARIABLE
+         && (gfc_impure_variable (cons->expr->symtree->n.sym)
+             || gfc_is_coindexed (cons->expr)))
+       {
+         t = FAILURE;
+         gfc_error ("Invalid expression in the derived type constructor for "
+                    "pointer component '%s' at %L in PURE procedure",
+                    comp->name, &cons->expr->where);
+       }
     }
 
   return t;
@@ -923,7 +961,8 @@ was_declared (gfc_symbol *sym)
 
   if (a.allocatable || a.dimension || a.dummy || a.external || a.intrinsic
       || a.optional || a.pointer || a.save || a.target || a.volatile_
-      || a.value || a.access != ACCESS_UNKNOWN || a.intent != INTENT_UNKNOWN)
+      || a.value || a.access != ACCESS_UNKNOWN || a.intent != INTENT_UNKNOWN
+      || a.asynchronous || a.codimension)
     return 1;
 
   return 0;
@@ -1101,6 +1140,10 @@ is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context)
 {
   gfc_symbol* proc_sym;
   gfc_symbol* context_proc;
+  gfc_namespace* real_context;
+
+  if (sym->attr.flavor == FL_PROGRAM)
+    return false;
 
   gcc_assert (sym->attr.flavor == FL_PROCEDURE);
 
@@ -1114,11 +1157,29 @@ is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context)
   if (proc_sym->attr.recursive || gfc_option.flag_recursive)
     return false;
 
-  /* Find the context procdure's "real" symbol if it has entries.  */
-  context_proc = (context->entries ? context->entries->sym
-                                  : context->proc_name);
-  if (!context_proc)
-    return true;
+  /* Find the context procedure's "real" symbol if it has entries.
+     We look for a procedure symbol, so recurse on the parents if we don't
+     find one (like in case of a BLOCK construct).  */
+  for (real_context = context; ; real_context = real_context->parent)
+    {
+      /* We should find something, eventually!  */
+      gcc_assert (real_context);
+
+      context_proc = (real_context->entries ? real_context->entries->sym
+                                           : real_context->proc_name);
+
+      /* In some special cases, there may not be a proc_name, like for this
+        invalid code:
+        real(bad_kind()) function foo () ...
+        when checking the call to bad_kind ().
+        In these cases, we simply return here and assume that the
+        call is ok.  */
+      if (!context_proc)
+       return false;
+
+      if (context_proc->attr.flavor != FL_LABEL)
+       break;
+    }
 
   /* A call from sym's body to itself is recursion, of course.  */
   if (context_proc == proc_sym)
@@ -1257,7 +1318,7 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
   gfc_expr *e;
   int save_need_full_assumed_size;
   gfc_component *comp;
-       
+
   for (; arg; arg = arg->next)
     {
       e = arg->expr;
@@ -1279,14 +1340,14 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
       if (gfc_is_proc_ptr_comp (e, &comp))
        {
          e->ts = comp->ts;
-         if (e->value.compcall.actual == NULL)
-           e->expr_type = EXPR_VARIABLE;
-         else
+         if (e->expr_type == EXPR_PPC)
            {
              if (comp->as != NULL)
                e->rank = comp->as->rank;
              e->expr_type = EXPR_FUNCTION;
            }
+         if (gfc_resolve_expr (e) == FAILURE)                          
+           return FAILURE; 
          goto argument_list;
        }
 
@@ -1364,10 +1425,7 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
          /* If the symbol is the function that names the current (or
             parent) scope, then we really have a variable reference.  */
 
-         if (sym->attr.function && sym->result == sym
-             && (sym->ns->proc_name == sym
-                 || (sym->ns->parent != NULL
-                     && sym->ns->parent->proc_name == sym)))
+         if (gfc_is_function_return_value (sym, sym->ns))
            goto got_variable;
 
          /* If all else fails, see if we have a specific intrinsic.  */
@@ -1490,6 +1548,15 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
                }
            }
        }
+
+      /* Fortran 2008, C1237.  */
+      if (e->expr_type == EXPR_VARIABLE && gfc_is_coindexed (e)
+          && gfc_has_ultimate_pointer (e))
+        {
+          gfc_error ("Coindexed actual argument at %L with ultimate pointer "
+                    "component", &e->where);
+          return FAILURE;
+        }
     }
 
   return SUCCESS;
@@ -1757,20 +1824,7 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
        && not_in_recursive (sym, gsym->ns)
        && not_entry_self_reference (sym, gsym->ns))
     {
-      /* Make sure that translation for the gsymbol occurs before
-        the procedure currently being resolved.  */
-      ns = gsym->ns->resolved ? NULL : gfc_global_ns_list;
-      for (; ns && ns != gsym->ns; ns = ns->sibling)
-       {
-         if (ns->sibling == gsym->ns)
-           {
-             ns->sibling = gsym->ns->sibling;
-             gsym->ns->sibling = gfc_global_ns_list;
-             gfc_global_ns_list = gsym->ns;
-             break;
-           }
-       }
-
+      /* Resolve the gsymbol namespace if needed.  */
       if (!gsym->ns->resolved)
        {
          gfc_dt_list *old_dt_list;
@@ -1790,6 +1844,20 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
          gfc_derived_types = old_dt_list;
        }
 
+      /* Make sure that translation for the gsymbol occurs before
+        the procedure currently being resolved.  */
+      ns = gfc_global_ns_list;
+      for (; ns && ns != gsym->ns; ns = ns->sibling)
+       {
+         if (ns->sibling == gsym->ns)
+           {
+             ns->sibling = gsym->ns->sibling;
+             gsym->ns->sibling = gfc_global_ns_list;
+             gfc_global_ns_list = gsym->ns;
+             break;
+           }
+       }
+
       if (gsym->ns->proc_name->attr.function
            && gsym->ns->proc_name->as
            && gsym->ns->proc_name->as->rank
@@ -1798,10 +1866,76 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
                   "explicit INTERFACE or the rank is incorrect", sym->name,
                   where);
 
+      /* Non-assumed length character functions.  */
+      if (sym->attr.function && sym->ts.type == BT_CHARACTER
+         && gsym->ns->proc_name->ts.u.cl->length != NULL)
+       {
+         gfc_charlen *cl = sym->ts.u.cl;
+
+         if (!sym->attr.entry_master && sym->attr.if_source == IFSRC_UNKNOWN
+             && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT)
+           {
+             gfc_error ("Nonconstant character-length function '%s' at %L "
+                        "must have an explicit interface", sym->name,
+                        &sym->declared_at);
+           }
+       }
+
+      /* Differences in constant character lengths.  */
+      if (sym->attr.function && sym->ts.type == BT_CHARACTER)
+       {
+         long int l1 = 0, l2 = 0;
+         gfc_charlen *cl1 = sym->ts.u.cl;
+         gfc_charlen *cl2 = gsym->ns->proc_name->ts.u.cl;
+
+         if (cl1 != NULL
+             && cl1->length != NULL
+             && cl1->length->expr_type == EXPR_CONSTANT)
+           l1 = mpz_get_si (cl1->length->value.integer);
+
+         if (cl2 != NULL
+             && cl2->length != NULL
+             && cl2->length->expr_type == EXPR_CONSTANT)
+           l2 = mpz_get_si (cl2->length->value.integer);
+
+         if (l1 && l2 && l1 != l2)
+           gfc_error ("Character length mismatch in return type of "
+                      "function '%s' at %L (%ld/%ld)", sym->name,
+                      &sym->declared_at, l1, l2);
+       }
+
+     /* Type mismatch of function return type and expected type.  */
+     if (sym->attr.function
+        && !gfc_compare_types (&sym->ts, &gsym->ns->proc_name->ts))
+       gfc_error ("Return type mismatch of function '%s' at %L (%s/%s)",
+                  sym->name, &sym->declared_at, gfc_typename (&sym->ts),
+                  gfc_typename (&gsym->ns->proc_name->ts));
+
+      /* Assumed shape arrays as dummy arguments.  */
+      if (gsym->ns->proc_name->formal)
+       {
+         gfc_formal_arglist *arg = gsym->ns->proc_name->formal;
+         for ( ; arg; arg = arg->next)
+           if (arg->sym && arg->sym->as
+               && arg->sym->as->type == AS_ASSUMED_SHAPE)
+             {
+               gfc_error ("Procedure '%s' at %L with assumed-shape dummy "
+                          "'%s' argument must have an explicit interface",
+                          sym->name, &sym->declared_at, arg->sym->name);
+               break;
+             }
+           else if (arg->sym && arg->sym->attr.optional)
+             {
+               gfc_error ("Procedure '%s' at %L with optional dummy argument "
+                          "'%s' must have an explicit interface",
+                          sym->name, &sym->declared_at, arg->sym->name);
+               break;
+             }
+       }
+
       if (gfc_option.flag_whole_file == 1
-           || ((gfc_option.warn_std & GFC_STD_LEGACY)
-                 &&
-              !(gfc_option.warn_std & GFC_STD_GNU)))
+         || ((gfc_option.warn_std & GFC_STD_LEGACY)
+             && !(gfc_option.warn_std & GFC_STD_GNU)))
        gfc_errors_to_warnings (1);
 
       gfc_procedure_use (gsym->ns->proc_name, actual, where);
@@ -2485,6 +2619,10 @@ resolve_function (gfc_expr *expr)
   if (expr->symtree)
     sym = expr->symtree->n.sym;
 
+  /* If this is a procedure pointer component, it has already been resolved.  */
+  if (gfc_is_proc_ptr_comp (expr, NULL))
+    return SUCCESS;
+  
   if (sym && sym->attr.intrinsic
       && resolve_intrinsic (sym, &expr->where) == FAILURE)
     return FAILURE;
@@ -2495,7 +2633,9 @@ resolve_function (gfc_expr *expr)
       return FAILURE;
     }
 
-  if (sym && sym->attr.abstract)
+  /* If this ia a deferred TBP with an abstract interface (which may
+     of course be referenced), expr->value.function.esym will be set.  */
+  if (sym && sym->attr.abstract && !expr->value.function.esym)
     {
       gfc_error ("ABSTRACT INTERFACE '%s' must not be referenced at %L",
                 sym->name, &expr->where);
@@ -2509,11 +2649,19 @@ resolve_function (gfc_expr *expr)
   if (expr->symtree && expr->symtree->n.sym)
     p = expr->symtree->n.sym->attr.proc;
 
+  if (expr->value.function.isym && expr->value.function.isym->inquiry)
+    inquiry_argument = true;
   no_formal_args = sym && is_external_proc (sym) && sym->formal == NULL;
+
   if (resolve_actual_arglist (expr->value.function.actual,
                              p, no_formal_args) == FAILURE)
+    {
+      inquiry_argument = false;
       return FAILURE;
+    }
 
+  inquiry_argument = false;
   /* Need to setup the call to the correct c_associated, depending on
      the number of cptrs to user gives to compare.  */
   if (sym && sym->attr.is_iso_c == 1)
@@ -3107,6 +3255,15 @@ resolve_call (gfc_code *c)
        }
     }
 
+  /* If this ia a deferred TBP with an abstract interface
+     (which may of course be referenced), c->expr1 will be set.  */
+  if (csym && csym->attr.abstract && !c->expr1)
+    {
+      gfc_error ("ABSTRACT INTERFACE '%s' must not be referenced at %L",
+                csym->name, &c->loc);
+      return FAILURE;
+    }
+
   /* Subroutines without the RECURSIVE attribution are not allowed to
    * call themselves.  */
   if (csym && is_illegal_recursion (csym, gfc_current_ns))
@@ -3272,7 +3429,7 @@ resolve_operator (gfc_expr *e)
     case INTRINSIC_POWER:
       if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
        {
-         gfc_type_convert_binary (e);
+         gfc_type_convert_binary (e, 1);
          break;
        }
 
@@ -3359,7 +3516,7 @@ resolve_operator (gfc_expr *e)
 
       if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts))
        {
-         gfc_type_convert_binary (e);
+         gfc_type_convert_binary (e, 1);
 
          e->ts.type = BT_LOGICAL;
          e->ts.kind = gfc_default_logical_kind;
@@ -3510,8 +3667,14 @@ resolve_operator (gfc_expr *e)
 
 bad_op:
 
-  if (gfc_extend_expr (e) == SUCCESS)
-    return SUCCESS;
+  {
+    bool real_error;
+    if (gfc_extend_expr (e, &real_error) == SUCCESS)
+      return SUCCESS;
+
+    if (real_error)
+      return FAILURE;
+  }
 
   if (dual_locus_error)
     gfc_error (msg, &op1->where, &op2->where);
@@ -3659,6 +3822,17 @@ check_dimension (int i, gfc_array_ref *ar, gfc_array_spec *as)
 {
   mpz_t last_value;
 
+  if (ar->dimen_type[i] == DIMEN_STAR)
+    {
+      gcc_assert (ar->stride[i] == NULL);
+      /* This implies [*] as [*:] and [*:3] are not possible.  */
+      if (ar->start[i] == NULL)
+       {
+         gcc_assert (ar->end[i] == NULL);
+         return SUCCESS;
+       }
+    }
+
 /* Given start, end and stride values, calculate the minimum and
    maximum referenced indexes.  */
 
@@ -3667,21 +3841,36 @@ check_dimension (int i, gfc_array_ref *ar, gfc_array_spec *as)
     case DIMEN_VECTOR:
       break;
 
+    case DIMEN_STAR:
     case DIMEN_ELEMENT:
       if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT)
        {
-         gfc_warning ("Array reference at %L is out of bounds "
-                      "(%ld < %ld) in dimension %d", &ar->c_where[i],
-                      mpz_get_si (ar->start[i]->value.integer),
-                      mpz_get_si (as->lower[i]->value.integer), i+1);
+         if (i < as->rank)
+           gfc_warning ("Array reference at %L is out of bounds "
+                        "(%ld < %ld) in dimension %d", &ar->c_where[i],
+                        mpz_get_si (ar->start[i]->value.integer),
+                        mpz_get_si (as->lower[i]->value.integer), i+1);
+         else
+           gfc_warning ("Array reference at %L is out of bounds "
+                        "(%ld < %ld) in codimension %d", &ar->c_where[i],
+                        mpz_get_si (ar->start[i]->value.integer),
+                        mpz_get_si (as->lower[i]->value.integer),
+                        i + 1 - as->rank);
          return SUCCESS;
        }
       if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT)
        {
-         gfc_warning ("Array reference at %L is out of bounds "
-                      "(%ld > %ld) in dimension %d", &ar->c_where[i],
-                      mpz_get_si (ar->start[i]->value.integer),
-                      mpz_get_si (as->upper[i]->value.integer), i+1);
+         if (i < as->rank)
+           gfc_warning ("Array reference at %L is out of bounds "
+                        "(%ld > %ld) in dimension %d", &ar->c_where[i],
+                        mpz_get_si (ar->start[i]->value.integer),
+                        mpz_get_si (as->upper[i]->value.integer), i+1);
+         else
+           gfc_warning ("Array reference at %L is out of bounds "
+                        "(%ld > %ld) in codimension %d", &ar->c_where[i],
+                        mpz_get_si (ar->start[i]->value.integer),
+                        mpz_get_si (as->upper[i]->value.integer),
+                        i + 1 - as->rank);
          return SUCCESS;
        }
 
@@ -3801,18 +3990,41 @@ compare_spec_to_ref (gfc_array_ref *ar)
       return FAILURE;
     }
 
+  /* ar->codimen == 0 is a local array.  */
+  if (as->corank != ar->codimen && ar->codimen != 0)
+    {
+      gfc_error ("Coindex rank mismatch in array reference at %L (%d/%d)",
+                &ar->where, ar->codimen, as->corank);
+      return FAILURE;
+    }
+
   for (i = 0; i < as->rank; i++)
     if (check_dimension (i, ar, as) == FAILURE)
       return FAILURE;
 
+  /* Local access has no coarray spec.  */
+  if (ar->codimen != 0)
+    for (i = as->rank; i < as->rank + as->corank; i++)
+      {
+       if (ar->dimen_type[i] != DIMEN_ELEMENT && !ar->in_allocate)
+         {
+           gfc_error ("Coindex of codimension %d must be a scalar at %L",
+                      i + 1 - as->rank, &ar->where);
+           return FAILURE;
+         }
+       if (check_dimension (i, ar, as) == FAILURE)
+         return FAILURE;
+      }
+
   return SUCCESS;
 }
 
 
 /* Resolve one part of an array index.  */
 
-gfc_try
-gfc_resolve_index (gfc_expr *index, int check_scalar)
+static gfc_try
+gfc_resolve_index_1 (gfc_expr *index, int check_scalar,
+                    int force_index_integer_kind)
 {
   gfc_typespec ts;
 
@@ -3840,7 +4052,8 @@ gfc_resolve_index (gfc_expr *index, int check_scalar)
                        &index->where) == FAILURE)
       return FAILURE;
 
-  if (index->ts.kind != gfc_index_integer_kind
+  if ((index->ts.kind != gfc_index_integer_kind
+       && force_index_integer_kind)
       || index->ts.type != BT_INTEGER)
     {
       gfc_clear_ts (&ts);
@@ -3853,6 +4066,14 @@ gfc_resolve_index (gfc_expr *index, int check_scalar)
   return SUCCESS;
 }
 
+/* Resolve one part of an array index.  */
+
+gfc_try
+gfc_resolve_index (gfc_expr *index, int check_scalar)
+{
+  return gfc_resolve_index_1 (index, check_scalar, 1);
+}
+
 /* Resolve a dim argument to an intrinsic function.  */
 
 gfc_try
@@ -3881,6 +4102,7 @@ gfc_resolve_dim_arg (gfc_expr *dim)
     {
       gfc_typespec ts;
 
+      gfc_clear_ts (&ts);
       ts.type = BT_INTEGER;
       ts.kind = gfc_index_integer_kind;
 
@@ -3908,7 +4130,10 @@ find_array_spec (gfc_expr *e)
   gfc_symbol *derived;
   gfc_ref *ref;
 
-  as = e->symtree->n.sym->as;
+  if (e->symtree->n.sym->ts.type == BT_CLASS)
+    as = CLASS_DATA (e->symtree->n.sym)->as;
+  else
+    as = e->symtree->n.sym->as;
   derived = NULL;
 
   for (ref = e->ref; ref; ref = ref->next)
@@ -3926,6 +4151,9 @@ find_array_spec (gfc_expr *e)
        if (derived == NULL)
          derived = e->symtree->n.sym->ts.u.derived;
 
+       if (derived->attr.is_class)
+         derived = derived->components->ts.u.derived;
+
        c = derived->components;
 
        for (; c; c = c->next)
@@ -3966,11 +4194,14 @@ resolve_array_ref (gfc_array_ref *ar)
   int i, check_scalar;
   gfc_expr *e;
 
-  for (i = 0; i < ar->dimen; i++)
+  for (i = 0; i < ar->dimen + ar->codimen; i++)
     {
       check_scalar = ar->dimen_type[i] == DIMEN_RANGE;
 
-      if (gfc_resolve_index (ar->start[i], check_scalar) == FAILURE)
+      /* Do not force gfc_index_integer_kind for the start.  We can
+         do fine with any integer kind.  This avoids temporary arrays
+        created for indexing with a vector.  */
+      if (gfc_resolve_index_1 (ar->start[i], check_scalar, 0) == FAILURE)
        return FAILURE;
       if (gfc_resolve_index (ar->end[i], check_scalar) == FAILURE)
        return FAILURE;
@@ -4000,6 +4231,9 @@ resolve_array_ref (gfc_array_ref *ar)
          }
     }
 
+  if (ar->type == AR_FULL && ar->as->rank == 0)
+    ar->type = AR_ELEMENT;
+
   /* If the reference type is unknown, figure out what kind it is.  */
 
   if (ar->type == AR_UNKNOWN)
@@ -4134,7 +4368,7 @@ gfc_resolve_substring_charlen (gfc_expr *e)
   if (char_ref->u.ss.start)
     start = gfc_copy_expr (char_ref->u.ss.start);
   else
-    start = gfc_int_expr (1);
+    start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
 
   if (char_ref->u.ss.end)
     end = gfc_copy_expr (char_ref->u.ss.end);
@@ -4148,7 +4382,9 @@ gfc_resolve_substring_charlen (gfc_expr *e)
 
   /* Length = (end - start +1).  */
   e->ts.u.cl->length = gfc_subtract (end, start);
-  e->ts.u.cl->length = gfc_add (e->ts.u.cl->length, gfc_int_expr (1));
+  e->ts.u.cl->length = gfc_add (e->ts.u.cl->length,
+                               gfc_get_int_expr (gfc_default_integer_kind,
+                                                 NULL, 1));
 
   e->ts.u.cl->length->ts.type = BT_INTEGER;
   e->ts.u.cl->length->ts.kind = gfc_charlen_int_kind;
@@ -4204,6 +4440,13 @@ resolve_ref (gfc_expr *expr)
          switch (ref->u.ar.type)
            {
            case AR_FULL:
+             /* Coarray scalar.  */
+             if (ref->u.ar.as->rank == 0)
+               {
+                 current_part_dimension = 0;
+                 break;
+               }
+             /* Fall through.  */
            case AR_SECTION:
              current_part_dimension = 1;
              break;
@@ -4221,7 +4464,9 @@ resolve_ref (gfc_expr *expr)
        case REF_COMPONENT:
          if (current_part_dimension || seen_part_dimension)
            {
-             if (ref->u.c.component->attr.pointer)
+             /* F03:C614.  */
+             if (ref->u.c.component->attr.pointer
+                 || ref->u.c.component->attr.proc_pointer)
                {
                  gfc_error ("Component to the right of a part reference "
                             "with nonzero rank must not have the POINTER "
@@ -4471,6 +4716,47 @@ resolve_procedure:
   if (t == SUCCESS && resolve_procedure_expression (e) == FAILURE)
     t = FAILURE;
 
+  /* F2008, C617 and C1229.  */
+  if (!inquiry_argument && (e->ts.type == BT_CLASS || e->ts.type == BT_DERIVED)
+      && gfc_is_coindexed (e))
+    {
+      gfc_ref *ref, *ref2 = NULL;
+
+      if (e->ts.type == BT_CLASS)
+       {
+         gfc_error ("Polymorphic subobject of coindexed object at %L",
+                    &e->where);
+         t = FAILURE;
+       }
+
+      for (ref = e->ref; ref; ref = ref->next)
+       {
+         if (ref->type == REF_COMPONENT)
+           ref2 = ref;
+         if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
+           break;
+       }
+
+      for ( ; ref; ref = ref->next)
+       if (ref->type == REF_COMPONENT)
+         break;
+
+      /* Expression itself is coindexed object.  */
+      if (ref == NULL)
+       {
+         gfc_component *c;
+         c = ref2 ? ref2->u.c.component : e->symtree->n.sym->components;
+         for ( ; c; c = c->next)
+           if (c->attr.allocatable && c->ts.type == BT_CLASS)
+             {
+               gfc_error ("Coindexed object with polymorphic allocatable "
+                        "subcomponent at %L", &e->where);
+               t = FAILURE;
+               break;
+             }
+       }
+    }
+
   return t;
 }
 
@@ -4595,12 +4881,14 @@ gfc_resolve_character_operator (gfc_expr *e)
   if (op1->ts.u.cl && op1->ts.u.cl->length)
     e1 = gfc_copy_expr (op1->ts.u.cl->length);
   else if (op1->expr_type == EXPR_CONSTANT)
-    e1 = gfc_int_expr (op1->value.character.length);
+    e1 = gfc_get_int_expr (gfc_default_integer_kind, NULL,
+                          op1->value.character.length);
 
   if (op2->ts.u.cl && op2->ts.u.cl->length)
     e2 = gfc_copy_expr (op2->ts.u.cl->length);
   else if (op2->expr_type == EXPR_CONSTANT)
-    e2 = gfc_int_expr (op2->value.character.length);
+    e2 = gfc_get_int_expr (gfc_default_integer_kind, NULL,
+                          op2->value.character.length);
 
   e->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
 
@@ -4687,10 +4975,16 @@ extract_compcall_passed_object (gfc_expr* e)
 
   gcc_assert (e->expr_type == EXPR_COMPCALL);
 
-  po = gfc_get_expr ();
-  po->expr_type = EXPR_VARIABLE;
-  po->symtree = e->symtree;
-  po->ref = gfc_copy_ref (e->ref);
+  if (e->value.compcall.base_object)
+    po = gfc_copy_expr (e->value.compcall.base_object);
+  else
+    {
+      po = gfc_get_expr ();
+      po->expr_type = EXPR_VARIABLE;
+      po->symtree = e->symtree;
+      po->ref = gfc_copy_ref (e->ref);
+      po->where = e->where;
+    }
 
   if (gfc_resolve_expr (po) == FAILURE)
     return NULL;
@@ -4717,13 +5011,7 @@ update_compcall_arglist (gfc_expr* e)
   if (!po)
     return FAILURE;
 
-  if (po->rank > 0)
-    {
-      gfc_error ("Passed-object at %L must be scalar", &e->where);
-      return FAILURE;
-    }
-
-  if (tbp->nopass)
+  if (tbp->nopass || e->value.compcall.ignore_pass)
     {
       gfc_free_expr (po);
       return SUCCESS;
@@ -4750,11 +5038,12 @@ extract_ppc_passed_object (gfc_expr *e)
   po->expr_type = EXPR_VARIABLE;
   po->symtree = e->symtree;
   po->ref = gfc_copy_ref (e->ref);
+  po->where = e->where;
 
   /* Remove PPC reference.  */
   ref = &po->ref;
   while ((*ref)->next)
-    (*ref) = (*ref)->next;
+    ref = &(*ref)->next;
   gfc_free_ref_list (*ref);
   *ref = NULL;
 
@@ -4816,14 +5105,31 @@ check_typebound_baseobject (gfc_expr* e)
   if (!base)
     return FAILURE;
 
-  gcc_assert (base->ts.type == BT_DERIVED);
-  if (base->ts.u.derived->attr.abstract)
+  gcc_assert (base->ts.type == BT_DERIVED || base->ts.type == BT_CLASS);
+
+  if (base->ts.type == BT_DERIVED && base->ts.u.derived->attr.abstract)
     {
       gfc_error ("Base object for type-bound procedure call at %L is of"
                 " ABSTRACT type '%s'", &e->where, base->ts.u.derived->name);
       return FAILURE;
     }
 
+  /* If the procedure called is NOPASS, the base object must be scalar.  */
+  if (e->value.compcall.tbp->nopass && base->rank > 0)
+    {
+      gfc_error ("Base object for NOPASS type-bound procedure call at %L must"
+                " be scalar", &e->where);
+      return FAILURE;
+    }
+
+  /* FIXME: Remove once PR 41177 (this problem) is fixed completely.  */
+  if (base->rank > 0)
+    {
+      gfc_error ("Non-scalar base object at %L currently not implemented",
+                &e->where);
+      return FAILURE;
+    }
+
   return SUCCESS;
 }
 
@@ -4854,15 +5160,54 @@ resolve_typebound_static (gfc_expr* e, gfc_symtree** target,
 }
 
 
+/* Get the ultimate declared type from an expression.  In addition,
+   return the last class/derived type reference and the copy of the
+   reference list.  */
+static gfc_symbol*
+get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref,
+                       gfc_expr *e)
+{
+  gfc_symbol *declared;
+  gfc_ref *ref;
+
+  declared = NULL;
+  if (class_ref)
+    *class_ref = NULL;
+  if (new_ref)
+    *new_ref = gfc_copy_ref (e->ref);
+
+  for (ref = e->ref; ref; ref = ref->next)
+    {
+      if (ref->type != REF_COMPONENT)
+       continue;
+
+      if (ref->u.c.component->ts.type == BT_CLASS
+           || ref->u.c.component->ts.type == BT_DERIVED)
+       {
+         declared = ref->u.c.component->ts.u.derived;
+         if (class_ref)
+           *class_ref = ref;
+       }
+    }
+
+  if (declared == NULL)
+    declared = e->symtree->n.sym->ts.u.derived;
+
+  return declared;
+}
+
+
 /* Given an EXPR_COMPCALL calling a GENERIC typebound procedure, figure out
    which of the specific bindings (if any) matches the arglist and transform
    the expression into a call of that binding.  */
 
 static gfc_try
-resolve_typebound_generic_call (gfc_expr* e)
+resolve_typebound_generic_call (gfc_expr* e, const char **name)
 {
   gfc_typebound_proc* genproc;
   const char* genname;
+  gfc_symtree *st;
+  gfc_symbol *derived;
 
   gcc_assert (e->expr_type == EXPR_COMPCALL);
   genname = e->value.compcall.name;
@@ -4915,6 +5260,10 @@ resolve_typebound_generic_call (gfc_expr* e)
          if (matches)
            {
              e->value.compcall.tbp = g->specific;
+             /* Pass along the name for CLASS methods, where the vtab
+                procedure pointer component has to be referenced.  */
+             if (name)
+               *name = g->specific_st->name;
              goto success;
            }
        }
@@ -4926,6 +5275,19 @@ resolve_typebound_generic_call (gfc_expr* e)
   return FAILURE;
 
 success:
+  /* Make sure that we have the right specific instance for the name.  */
+  genname = e->value.compcall.tbp->u.specific->name;
+
+  /* Is the symtree name a "unique name".  */
+  if (*genname == '@')
+    genname = e->value.compcall.tbp->u.specific->n.sym->name;
+
+  derived = get_declared_from_expr (NULL, NULL, e);
+
+  st = gfc_find_typebound_proc (derived, NULL, genname, false, &e->where);
+  if (st)
+    e->value.compcall.tbp = st->n.tb;
+
   return SUCCESS;
 }
 
@@ -4933,7 +5295,7 @@ success:
 /* Resolve a call to a type-bound subroutine.  */
 
 static gfc_try
-resolve_typebound_call (gfc_code* c)
+resolve_typebound_call (gfc_code* c, const char **name)
 {
   gfc_actual_arglist* newactual;
   gfc_symtree* target;
@@ -4949,7 +5311,12 @@ resolve_typebound_call (gfc_code* c)
   if (check_typebound_baseobject (c->expr1) == FAILURE)
     return FAILURE;
 
-  if (resolve_typebound_generic_call (c->expr1) == FAILURE)
+  /* Pass along the name for CLASS methods, where the vtab
+     procedure pointer component has to be referenced.  */
+  if (name)
+    *name = c->expr1->value.compcall.name;
+
+  if (resolve_typebound_generic_call (c->expr1, name) == FAILURE)
     return FAILURE;
 
   /* Transform into an ordinary EXEC_CALL for now.  */
@@ -4959,20 +5326,23 @@ resolve_typebound_call (gfc_code* c)
 
   c->ext.actual = newactual;
   c->symtree = target;
-  c->op = EXEC_CALL;
+  c->op = (c->expr1->value.compcall.assign ? EXEC_ASSIGN_CALL : EXEC_CALL);
 
   gcc_assert (!c->expr1->ref && !c->expr1->value.compcall.actual);
+
   gfc_free_expr (c->expr1);
-  c->expr1 = NULL;
+  c->expr1 = gfc_get_expr ();
+  c->expr1->expr_type = EXPR_FUNCTION;
+  c->expr1->symtree = target;
+  c->expr1->where = c->loc;
 
   return resolve_call (c);
 }
 
 
 /* Resolve a component-call expression.  */
-
 static gfc_try
-resolve_compcall (gfc_expr* e)
+resolve_compcall (gfc_expr* e, const char **name)
 {
   gfc_actual_arglist* newactual;
   gfc_symtree* target;
@@ -4985,10 +5355,18 @@ resolve_compcall (gfc_expr* e)
       return FAILURE;
     }
 
+  /* These must not be assign-calls!  */
+  gcc_assert (!e->value.compcall.assign);
+
   if (check_typebound_baseobject (e) == FAILURE)
     return FAILURE;
 
-  if (resolve_typebound_generic_call (e) == FAILURE)
+  /* Pass along the name for CLASS methods, where the vtab
+     procedure pointer component has to be referenced.  */
+  if (name)
+    *name = e->value.compcall.name;
+
+  if (resolve_typebound_generic_call (e, name) == FAILURE)
     return FAILURE;
   gcc_assert (!e->value.compcall.tbp->is_generic);
 
@@ -5003,24 +5381,173 @@ resolve_compcall (gfc_expr* e)
     return FAILURE;
 
   e->value.function.actual = newactual;
-  e->value.function.name = e->value.compcall.name;
+  e->value.function.name = NULL;
   e->value.function.esym = target->n.sym;
   e->value.function.isym = NULL;
   e->symtree = target;
   e->ts = target->n.sym->ts;
   e->expr_type = EXPR_FUNCTION;
 
+  /* Resolution is not necessary if this is a class subroutine; this
+     function only has to identify the specific proc. Resolution of
+     the call will be done next in resolve_typebound_call.  */
   return gfc_resolve_expr (e);
 }
 
 
+
+/* Resolve a typebound function, or 'method'. First separate all
+   the non-CLASS references by calling resolve_compcall directly.  */
+
+static gfc_try
+resolve_typebound_function (gfc_expr* e)
+{
+  gfc_symbol *declared;
+  gfc_component *c;
+  gfc_ref *new_ref;
+  gfc_ref *class_ref;
+  gfc_symtree *st;
+  const char *name;
+  const char *genname;
+  gfc_typespec ts;
+
+  st = e->symtree;
+  if (st == NULL)
+    return resolve_compcall (e, NULL);
+
+  /* Get the CLASS declared type.  */
+  declared = get_declared_from_expr (&class_ref, &new_ref, e);
+
+  /* Weed out cases of the ultimate component being a derived type.  */
+  if ((class_ref && class_ref->u.c.component->ts.type == BT_DERIVED)
+        || (!class_ref && st->n.sym->ts.type != BT_CLASS))
+    {
+      gfc_free_ref_list (new_ref);
+      return resolve_compcall (e, NULL);
+    }
+
+  c = gfc_find_component (declared, "$data", true, true);
+  declared = c->ts.u.derived;
+
+  /* Keep the generic name so that the vtab reference can be made.  */
+  genname = NULL; 
+  if (e->value.compcall.tbp->is_generic)
+    genname = e->value.compcall.name;
+
+  /* Treat the call as if it is a typebound procedure, in order to roll
+     out the correct name for the specific function.  */
+  resolve_compcall (e, &name);
+  ts = e->ts;
+
+  /* Then convert the expression to a procedure pointer component call.  */
+  e->value.function.esym = NULL;
+  e->symtree = st;
+
+  if (new_ref)  
+    e->ref = new_ref;
+
+  /* '$vptr' points to the vtab, which contains the procedure pointers.  */
+  gfc_add_component_ref (e, "$vptr");
+  if (genname)
+    {
+      /* A generic procedure needs the subsidiary vtabs and vtypes for
+        the specific procedures to have been build.  */
+      gfc_symbol *vtab;
+      vtab = gfc_find_derived_vtab (declared, true);
+      gcc_assert (vtab);
+      gfc_add_component_ref (e, genname);
+    }
+  gfc_add_component_ref (e, name);
+
+  /* Recover the typespec for the expression.  This is really only
+     necessary for generic procedures, where the additional call
+     to gfc_add_component_ref seems to throw the collection of the
+     correct typespec.  */
+  e->ts = ts;
+  return SUCCESS;
+}
+
+/* Resolve a typebound subroutine, or 'method'. First separate all
+   the non-CLASS references by calling resolve_typebound_call
+   directly.  */
+
+static gfc_try
+resolve_typebound_subroutine (gfc_code *code)
+{
+  gfc_symbol *declared;
+  gfc_component *c;
+  gfc_ref *new_ref;
+  gfc_ref *class_ref;
+  gfc_symtree *st;
+  const char *genname;
+  const char *name;
+  gfc_typespec ts;
+
+  st = code->expr1->symtree;
+  if (st == NULL)
+    return resolve_typebound_call (code, NULL);
+
+  /* Get the CLASS declared type.  */
+  declared = get_declared_from_expr (&class_ref, &new_ref, code->expr1);
+
+  /* Weed out cases of the ultimate component being a derived type.  */
+  if ((class_ref && class_ref->u.c.component->ts.type == BT_DERIVED)
+        || (!class_ref && st->n.sym->ts.type != BT_CLASS))
+    {
+      gfc_free_ref_list (new_ref);
+      return resolve_typebound_call (code, NULL);
+    } 
+
+  c = gfc_find_component (declared, "$data", true, true);
+  declared = c->ts.u.derived;
+
+  /* Keep the generic name so that the vtab reference can be made.  */
+  genname = NULL; 
+  if (code->expr1->value.compcall.tbp->is_generic)
+    genname = code->expr1->value.compcall.name;
+
+  resolve_typebound_call (code, &name);
+  ts = code->expr1->ts;
+
+  /* Then convert the expression to a procedure pointer component call.  */
+  code->expr1->value.function.esym = NULL;
+  code->expr1->symtree = st;
+
+  if (new_ref)
+    code->expr1->ref = new_ref;
+
+  /* '$vptr' points to the vtab, which contains the procedure pointers.  */
+  gfc_add_component_ref (code->expr1, "$vptr");
+  if (genname)
+    {
+      /* A generic procedure needs the subsidiary vtabs and vtypes for
+        the specific procedures to have been build.  */
+      gfc_symbol *vtab;
+      vtab = gfc_find_derived_vtab (declared, true);
+      gcc_assert (vtab);
+      gfc_add_component_ref (code->expr1, genname);
+    }
+  gfc_add_component_ref (code->expr1, name);
+
+  /* Recover the typespec for the expression.  This is really only
+     necessary for generic procedures, where the additional call
+     to gfc_add_component_ref seems to throw the collection of the
+     correct typespec.  */
+  code->expr1->ts = ts;
+  return SUCCESS;
+}
+
+
 /* Resolve a CALL to a Procedure Pointer Component (Subroutine).  */
 
 static gfc_try
 resolve_ppc_call (gfc_code* c)
 {
   gfc_component *comp;
-  gcc_assert (gfc_is_proc_ptr_comp (c->expr1, &comp));
+  bool b;
+
+  b = gfc_is_proc_ptr_comp (c->expr1, &comp);
+  gcc_assert (b);
 
   c->resolved_sym = c->expr1->symtree->n.sym;
   c->expr1->expr_type = EXPR_VARIABLE;
@@ -5052,7 +5579,10 @@ static gfc_try
 resolve_expr_ppc (gfc_expr* e)
 {
   gfc_component *comp;
-  gcc_assert (gfc_is_proc_ptr_comp (e, &comp));
+  bool b;
+
+  b = gfc_is_proc_ptr_comp (e, &comp);
+  gcc_assert (b);
 
   /* Convert to EXPR_FUNCTION.  */
   e->expr_type = EXPR_FUNCTION;
@@ -5081,6 +5611,33 @@ resolve_expr_ppc (gfc_expr* e)
 }
 
 
+static bool
+gfc_is_expandable_expr (gfc_expr *e)
+{
+  gfc_constructor *con;
+
+  if (e->expr_type == EXPR_ARRAY)
+    {
+      /* Traverse the constructor looking for variables that are flavor
+        parameter.  Parameters must be expanded since they are fully used at
+        compile time.  */
+      con = gfc_constructor_first (e->value.constructor);
+      for (; con; con = gfc_constructor_next (con))
+       {
+         if (con->expr->expr_type == EXPR_VARIABLE
+             && con->expr->symtree
+             && (con->expr->symtree->n.sym->attr.flavor == FL_PARAMETER
+             || con->expr->symtree->n.sym->attr.flavor == FL_VARIABLE))
+           return true;
+         if (con->expr->expr_type == EXPR_ARRAY
+             && gfc_is_expandable_expr (con->expr))
+           return true;
+       }
+    }
+
+  return false;
+}
+
 /* Resolve an expression.  That is, make sure that types of operands agree
    with their operators, intrinsic operators are converted to function calls
    for overloaded types and unresolved function references are resolved.  */
@@ -5089,10 +5646,16 @@ gfc_try
 gfc_resolve_expr (gfc_expr *e)
 {
   gfc_try t;
+  bool inquiry_save;
 
   if (e == NULL)
     return SUCCESS;
 
+  /* inquiry_argument only applies to variables.  */
+  inquiry_save = inquiry_argument;
+  if (e->expr_type != EXPR_VARIABLE)
+    inquiry_argument = false;
+
   switch (e->expr_type)
     {
     case EXPR_OP:
@@ -5118,7 +5681,7 @@ gfc_resolve_expr (gfc_expr *e)
       break;
 
     case EXPR_COMPCALL:
-      t = resolve_compcall (e);
+      t = resolve_typebound_function (e);
       break;
 
     case EXPR_SUBSTRING:
@@ -5144,14 +5707,20 @@ gfc_resolve_expr (gfc_expr *e)
       if (t == SUCCESS)
        {
          expression_rank (e);
-         gfc_expand_constructor (e);
+         if (gfc_is_constant_expr (e) || gfc_is_expandable_expr (e))
+           gfc_expand_constructor (e);
        }
 
       /* This provides the opportunity for the length of constructors with
         character valued function elements to propagate the string length
         to the expression.  */
       if (t == SUCCESS && e->ts.type == BT_CHARACTER)
-       t = gfc_resolve_character_array_constructor (e);
+        {
+         /* For efficiency, we call gfc_expand_constructor for BT_CHARACTER
+            here rather then add a duplicate test for it above.  */ 
+         gfc_expand_constructor (e);
+         t = gfc_resolve_character_array_constructor (e);
+       }
 
       break;
 
@@ -5174,6 +5743,8 @@ gfc_resolve_expr (gfc_expr *e)
   if (e->ts.type == BT_CHARACTER && t == SUCCESS && !e->ts.u.cl)
     fixup_charlen (e);
 
+  inquiry_argument = inquiry_save;
+
   return t;
 }
 
@@ -5431,6 +6002,8 @@ resolve_deallocate_expr (gfc_expr *e)
   symbol_attribute attr;
   int allocatable, pointer, check_intent_in;
   gfc_ref *ref;
+  gfc_symbol *sym;
+  gfc_component *c;
 
   /* Check INTENT(IN), unless the object is a sub-component of a pointer.  */
   check_intent_in = 1;
@@ -5441,8 +6014,18 @@ resolve_deallocate_expr (gfc_expr *e)
   if (e->expr_type != EXPR_VARIABLE)
     goto bad;
 
-  allocatable = e->symtree->n.sym->attr.allocatable;
-  pointer = e->symtree->n.sym->attr.pointer;
+  sym = e->symtree->n.sym;
+
+  if (sym->ts.type == BT_CLASS)
+    {
+      allocatable = CLASS_DATA (sym)->attr.allocatable;
+      pointer = CLASS_DATA (sym)->attr.pointer;
+    }
+  else
+    {
+      allocatable = sym->attr.allocatable;
+      pointer = sym->attr.pointer;
+    }
   for (ref = e->ref; ref; ref = ref->next)
     {
       if (pointer)
@@ -5456,9 +6039,17 @@ resolve_deallocate_expr (gfc_expr *e)
          break;
 
        case REF_COMPONENT:
-         allocatable = (ref->u.c.component->as != NULL
-                        && ref->u.c.component->as->type == AS_DEFERRED);
-         pointer = ref->u.c.component->attr.pointer;
+         c = ref->u.c.component;
+         if (c->ts.type == BT_CLASS)
+           {
+             allocatable = CLASS_DATA (c)->attr.allocatable;
+             pointer = CLASS_DATA (c)->attr.pointer;
+           }
+         else
+           {
+             allocatable = c->attr.allocatable;
+             pointer = c->attr.pointer;
+           }
          break;
 
        case REF_SUBSTRING:
@@ -5474,16 +6065,22 @@ resolve_deallocate_expr (gfc_expr *e)
     bad:
       gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
                 &e->where);
+      return FAILURE;
     }
 
-  if (check_intent_in
-      && e->symtree->n.sym->attr.intent == INTENT_IN)
+  if (check_intent_in && sym->attr.intent == INTENT_IN)
     {
       gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L",
-                e->symtree->n.sym->name, &e->where);
+                sym->name, &e->where);
       return FAILURE;
     }
 
+  if (e->ts.type == BT_CLASS)
+    {
+      /* Only deallocate the DATA component.  */
+      gfc_add_component_ref (e, "$data");
+    }
+
   return SUCCESS;
 }
 
@@ -5510,8 +6107,8 @@ gfc_find_sym_in_expr (gfc_symbol *sym, gfc_expr *e)
    derived types with default initializers, and derived types with allocatable
    components that need nullification.)  */
 
-static gfc_expr *
-expr_to_initialize (gfc_expr *e)
+gfc_expr *
+gfc_expr_to_initialize (gfc_expr *e)
 {
   gfc_expr *result;
   gfc_ref *ref;
@@ -5536,6 +6133,58 @@ expr_to_initialize (gfc_expr *e)
 }
 
 
+/* Used in resolve_allocate_expr to check that a allocation-object and
+   a source-expr are conformable.  This does not catch all possible 
+   cases; in particular a runtime checking is needed.  */
+
+static gfc_try
+conformable_arrays (gfc_expr *e1, gfc_expr *e2)
+{
+  /* First compare rank.  */
+  if (e2->ref && e1->rank != e2->ref->u.ar.as->rank)
+    {
+      gfc_error ("Source-expr at %L must be scalar or have the "
+                "same rank as the allocate-object at %L",
+                &e1->where, &e2->where);
+      return FAILURE;
+    }
+
+  if (e1->shape)
+    {
+      int i;
+      mpz_t s;
+
+      mpz_init (s);
+
+      for (i = 0; i < e1->rank; i++)
+       {
+         if (e2->ref->u.ar.end[i])
+           {
+             mpz_set (s, e2->ref->u.ar.end[i]->value.integer);
+             mpz_sub (s, s, e2->ref->u.ar.start[i]->value.integer);
+             mpz_add_ui (s, s, 1);
+           }
+         else
+           {
+             mpz_set (s, e2->ref->u.ar.start[i]->value.integer);
+           }
+
+         if (mpz_cmp (e1->shape[i], s) != 0)
+           {
+             gfc_error ("Source-expr at %L and allocate-object at %L must "
+                        "have the same shape", &e1->where, &e2->where);
+             mpz_clear (s);
+             return FAILURE;
+           }
+       }
+
+      mpz_clear (s);
+    }
+
+  return SUCCESS;
+}
+
+
 /* 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.  */
@@ -5543,25 +6192,40 @@ expr_to_initialize (gfc_expr *e)
 static gfc_try
 resolve_allocate_expr (gfc_expr *e, gfc_code *code)
 {
-  int i, pointer, allocatable, dimension, check_intent_in;
+  int i, pointer, allocatable, dimension, check_intent_in, is_abstract;
+  int codimension;
   symbol_attribute attr;
   gfc_ref *ref, *ref2;
   gfc_array_ref *ar;
-  gfc_code *init_st;
-  gfc_expr *init_e;
-  gfc_symbol *sym;
+  gfc_symbol *sym = NULL;
   gfc_alloc *a;
+  gfc_component *c;
+  gfc_expr *init_e;
 
   /* Check INTENT(IN), unless the object is a sub-component of a pointer.  */
   check_intent_in = 1;
 
+  /* Mark the ultimost array component as being in allocate to allow DIMEN_STAR
+     checking of coarrays.  */
+  for (ref = e->ref; ref; ref = ref->next)
+    if (ref->next == NULL)
+      break;
+
+  if (ref && ref->type == REF_ARRAY)
+    ref->u.ar.in_allocate = true;
+
   if (gfc_resolve_expr (e) == FAILURE)
-    return FAILURE;
+    goto failure;
 
   /* Make sure the expression is allocatable or a pointer.  If it is
      pointer, the next-to-last reference must be a pointer.  */
 
   ref2 = NULL;
+  if (e->symtree)
+    sym = e->symtree->n.sym;
+
+  /* Check whether ultimate component is abstract and CLASS.  */
+  is_abstract = 0;
 
   if (e->expr_type != EXPR_VARIABLE)
     {
@@ -5569,12 +6233,25 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
       attr = gfc_expr_attr (e);
       pointer = attr.pointer;
       dimension = attr.dimension;
+      codimension = attr.codimension;
     }
   else
     {
-      allocatable = e->symtree->n.sym->attr.allocatable;
-      pointer = e->symtree->n.sym->attr.pointer;
-      dimension = e->symtree->n.sym->attr.dimension;
+      if (sym->ts.type == BT_CLASS)
+       {
+         allocatable = CLASS_DATA (sym)->attr.allocatable;
+         pointer = CLASS_DATA (sym)->attr.pointer;
+         dimension = CLASS_DATA (sym)->attr.dimension;
+         codimension = CLASS_DATA (sym)->attr.codimension;
+         is_abstract = CLASS_DATA (sym)->attr.abstract;
+       }
+      else
+       {
+         allocatable = sym->attr.allocatable;
+         pointer = sym->attr.pointer;
+         dimension = sym->attr.dimension;
+         codimension = sym->attr.codimension;
+       }
 
       for (ref = e->ref; ref; ref2 = ref, ref = ref->next)
        {
@@ -5589,11 +6266,31 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
                break;
 
              case REF_COMPONENT:
-               allocatable = (ref->u.c.component->as != NULL
-                              && ref->u.c.component->as->type == AS_DEFERRED);
+               /* F2008, C644.  */
+               if (gfc_is_coindexed (e))
+                 {
+                   gfc_error ("Coindexed allocatable object at %L",
+                              &e->where);
+                   goto failure;
+                 }
 
-               pointer = ref->u.c.component->attr.pointer;
-               dimension = ref->u.c.component->attr.dimension;
+               c = ref->u.c.component;
+               if (c->ts.type == BT_CLASS)
+                 {
+                   allocatable = CLASS_DATA (c)->attr.allocatable;
+                   pointer = CLASS_DATA (c)->attr.pointer;
+                   dimension = CLASS_DATA (c)->attr.dimension;
+                   codimension = CLASS_DATA (c)->attr.codimension;
+                   is_abstract = CLASS_DATA (c)->attr.abstract;
+                 }
+               else
+                 {
+                   allocatable = c->attr.allocatable;
+                   pointer = c->attr.pointer;
+                   dimension = c->attr.dimension;
+                   codimension = c->attr.codimension;
+                   is_abstract = c->attr.abstract;
+                 }
                break;
 
              case REF_SUBSTRING:
@@ -5608,39 +6305,90 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
     {
       gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
                 &e->where);
-      return FAILURE;
+      goto failure;
     }
 
-  if (check_intent_in
-      && e->symtree->n.sym->attr.intent == INTENT_IN)
+  /* Some checks for the SOURCE tag.  */
+  if (code->expr3)
     {
-      gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
-                e->symtree->n.sym->name, &e->where);
-      return FAILURE;
+      /* Check F03:C631.  */
+      if (!gfc_type_compatible (&e->ts, &code->expr3->ts))
+       {
+         gfc_error ("Type of entity at %L is type incompatible with "
+                     "source-expr at %L", &e->where, &code->expr3->where);
+         goto failure;
+       }
+
+      /* Check F03:C632 and restriction following Note 6.18.  */
+      if (code->expr3->rank > 0
+         && conformable_arrays (code->expr3, e) == FAILURE)
+       goto failure;
+
+      /* Check F03:C633.  */
+      if (code->expr3->ts.kind != e->ts.kind)
+       {
+         gfc_error ("The allocate-object at %L and the source-expr at %L "
+                     "shall have the same kind type parameter",
+                     &e->where, &code->expr3->where);
+         goto failure;
+       }
+    }
+  else if (is_abstract&& code->ext.alloc.ts.type == BT_UNKNOWN)
+    {
+      gcc_assert (e->ts.type == BT_CLASS);
+      gfc_error ("Allocating %s of ABSTRACT base type at %L requires a "
+                "type-spec or SOURCE=", sym->name, &e->where);
+      goto failure;
     }
 
-  /* Add default initializer for those derived types that need them.  */
-  if (e->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&e->ts)))
+  if (check_intent_in && sym->attr.intent == INTENT_IN)
     {
-      init_st = gfc_get_code ();
-      init_st->loc = code->loc;
-      init_st->op = EXEC_INIT_ASSIGN;
-      init_st->expr1 = expr_to_initialize (e);
-      init_st->expr2 = init_e;
-      init_st->next = code->next;
-      code->next = init_st;
+      gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
+                sym->name, &e->where);
+      goto failure;
+    }
+    
+  if (!code->expr3)
+    {
+      /* Add default initializer for those derived types that need them.  */
+      if (e->ts.type == BT_DERIVED
+         && (init_e = gfc_default_initializer (&e->ts)))
+       {
+         gfc_code *init_st = gfc_get_code ();
+         init_st->loc = code->loc;
+         init_st->op = EXEC_INIT_ASSIGN;
+         init_st->expr1 = gfc_expr_to_initialize (e);
+         init_st->expr2 = init_e;
+         init_st->next = code->next;
+         code->next = init_st;
+       }
+      else if (e->ts.type == BT_CLASS
+              && ((code->ext.alloc.ts.type == BT_UNKNOWN
+                   && (init_e = gfc_default_initializer (&CLASS_DATA (e)->ts)))
+                  || (code->ext.alloc.ts.type == BT_DERIVED
+                      && (init_e = gfc_default_initializer (&code->ext.alloc.ts)))))
+       {
+         gfc_code *init_st = gfc_get_code ();
+         init_st->loc = code->loc;
+         init_st->op = EXEC_INIT_ASSIGN;
+         init_st->expr1 = gfc_expr_to_initialize (e);
+         init_st->expr2 = init_e;
+         init_st->next = code->next;
+         code->next = init_st;
+       }
     }
 
-  if (pointer && dimension == 0)
-    return SUCCESS;
+  if (pointer || (dimension == 0 && codimension == 0))
+    goto success;
 
   /* Make sure the next-to-last reference node is an array specification.  */
 
-  if (ref2 == NULL || ref2->type != REF_ARRAY || ref2->u.ar.type == AR_FULL)
+  if (ref2 == NULL || ref2->type != REF_ARRAY || ref2->u.ar.type == AR_FULL
+      || (dimension && ref2->u.ar.dimen == 0))
     {
       gfc_error ("Array specification required in ALLOCATE statement "
                 "at %L", &e->where);
-      return FAILURE;
+      goto failure;
     }
 
   /* Make sure that the array section reference makes sense in the
@@ -5648,6 +6396,13 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
 
   ar = &ref2->u.ar;
 
+  if (codimension && ar->codimen == 0)
+    {
+      gfc_error ("Coarray specification required in ALLOCATE statement "
+                "at %L", &e->where);
+      goto failure;
+    }
+
   for (i = 0; i < ar->dimen; i++)
     {
       if (ref2->u.ar.type == AR_ELEMENT)
@@ -5668,19 +6423,19 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
 
        case DIMEN_UNKNOWN:
        case DIMEN_VECTOR:
+       case DIMEN_STAR:
          gfc_error ("Bad array specification in ALLOCATE statement at %L",
                     &e->where);
-         return FAILURE;
+         goto failure;
        }
 
 check_symbols:
-
-      for (a = code->ext.alloc_list; a; a = a->next)
+      for (a = code->ext.alloc.list; a; a = a->next)
        {
          sym = a->expr->symtree->n.sym;
 
          /* TODO - check derived type components.  */
-         if (sym->ts.type == BT_DERIVED)
+         if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
            continue;
 
          if ((ar->start[i] != NULL
@@ -5691,12 +6446,46 @@ check_symbols:
              gfc_error ("'%s' must not appear in the array specification at "
                         "%L in the same ALLOCATE statement where it is "
                         "itself allocated", sym->name, &ar->where);
-             return FAILURE;
+             goto failure;
            }
        }
     }
 
+  for (i = ar->dimen; i < ar->codimen + ar->dimen; i++)
+    {
+      if (ar->dimen_type[i] == DIMEN_ELEMENT
+         || ar->dimen_type[i] == DIMEN_RANGE)
+       {
+         if (i == (ar->dimen + ar->codimen - 1))
+           {
+             gfc_error ("Expected '*' in coindex specification in ALLOCATE "
+                        "statement at %L", &e->where);
+             goto failure;
+           }
+         break;
+       }
+
+      if (ar->dimen_type[i] == DIMEN_STAR && i == (ar->dimen + ar->codimen - 1)
+         && ar->stride[i] == NULL)
+       break;
+
+      gfc_error ("Bad coarray specification in ALLOCATE statement at %L",
+                &e->where);
+      goto failure;
+    }
+
+  if (codimension && ar->as->rank == 0)
+    {
+      gfc_error ("Sorry, allocatable scalar coarrays are not yet supported "
+                "at %L", &e->where);
+      goto failure;
+    }
+
+success:
   return SUCCESS;
+
+failure:
+  return FAILURE;
 }
 
 static void
@@ -5720,13 +6509,14 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
        gfc_error ("Illegal stat-variable at %L for a PURE procedure",
                   &stat->where);
 
-      if (stat->ts.type != BT_INTEGER
-         && !(stat->ref && (stat->ref->type == REF_ARRAY
-              || stat->ref->type == REF_COMPONENT)))
+      if ((stat->ts.type != BT_INTEGER
+          && !(stat->ref && (stat->ref->type == REF_ARRAY
+                             || stat->ref->type == REF_COMPONENT)))
+         || stat->rank > 0)
        gfc_error ("Stat-variable at %L must be a scalar INTEGER "
                   "variable", &stat->where);
 
-      for (p = code->ext.alloc_list; p; p = p->next)
+      for (p = code->ext.alloc.list; p; p = p->next)
        if (p->expr->symtree->n.sym->name == stat->symtree->n.sym->name)
          gfc_error ("Stat-variable at %L shall not be %sd within "
                     "the same %s statement", &stat->where, fcn, fcn);
@@ -5747,14 +6537,15 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
        gfc_error ("Illegal errmsg-variable at %L for a PURE procedure",
                   &errmsg->where);
 
-      if (errmsg->ts.type != BT_CHARACTER
-         && !(errmsg->ref
-              && (errmsg->ref->type == REF_ARRAY
-                  || errmsg->ref->type == REF_COMPONENT)))
+      if ((errmsg->ts.type != BT_CHARACTER
+          && !(errmsg->ref
+               && (errmsg->ref->type == REF_ARRAY
+                   || errmsg->ref->type == REF_COMPONENT)))
+         || errmsg->rank > 0 )
        gfc_error ("Errmsg-variable at %L must be a scalar CHARACTER "
                   "variable", &errmsg->where);
 
-      for (p = code->ext.alloc_list; p; p = p->next)
+      for (p = code->ext.alloc.list; p; p = p->next)
        if (p->expr->symtree->n.sym->name == errmsg->symtree->n.sym->name)
          gfc_error ("Errmsg-variable at %L shall not be %sd within "
                     "the same %s statement", &errmsg->where, fcn, fcn);
@@ -5762,7 +6553,7 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
 
   /* Check that an allocate-object appears only once in the statement.  
      FIXME: Checking derived types is disabled.  */
-  for (p = code->ext.alloc_list; p; p = p->next)
+  for (p = code->ext.alloc.list; p; p = p->next)
     {
       pe = p->expr;
       if ((pe->ref && pe->ref->type != REF_COMPONENT)
@@ -5782,12 +6573,12 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
 
   if (strcmp (fcn, "ALLOCATE") == 0)
     {
-      for (a = code->ext.alloc_list; a; a = a->next)
+      for (a = code->ext.alloc.list; a; a = a->next)
        resolve_allocate_expr (a->expr, code);
     }
   else
     {
-      for (a = code->ext.alloc_list; a; a = a->next)
+      for (a = code->ext.alloc.list; a; a = a->next)
        resolve_deallocate_expr (a->expr);
     }
 }
@@ -6008,8 +6799,9 @@ validate_case_label_expr (gfc_expr *e, gfc_expr *case_expr)
       return FAILURE;
     }
 
-  /* Convert the case value kind to that of case expression kind, if needed.
-     FIXME:  Should a warning be issued?  */
+  /* Convert the case value kind to that of case expression kind,
+     if needed */
+
   if (e->ts.kind != case_expr->ts.kind)
     gfc_convert_type_warn (e, &case_expr->ts, 2, 0);
 
@@ -6095,6 +6887,31 @@ resolve_select (gfc_code *code)
       return;
     }
 
+
+  /* Raise a warning if an INTEGER case value exceeds the range of
+     the case-expr. Later, all expressions will be promoted to the
+     largest kind of all case-labels.  */
+
+  if (type == BT_INTEGER)
+    for (body = code->block; body; body = body->block)
+      for (cp = body->ext.case_list; cp; cp = cp->next)
+       {
+         if (cp->low
+             && gfc_check_integer_range (cp->low->value.integer,
+                                         case_expr->ts.kind) != ARITH_OK)
+           gfc_warning ("Expression in CASE statement at %L is "
+                        "not in the range of %s", &cp->low->where,
+                        gfc_typename (&case_expr->ts));
+
+         if (cp->high
+             && cp->low != cp->high
+             && gfc_check_integer_range (cp->high->value.integer,
+                                         case_expr->ts.kind) != ARITH_OK)
+           gfc_warning ("Expression in CASE statement at %L is "
+                        "not in the range of %s", &cp->high->where,
+                        gfc_typename (&case_expr->ts));
+       }
+
   /* PR 19168 has a long discussion concerning a mismatch of the kinds
      of the SELECT CASE expression and its CASE values.  Walk the lists
      of case values, and if we find a mismatch, promote case_expr to
@@ -6117,7 +6934,6 @@ resolve_select (gfc_code *code)
                  && gfc_compare_expr (cp->low, cp->high, INTRINSIC_GT) > 0)
                continue;
 
-             /* FIXME: Should a warning be issued?  */
              if (cp->low != NULL
                  && case_expr->ts.kind != gfc_kind_max(case_expr, cp->low))
                gfc_convert_type_warn (case_expr, &cp->low->ts, 2, 0);
@@ -6168,8 +6984,8 @@ resolve_select (gfc_code *code)
 
          /* Deal with single value cases and case ranges.  Errors are
             issued from the validation function.  */
-         if(validate_case_label_expr (cp->low, case_expr) != SUCCESS
-            || validate_case_label_expr (cp->high, case_expr) != SUCCESS)
+         if (validate_case_label_expr (cp->low, case_expr) != SUCCESS
+             || validate_case_label_expr (cp->high, case_expr) != SUCCESS)
            {
              t = FAILURE;
              break;
@@ -6191,7 +7007,7 @@ resolve_select (gfc_code *code)
              value = cp->low->value.logical == 0 ? 2 : 1;
              if (value & seen_logical)
                {
-                 gfc_error ("constant logical value in CASE statement "
+                 gfc_error ("Constant logical value in CASE statement "
                             "is repeated at %L",
                             &cp->low->where);
                  t = FAILURE;
@@ -6304,12 +7120,285 @@ resolve_select (gfc_code *code)
        }
     }
 
-  /* More than two cases is legal but insane for logical selects.
-     Issue a warning for it.  */
-  if (gfc_option.warn_surprising && type == BT_LOGICAL
-      && ncases > 2)
-    gfc_warning ("Logical SELECT CASE block at %L has more that two cases",
-                &code->loc);
+  /* More than two cases is legal but insane for logical selects.
+     Issue a warning for it.  */
+  if (gfc_option.warn_surprising && type == BT_LOGICAL
+      && ncases > 2)
+    gfc_warning ("Logical SELECT CASE block at %L has more that two cases",
+                &code->loc);
+}
+
+
+/* Check if a derived type is extensible.  */
+
+bool
+gfc_type_is_extensible (gfc_symbol *sym)
+{
+  return !(sym->attr.is_bind_c || sym->attr.sequence);
+}
+
+
+/* Resolve a SELECT TYPE statement.  */
+
+static void
+resolve_select_type (gfc_code *code)
+{
+  gfc_symbol *selector_type;
+  gfc_code *body, *new_st, *if_st, *tail;
+  gfc_code *class_is = NULL, *default_case = NULL;
+  gfc_case *c;
+  gfc_symtree *st;
+  char name[GFC_MAX_SYMBOL_LEN];
+  gfc_namespace *ns;
+  int error = 0;
+
+  ns = code->ext.ns;
+  gfc_resolve (ns);
+
+  /* Check for F03:C813.  */
+  if (code->expr1->ts.type != BT_CLASS
+      && !(code->expr2 && code->expr2->ts.type == BT_CLASS))
+    {
+      gfc_error ("Selector shall be polymorphic in SELECT TYPE statement "
+                "at %L", &code->loc);
+      return;
+    }
+
+  if (code->expr2)
+    {
+      if (code->expr1->symtree->n.sym->attr.untyped)
+       code->expr1->symtree->n.sym->ts = code->expr2->ts;
+      selector_type = CLASS_DATA (code->expr2)->ts.u.derived;
+    }
+  else
+    selector_type = CLASS_DATA (code->expr1)->ts.u.derived;
+
+  /* Loop over TYPE IS / CLASS IS cases.  */
+  for (body = code->block; body; body = body->block)
+    {
+      c = body->ext.case_list;
+
+      /* Check F03:C815.  */
+      if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
+         && !gfc_type_is_extensible (c->ts.u.derived))
+       {
+         gfc_error ("Derived type '%s' at %L must be extensible",
+                    c->ts.u.derived->name, &c->where);
+         error++;
+         continue;
+       }
+
+      /* Check F03:C816.  */
+      if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
+         && !gfc_type_is_extension_of (selector_type, c->ts.u.derived))
+       {
+         gfc_error ("Derived type '%s' at %L must be an extension of '%s'",
+                    c->ts.u.derived->name, &c->where, selector_type->name);
+         error++;
+         continue;
+       }
+
+      /* Intercept the DEFAULT case.  */
+      if (c->ts.type == BT_UNKNOWN)
+       {
+         /* Check F03:C818.  */
+         if (default_case)
+           {
+             gfc_error ("The DEFAULT CASE at %L cannot be followed "
+                        "by a second DEFAULT CASE at %L",
+                        &default_case->ext.case_list->where, &c->where);
+             error++;
+             continue;
+           }
+         else
+           default_case = body;
+       }
+    }
+    
+  if (error>0)
+    return;
+
+  if (code->expr2)
+    {
+      /* Insert assignment for selector variable.  */
+      new_st = gfc_get_code ();
+      new_st->op = EXEC_ASSIGN;
+      new_st->expr1 = gfc_copy_expr (code->expr1);
+      new_st->expr2 = gfc_copy_expr (code->expr2);
+      ns->code = new_st;
+    }
+
+  /* Put SELECT TYPE statement inside a BLOCK.  */
+  new_st = gfc_get_code ();
+  new_st->op = code->op;
+  new_st->expr1 = code->expr1;
+  new_st->expr2 = code->expr2;
+  new_st->block = code->block;
+  if (!ns->code)
+    ns->code = new_st;
+  else
+    ns->code->next = new_st;
+  code->op = EXEC_BLOCK;
+  code->expr1 = code->expr2 =  NULL;
+  code->block = NULL;
+
+  code = new_st;
+
+  /* Transform to EXEC_SELECT.  */
+  code->op = EXEC_SELECT;
+  gfc_add_component_ref (code->expr1, "$vptr");
+  gfc_add_component_ref (code->expr1, "$hash");
+
+  /* Loop over TYPE IS / CLASS IS cases.  */
+  for (body = code->block; body; body = body->block)
+    {
+      c = body->ext.case_list;
+
+      if (c->ts.type == BT_DERIVED)
+       c->low = c->high = gfc_get_int_expr (gfc_default_integer_kind, NULL,
+                                            c->ts.u.derived->hash_value);
+
+      else if (c->ts.type == BT_UNKNOWN)
+       continue;
+
+      /* Assign temporary to selector.  */
+      if (c->ts.type == BT_CLASS)
+       sprintf (name, "tmp$class$%s", c->ts.u.derived->name);
+      else
+       sprintf (name, "tmp$type$%s", c->ts.u.derived->name);
+      st = gfc_find_symtree (ns->sym_root, name);
+      new_st = gfc_get_code ();
+      new_st->expr1 = gfc_get_variable_expr (st);
+      new_st->expr2 = gfc_get_variable_expr (code->expr1->symtree);
+      if (c->ts.type == BT_DERIVED)
+       {
+         new_st->op = EXEC_POINTER_ASSIGN;
+         gfc_add_component_ref (new_st->expr2, "$data");
+       }
+      else
+       new_st->op = EXEC_POINTER_ASSIGN;
+      new_st->next = body->next;
+      body->next = new_st;
+    }
+    
+  /* Take out CLASS IS cases for separate treatment.  */
+  body = code;
+  while (body && body->block)
+    {
+      if (body->block->ext.case_list->ts.type == BT_CLASS)
+       {
+         /* Add to class_is list.  */
+         if (class_is == NULL)
+           { 
+             class_is = body->block;
+             tail = class_is;
+           }
+         else
+           {
+             for (tail = class_is; tail->block; tail = tail->block) ;
+             tail->block = body->block;
+             tail = tail->block;
+           }
+         /* Remove from EXEC_SELECT list.  */
+         body->block = body->block->block;
+         tail->block = NULL;
+       }
+      else
+       body = body->block;
+    }
+
+  if (class_is)
+    {
+      gfc_symbol *vtab;
+      
+      if (!default_case)
+       {
+         /* Add a default case to hold the CLASS IS cases.  */
+         for (tail = code; tail->block; tail = tail->block) ;
+         tail->block = gfc_get_code ();
+         tail = tail->block;
+         tail->op = EXEC_SELECT_TYPE;
+         tail->ext.case_list = gfc_get_case ();
+         tail->ext.case_list->ts.type = BT_UNKNOWN;
+         tail->next = NULL;
+         default_case = tail;
+       }
+
+      /* More than one CLASS IS block?  */
+      if (class_is->block)
+       {
+         gfc_code **c1,*c2;
+         bool swapped;
+         /* Sort CLASS IS blocks by extension level.  */
+         do
+           {
+             swapped = false;
+             for (c1 = &class_is; (*c1) && (*c1)->block; c1 = &((*c1)->block))
+               {
+                 c2 = (*c1)->block;
+                 /* F03:C817 (check for doubles).  */
+                 if ((*c1)->ext.case_list->ts.u.derived->hash_value
+                     == c2->ext.case_list->ts.u.derived->hash_value)
+                   {
+                     gfc_error ("Double CLASS IS block in SELECT TYPE "
+                                "statement at %L", &c2->ext.case_list->where);
+                     return;
+                   }
+                 if ((*c1)->ext.case_list->ts.u.derived->attr.extension
+                     < c2->ext.case_list->ts.u.derived->attr.extension)
+                   {
+                     /* Swap.  */
+                     (*c1)->block = c2->block;
+                     c2->block = *c1;
+                     *c1 = c2;
+                     swapped = true;
+                   }
+               }
+           }
+         while (swapped);
+       }
+       
+      /* Generate IF chain.  */
+      if_st = gfc_get_code ();
+      if_st->op = EXEC_IF;
+      new_st = if_st;
+      for (body = class_is; body; body = body->block)
+       {
+         new_st->block = gfc_get_code ();
+         new_st = new_st->block;
+         new_st->op = EXEC_IF;
+         /* Set up IF condition: Call _gfortran_is_extension_of.  */
+         new_st->expr1 = gfc_get_expr ();
+         new_st->expr1->expr_type = EXPR_FUNCTION;
+         new_st->expr1->ts.type = BT_LOGICAL;
+         new_st->expr1->ts.kind = 4;
+         new_st->expr1->value.function.name = gfc_get_string (PREFIX ("is_extension_of"));
+         new_st->expr1->value.function.isym = XCNEW (gfc_intrinsic_sym);
+         new_st->expr1->value.function.isym->id = GFC_ISYM_EXTENDS_TYPE_OF;
+         /* Set up arguments.  */
+         new_st->expr1->value.function.actual = gfc_get_actual_arglist ();
+         new_st->expr1->value.function.actual->expr = gfc_get_variable_expr (code->expr1->symtree);
+         gfc_add_component_ref (new_st->expr1->value.function.actual->expr, "$vptr");
+         vtab = gfc_find_derived_vtab (body->ext.case_list->ts.u.derived, true);
+         st = gfc_find_symtree (vtab->ns->sym_root, vtab->name);
+         new_st->expr1->value.function.actual->next = gfc_get_actual_arglist ();
+         new_st->expr1->value.function.actual->next->expr = gfc_get_variable_expr (st);
+         new_st->next = body->next;
+       }
+       if (default_case->next)
+         {
+           new_st->block = gfc_get_code ();
+           new_st = new_st->block;
+           new_st->op = EXEC_IF;
+           new_st->next = default_case->next;
+         }
+         
+       /* Replace CLASS DEFAULT code by the IF chain.  */
+       default_case->next = if_st;
+    }
+
+  resolve_select (code);
+
 }
 
 
@@ -6409,6 +7498,49 @@ find_reachable_labels (gfc_code *block)
     }
 }
 
+
+static void
+resolve_sync (gfc_code *code)
+{
+  /* Check imageset. The * case matches expr1 == NULL.  */
+  if (code->expr1)
+    {
+      if (code->expr1->ts.type != BT_INTEGER || code->expr1->rank > 1)
+       gfc_error ("Imageset argument at %L must be a scalar or rank-1 "
+                  "INTEGER expression", &code->expr1->where);
+      if (code->expr1->expr_type == EXPR_CONSTANT && code->expr1->rank == 0
+         && mpz_cmp_si (code->expr1->value.integer, 1) < 0)
+       gfc_error ("Imageset argument at %L must between 1 and num_images()",
+                  &code->expr1->where);
+      else if (code->expr1->expr_type == EXPR_ARRAY
+              && gfc_simplify_expr (code->expr1, 0) == SUCCESS)
+       {
+          gfc_constructor *cons;
+          cons = gfc_constructor_first (code->expr1->value.constructor);
+          for (; cons; cons = gfc_constructor_next (cons))
+            if (cons->expr->expr_type == EXPR_CONSTANT
+                &&  mpz_cmp_si (cons->expr->value.integer, 1) < 0)
+              gfc_error ("Imageset argument at %L must between 1 and "
+                         "num_images()", &cons->expr->where);
+       }
+    }
+
+  /* Check STAT.  */
+  if (code->expr2
+      && (code->expr2->ts.type != BT_INTEGER || code->expr2->rank != 0
+         || code->expr2->expr_type != EXPR_VARIABLE))
+    gfc_error ("STAT= argument at %L must be a scalar INTEGER variable",
+              &code->expr2->where);
+
+  /* Check ERRMSG.  */
+  if (code->expr3
+      && (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0
+         || code->expr3->expr_type != EXPR_VARIABLE))
+    gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable",
+              &code->expr3->where);
+}
+
+
 /* Given a branch to a label, see if the branch is conforming.
    The code node describes where the branch is located.  */
 
@@ -6449,15 +7581,36 @@ resolve_branch (gfc_st_label *label, gfc_code *code)
      the bitmap reachable_labels.  */
 
   if (bitmap_bit_p (cs_base->reachable_labels, label->value))
-    return;
+    {
+      /* Check now whether there is a CRITICAL construct; if so, check
+        whether the label is still visible outside of the CRITICAL block,
+        which is invalid.  */
+      for (stack = cs_base; stack; stack = stack->prev)
+       if (stack->current->op == EXEC_CRITICAL
+           && bitmap_bit_p (stack->reachable_labels, label->value))
+         gfc_error ("GOTO statement at %L leaves CRITICAL construct for label"
+                     " at %L", &code->loc, &label->where);
+
+      return;
+    }
 
   /* Step four:  If we haven't found the label in the bitmap, it may
     still be the label of the END of the enclosing block, in which
     case we find it by going up the code_stack.  */
 
   for (stack = cs_base; stack; stack = stack->prev)
-    if (stack->current->next && stack->current->next->here == label)
-      break;
+    {
+      if (stack->current->next && stack->current->next->here == label)
+       break;
+      if (stack->current->op == EXEC_CRITICAL)
+       {
+         /* Note: A label at END CRITICAL does not leave the CRITICAL
+            construct as END CRITICAL is still part of it.  */
+         gfc_error ("GOTO statement at %L leaves CRITICAL construct for label"
+                     " at %L", &code->loc, &label->where);
+         return;
+       }
+    }
 
   if (stack)
     {
@@ -6824,7 +7977,19 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
 }
 
 
-/* Resolve lists of blocks found in IF, SELECT CASE, WHERE, FORALL ,GOTO and
+/* Resolve a BLOCK construct statement.  */
+
+static void
+resolve_block_construct (gfc_code* code)
+{
+  /* Eventually, we may want to do some checks here or handle special stuff.
+     But so far the only thing we can do is resolving the local namespace.  */
+
+  gfc_resolve (code->ext.ns);
+}
+
+
+/* Resolve lists of blocks found in IF, SELECT CASE, WHERE, FORALL, GOTO and
    DO code nodes.  */
 
 static void resolve_code (gfc_code *, gfc_namespace *);
@@ -6861,10 +8026,16 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
          resolve_branch (b->label1, b);
          break;
 
+       case EXEC_BLOCK:
+         resolve_block_construct (b);
+         break;
+
        case EXEC_SELECT:
+       case EXEC_SELECT_TYPE:
        case EXEC_FORALL:
        case EXEC_DO:
        case EXEC_DO_WHILE:
+       case EXEC_CRITICAL:
        case EXEC_READ:
        case EXEC_WRITE:
        case EXEC_IOLENGTH:
@@ -6888,7 +8059,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
          break;
 
        default:
-         gfc_internal_error ("resolve_block(): Bad block type");
+         gfc_internal_error ("gfc_resolve_blocks(): Bad block type");
        }
 
       resolve_code (b->next, ns);
@@ -6911,23 +8082,35 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
 
   if (gfc_extend_assign (code, ns) == SUCCESS)
     {
-      lhs = code->ext.actual->expr;
-      rhs = code->ext.actual->next->expr;
-      if (gfc_pure (NULL) && !gfc_pure (code->symtree->n.sym))
+      gfc_expr** rhsptr;
+
+      if (code->op == EXEC_ASSIGN_CALL)
        {
-         gfc_error ("Subroutine '%s' called instead of assignment at "
-                    "%L must be PURE", code->symtree->n.sym->name,
-                    &code->loc);
-         return rval;
+         lhs = code->ext.actual->expr;
+         rhsptr = &code->ext.actual->next->expr;
+       }
+      else
+       {
+         gfc_actual_arglist* args;
+         gfc_typebound_proc* tbp;
+
+         gcc_assert (code->op == EXEC_COMPCALL);
+
+         args = code->expr1->value.compcall.actual;
+         lhs = args->expr;
+         rhsptr = &args->next->expr;
+
+         tbp = code->expr1->value.compcall.tbp;
+         gcc_assert (!tbp->is_generic);
        }
 
       /* Make a temporary rhs when there is a default initializer
         and rhs is the same symbol as the lhs.  */
-      if (rhs->expr_type == EXPR_VARIABLE
-           && rhs->symtree->n.sym->ts.type == BT_DERIVED
-           && has_default_initializer (rhs->symtree->n.sym->ts.u.derived)
-           && (lhs->symtree->n.sym == rhs->symtree->n.sym))
-        code->ext.actual->next->expr = gfc_get_parentheses (rhs);
+      if ((*rhsptr)->expr_type == EXPR_VARIABLE
+           && (*rhsptr)->symtree->n.sym->ts.type == BT_DERIVED
+           && gfc_has_default_initializer ((*rhsptr)->symtree->n.sym->ts.u.derived)
+           && (lhs->symtree->n.sym == (*rhsptr)->symtree->n.sym))
+       *rhsptr = gfc_get_parentheses (*rhsptr);
 
       return true;
     }
@@ -6937,8 +8120,8 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
 
   if (rhs->is_boz
       && gfc_notify_std (GFC_STD_GNU, "Extension: BOZ literal at %L outside "
-                         "a DATA statement and outside INT/REAL/DBLE/CMPLX",
-                         &code->loc) == FAILURE)
+                        "a DATA statement and outside INT/REAL/DBLE/CMPLX",
+                        &code->loc) == FAILURE)
     return false;
 
   /* Handle the case of a BOZ literal on the RHS.  */
@@ -6983,7 +8166,7 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
        rlen = rhs->value.character.length;
 
       else if (rhs->ts.u.cl != NULL
-                && rhs->ts.u.cl->length != NULL
+                && rhs->ts.u.cl->length != NULL
                 && rhs->ts.u.cl->length->expr_type == EXPR_CONSTANT)
        rlen = mpz_get_si (rhs->ts.u.cl->length->value.integer);
 
@@ -7023,20 +8206,56 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
       if (lhs->ts.type == BT_DERIVED
            && lhs->expr_type == EXPR_VARIABLE
            && lhs->ts.u.derived->attr.pointer_comp
-           && gfc_impure_variable (rhs->symtree->n.sym))
+           && rhs->expr_type == EXPR_VARIABLE
+           && (gfc_impure_variable (rhs->symtree->n.sym)
+               || gfc_is_coindexed (rhs)))
+       {
+         /* F2008, C1283.  */
+         if (gfc_is_coindexed (rhs))
+           gfc_error ("Coindexed expression at %L is assigned to "
+                       "a derived type variable with a POINTER "
+                       "component in a PURE procedure",
+                       &rhs->where);
+         else
+           gfc_error ("The impure variable at %L is assigned to "
+                       "a derived type variable with a POINTER "
+                       "component in a PURE procedure (12.6)",
+                       &rhs->where);
+         return rval;
+       }
+
+      /* Fortran 2008, C1283.  */
+      if (gfc_is_coindexed (lhs))
        {
-         gfc_error ("The impure variable at %L is assigned to "
-                    "a derived type variable with a POINTER "
-                    "component in a PURE procedure (12.6)",
-                    &rhs->where);
+         gfc_error ("Assignment to coindexed variable at %L in a PURE "
+                    "procedure", &rhs->where);
          return rval;
        }
     }
 
+  /* F03:7.4.1.2.  */
+  /* FIXME: Valid in Fortran 2008, unless the LHS is both polymorphic
+     and coindexed; cf. F2008, 7.2.1.2 and PR 43366.  */
+  if (lhs->ts.type == BT_CLASS)
+    {
+      gfc_error ("Variable must not be polymorphic in assignment at %L",
+                &lhs->where);
+      return false;
+    }
+
+  /* F2008, Section 7.2.1.2.  */
+  if (gfc_is_coindexed (lhs) && gfc_has_ultimate_allocatable (lhs))
+    {
+      gfc_error ("Coindexed variable must not be have an allocatable ultimate "
+                "component in assignment at %L", &lhs->where);
+      return false;
+    }
+
   gfc_check_assign (lhs, rhs, 1);
   return false;
 }
 
+
 /* Given a block of code, recursively resolve everything pointed to by this
    code block.  */
 
@@ -7086,6 +8305,11 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
            case EXEC_OMP_DO:
              gfc_resolve_omp_do_blocks (code, ns);
              break;
+           case EXEC_SELECT_TYPE:
+             gfc_current_ns = code->ext.ns;
+             gfc_resolve_blocks (code->block, gfc_current_ns);
+             gfc_current_ns = ns;
+             break;
            case EXEC_OMP_WORKSHARE:
              omp_workshare_save = omp_workshare_flag;
              omp_workshare_flag = 1;
@@ -7107,6 +8331,10 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
       if (gfc_resolve_expr (code->expr2) == FAILURE)
        t = FAILURE;
 
+      if (code->op == EXEC_ALLOCATE
+         && gfc_resolve_expr (code->expr3) == FAILURE)
+       t = FAILURE;
+
       switch (code->op)
        {
        case EXEC_NOP:
@@ -7114,9 +8342,18 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
        case EXEC_CYCLE:
        case EXEC_PAUSE:
        case EXEC_STOP:
+       case EXEC_ERROR_STOP:
        case EXEC_EXIT:
        case EXEC_CONTINUE:
        case EXEC_DT_END:
+       case EXEC_ASSIGN_CALL:
+       case EXEC_CRITICAL:
+         break;
+
+       case EXEC_SYNC_ALL:
+       case EXEC_SYNC_IMAGES:
+       case EXEC_SYNC_MEMORY:
+         resolve_sync (code);
          break;
 
        case EXEC_ENTRY:
@@ -7159,8 +8396,12 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
            break;
 
          if (resolve_ordinary_assign (code, ns))
-           goto call;
-
+           {
+             if (code->op == EXEC_COMPCALL)
+               goto compcall;
+             else
+               goto call;
+           }
          break;
 
        case EXEC_LABEL_ASSIGN:
@@ -7210,11 +8451,12 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          break;
 
        case EXEC_COMPCALL:
-         resolve_typebound_call (code);
+       compcall:
+         resolve_typebound_subroutine (code);
          break;
 
        case EXEC_CALL_PPC:
-          resolve_ppc_call (code);
+         resolve_ppc_call (code);
          break;
 
        case EXEC_SELECT:
@@ -7223,6 +8465,14 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          resolve_select (code);
          break;
 
+       case EXEC_SELECT_TYPE:
+         resolve_select_type (code);
+         break;
+
+       case EXEC_BLOCK:
+         gfc_resolve (code->ext.ns);
+         break;
+
        case EXEC_DO:
          if (code->ext.iterator != NULL)
            {
@@ -7615,9 +8865,12 @@ resolve_charlen (gfc_charlen *cl)
      value, the length of character entities declared is zero."  */
   if (cl->length && !gfc_extract_int (cl->length, &i) && i < 0)
     {
-      gfc_warning_now ("CHARACTER variable has zero length at %L",
-                      &cl->length->where);
-      gfc_replace_expr (cl->length, gfc_int_expr (0));
+      if (gfc_option.warn_surprising)
+       gfc_warning_now ("CHARACTER variable at %L has negative length %d,"
+                        " the length has been set to zero",
+                        &cl->length->where, i);
+      gfc_replace_expr (cl->length,
+                       gfc_get_int_expr (gfc_default_integer_kind, NULL, 0));
     }
 
   /* Check that the character length is not too large.  */
@@ -7649,13 +8902,12 @@ is_non_constant_shape_array (gfc_symbol *sym)
       /* 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++)
+      for (i = 0; i < sym->as->rank + sym->as->corank; i++)
        {
          e = sym->as->lower[i];
          if (e && (resolve_index_expr (e) == FAILURE
                    || !gfc_is_constant_expr (e)))
            not_constant = true;
-
          e = sym->as->upper[i];
          if (e && (resolve_index_expr (e) == FAILURE
                    || !gfc_is_constant_expr (e)))
@@ -7750,12 +9002,9 @@ build_default_init_expr (gfc_symbol *sym)
     return NULL;
 
   /* Now we'll try to build an initializer expression.  */
-  init_expr = gfc_get_expr ();
-  init_expr->expr_type = EXPR_CONSTANT;
-  init_expr->ts.type = sym->ts.type;
-  init_expr->ts.kind = sym->ts.kind;
-  init_expr->where = sym->declared_at;
-  
+  init_expr = gfc_get_constant_expr (sym->ts.type, sym->ts.kind,
+                                    &sym->declared_at);
+
   /* We will only initialize integers, reals, complex, logicals, and
      characters, and only if the corresponding command-line flags
      were set.  Otherwise, we free init_expr and return null.  */
@@ -7803,12 +9052,7 @@ build_default_init_expr (gfc_symbol *sym)
       break;
          
     case BT_COMPLEX:
-#ifdef HAVE_mpc
       mpc_init2 (init_expr->value.complex, mpfr_get_default_prec());
-#else
-      mpfr_init (init_expr->value.complex.r);
-      mpfr_init (init_expr->value.complex.i);
-#endif
       switch (gfc_option.flag_init_real)
        {
        case GFC_INIT_REAL_SNAN:
@@ -7830,12 +9074,7 @@ build_default_init_expr (gfc_symbol *sym)
          break;
 
        case GFC_INIT_REAL_ZERO:
-#ifdef HAVE_mpc
          mpc_set_ui (init_expr->value.complex, 0, GFC_MPC_RND_MODE);
-#else
-         mpfr_set_ui (init_expr->value.complex.r, 0.0, GFC_RND_MODE);
-         mpfr_set_ui (init_expr->value.complex.i, 0.0, GFC_RND_MODE);
-#endif
          break;
 
        default:
@@ -7904,7 +9143,8 @@ apply_default_init_local (gfc_symbol *sym)
 
   /* For saved variables, we don't want to add an initializer at 
      function entry, so we just add a static initializer.  */
-  if (sym->attr.save || sym->ns->save_all)
+  if (sym->attr.save || sym->ns->save_all 
+      || gfc_option.flag_max_stack_var_size == 0)
     {
       /* Don't clobber an existing initializer!  */
       gcc_assert (sym->value == NULL);
@@ -7926,11 +9166,14 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag)
       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);
+           {
+             gfc_error ("Allocatable array '%s' at %L must have "
+                        "a deferred shape", sym->name, &sym->declared_at);
+             return FAILURE;
+           }
+         else if (gfc_notify_std (GFC_STD_F2003, "Scalar object '%s' at %L "
+                                  "may not be ALLOCATABLE", sym->name,
+                                  &sym->declared_at) == FAILURE)
            return FAILURE;
        }
 
@@ -7944,24 +9187,38 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag)
     }
   else
     {
-      if (!mp_flag && !sym->attr.allocatable
-         && !sym->attr.pointer && !sym->attr.dummy)
+      if (!mp_flag && !sym->attr.allocatable && !sym->attr.pointer
+         && !sym->attr.dummy && sym->ts.type != BT_CLASS)
        {
          gfc_error ("Array '%s' at %L cannot have a deferred shape",
                     sym->name, &sym->declared_at);
          return FAILURE;
         }
     }
-  return SUCCESS;
-}
-
 
-/* Check if a derived type is extensible.  */
+  /* Constraints on polymorphic variables.  */
+  if (sym->ts.type == BT_CLASS && !(sym->result && sym->result != sym))
+    {
+      /* F03:C502.  */
+      if (!gfc_type_is_extensible (CLASS_DATA (sym)->ts.u.derived))
+       {
+         gfc_error ("Type '%s' of CLASS variable '%s' at %L is not extensible",
+                    CLASS_DATA (sym)->ts.u.derived->name, sym->name,
+                    &sym->declared_at);
+         return FAILURE;
+       }
 
-static bool
-type_is_extensible (gfc_symbol *sym)
-{
-  return !(sym->attr.is_bind_c || sym->attr.sequence);
+      /* F03:C509.  */
+      /* Assume that use associated symbols were checked in the module ns.  */ 
+      if (!sym->attr.class_ok && !sym->attr.use_assoc)
+       {
+         gfc_error ("CLASS variable '%s' at %L must be dummy, allocatable "
+                    "or pointer", sym->name, &sym->declared_at);
+         return FAILURE;
+       }
+    }
+    
+  return SUCCESS;
 }
 
 
@@ -7971,7 +9228,7 @@ type_is_extensible (gfc_symbol *sym)
 static gfc_try
 resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
 {
-  gcc_assert (sym->ts.type == BT_DERIVED);
+  gcc_assert (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS);
 
   /* Check to see if a derived type is blocked from being host
      associated by the presence of another class I symbol in the same
@@ -7999,38 +9256,18 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
      or POINTER attribute, the object shall have the SAVE attribute."
 
      The check for initializers is performed with
-     has_default_initializer because gfc_default_initializer generates
+     gfc_has_default_initializer because gfc_default_initializer generates
      a hidden default for allocatable components.  */
   if (!(sym->value || no_init_flag) && sym->ns->proc_name
       && sym->ns->proc_name->attr.flavor == FL_MODULE
       && !sym->ns->save_all && !sym->attr.save
       && !sym->attr.pointer && !sym->attr.allocatable
-      && has_default_initializer (sym->ts.u.derived))
-    {
-      gfc_error("Object '%s' at %L must have the SAVE attribute for "
-               "default initialization of a component",
-               sym->name, &sym->declared_at);
-      return FAILURE;
-    }
-
-  if (sym->ts.is_class)
-    {
-      /* C502.  */
-      if (!type_is_extensible (sym->ts.u.derived))
-       {
-         gfc_error ("Type '%s' of CLASS variable '%s' at %L is not extensible",
-                    sym->ts.u.derived->name, sym->name, &sym->declared_at);
-         return FAILURE;
-       }
-
-      /* C509.  */
-      if (!(sym->attr.dummy || sym->attr.allocatable || sym->attr.pointer))
-       {
-         gfc_error ("CLASS variable '%s' at %L must be dummy, allocatable "
-                    "or pointer", sym->name, &sym->declared_at);
-         return FAILURE;
-       }
-    }
+      && gfc_has_default_initializer (sym->ts.u.derived)
+      && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Implied SAVE for "
+                        "module variable '%s' at %L, needed due to "
+                        "the default initialization", sym->name,
+                        &sym->declared_at) == FAILURE)
+    return FAILURE;
 
   /* Assign default initializer.  */
   if (!(sym->value || sym->attr.pointer || sym->attr.allocatable)
@@ -8119,7 +9356,7 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
   if (sym->attr.allocatable || sym->attr.external || sym->attr.dummy
       || sym->attr.intrinsic || sym->attr.result)
     no_init_flag = 1;
-  else if (sym->attr.dimension && !sym->attr.pointer
+  else if ((sym->attr.dimension || sym->attr.codimension) && !sym->attr.pointer
           && is_non_constant_shape_array (sym))
     {
       no_init_flag = automatic_flag = 1;
@@ -8165,7 +9402,7 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
     }
 
 no_init_error:
-  if (sym->ts.type == BT_DERIVED)
+  if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
     return resolve_fl_variable_derived (sym, no_init_flag);
 
   return SUCCESS;
@@ -8179,10 +9416,6 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
 {
   gfc_formal_arglist *arg;
 
-  if (sym->attr.ambiguous_interfaces && !sym->attr.referenced)
-    gfc_warning ("Although not referenced, '%s' at %L has ambiguous "
-                "interfaces", sym->name, &sym->declared_at);
-
   if (sym->attr.function
       && resolve_fl_var_and_proc (sym, mp_flag) == FAILURE)
     return FAILURE;
@@ -8195,23 +9428,12 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
             && resolve_charlen (cl) == FAILURE)
        return FAILURE;
 
-      if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT)
+      if ((!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT)
+         && sym->attr.proc == PROC_ST_FUNCTION)
        {
-         if (sym->attr.proc == PROC_ST_FUNCTION)
-           {
-             gfc_error ("Character-valued statement function '%s' at %L must "
-                        "have constant length", sym->name, &sym->declared_at);
-             return FAILURE;
-           }
-
-         if (sym->attr.external && sym->formal == NULL
-             && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT)
-           {
-             gfc_error ("Automatic character length function '%s' at %L must "
-                        "have an explicit interface", sym->name,
-                        &sym->declared_at);
-             return FAILURE;
-           }
+         gfc_error ("Character-valued statement function '%s' at %L must "
+                    "have constant length", sym->name, &sym->declared_at);
+         return FAILURE;
        }
     }
 
@@ -8747,8 +9969,8 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
       if (proc_pass_arg != argpos && old_pass_arg != argpos
          && !gfc_compare_types (&proc_formal->sym->ts, &old_formal->sym->ts))
        {
-         gfc_error ("Types mismatch for dummy argument '%s' of '%s' %L in"
-                    " in respect to the overridden procedure",
+         gfc_error ("Types mismatch for dummy argument '%s' of '%s' %L "
+                    "in respect to the overridden procedure",
                     proc_formal->sym->name, proc->name, &where);
          return FAILURE;
        }
@@ -8811,6 +10033,9 @@ check_generic_tbp_ambiguity (gfc_tbp_generic* t1, gfc_tbp_generic* t2,
   sym1 = t1->specific->u.specific->n.sym;
   sym2 = t2->specific->u.specific->n.sym;
 
+  if (sym1 == sym2)
+    return SUCCESS;
+
   /* Both must be SUBROUTINEs or both must be FUNCTIONs.  */
   if (sym1->attr.subroutine != sym2->attr.subroutine
       || sym1->attr.function != sym2->attr.function)
@@ -8822,7 +10047,7 @@ check_generic_tbp_ambiguity (gfc_tbp_generic* t1, gfc_tbp_generic* t2,
     }
 
   /* Compare the interfaces.  */
-  if (gfc_compare_interfaces (sym1, sym2, 1, 0, NULL, 0))
+  if (gfc_compare_interfaces (sym1, sym2, sym2->name, 1, 0, NULL, 0))
     {
       gfc_error ("'%s' and '%s' for GENERIC '%s' at %L are ambiguous",
                 sym1->name, sym2->name, generic_name, &where);
@@ -8872,8 +10097,8 @@ resolve_tb_generic_targets (gfc_symbol* super_type,
        /* Look for an inherited specific binding.  */
        if (super_type)
          {
-           inherited = gfc_find_typebound_proc (super_type, NULL,
-                                                target_name, true);
+           inherited = gfc_find_typebound_proc (super_type, NULL, target_name,
+                                                true, NULL);
 
            if (inherited)
              {
@@ -8954,7 +10179,8 @@ resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st)
   if (super_type)
     {
       gfc_symtree* overridden;
-      overridden = gfc_find_typebound_proc (super_type, NULL, st->name, true);
+      overridden = gfc_find_typebound_proc (super_type, NULL, st->name,
+                                           true, NULL);
 
       if (overridden && overridden->n.tb)
        st->n.tb->overridden = overridden->n.tb;
@@ -8965,6 +10191,29 @@ resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st)
 }
 
 
+/* Retrieve the target-procedure of an operator binding and do some checks in
+   common for intrinsic and user-defined type-bound operators.  */
+
+static gfc_symbol*
+get_checked_tb_operator_target (gfc_tbp_generic* target, locus where)
+{
+  gfc_symbol* target_proc;
+
+  gcc_assert (target->specific && !target->specific->is_generic);
+  target_proc = target->specific->u.specific->n.sym;
+  gcc_assert (target_proc);
+
+  /* All operator bindings must have a passed-object dummy argument.  */
+  if (target->specific->nopass)
+    {
+      gfc_error ("Type-bound operator at %L can't be NOPASS", &where);
+      return NULL;
+    }
+
+  return target_proc;
+}
+
+
 /* Resolve a type-bound intrinsic operator.  */
 
 static gfc_try
@@ -8985,7 +10234,7 @@ resolve_typebound_intrinsic_op (gfc_symbol* derived, gfc_intrinsic_op op,
   super_type = gfc_get_derived_super_type (derived);
   if (super_type && super_type->f2k_derived)
     p->overridden = gfc_find_typebound_intrinsic_op (super_type, NULL,
-                                                    op, true);
+                                                    op, true, NULL);
   else
     p->overridden = NULL;
 
@@ -8998,12 +10247,12 @@ resolve_typebound_intrinsic_op (gfc_symbol* derived, gfc_intrinsic_op op,
     {
       gfc_symbol* target_proc;
 
-      gcc_assert (target->specific && !target->specific->is_generic);
-      target_proc = target->specific->u.specific->n.sym;
-      gcc_assert (target_proc);
+      target_proc = get_checked_tb_operator_target (target, p->where);
+      if (!target_proc)
+       goto error;
 
       if (!gfc_check_operator_interface (target_proc, op, p->where))
-       return FAILURE;
+       goto error;
     }
 
   return SUCCESS;
@@ -9041,7 +10290,7 @@ resolve_typebound_user_op (gfc_symtree* stree)
     {
       gfc_symtree* overridden;
       overridden = gfc_find_typebound_user_op (super_type, NULL,
-                                              stree->name, true);
+                                              stree->name, true, NULL);
 
       if (overridden && overridden->n.tb)
        stree->n.tb->overridden = overridden->n.tb;
@@ -9059,9 +10308,9 @@ resolve_typebound_user_op (gfc_symtree* stree)
     {
       gfc_symbol* target_proc;
 
-      gcc_assert (target->specific && !target->specific->is_generic);
-      target_proc = target->specific->u.specific->n.sym;
-      gcc_assert (target_proc);
+      target_proc = get_checked_tb_operator_target (target, stree->n.tb->where);
+      if (!target_proc)
+       goto error;
 
       if (check_uop_procedure (target_proc, stree->n.tb->where) == FAILURE)
        goto error;
@@ -9178,21 +10427,44 @@ resolve_typebound_procedure (gfc_symtree* stree)
          me_arg = proc->formal->sym;
        }
 
-      /* Now check that the argument-type matches.  */
+      /* Now check that the argument-type matches and the passed-object
+        dummy argument is generally fine.  */
+
       gcc_assert (me_arg);
-      if (me_arg->ts.type != BT_DERIVED
-         || me_arg->ts.u.derived != resolve_bindings_derived)
+
+      if (me_arg->ts.type != BT_CLASS)
+       {
+         gfc_error ("Non-polymorphic passed-object dummy argument of '%s'"
+                    " at %L", proc->name, &where);
+         goto error;
+       }
+
+      if (CLASS_DATA (me_arg)->ts.u.derived
+         != resolve_bindings_derived)
        {
          gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L must be of"
                     " the derived-type '%s'", me_arg->name, proc->name,
                     me_arg->name, &where, resolve_bindings_derived->name);
          goto error;
        }
-
-      if (!me_arg->ts.is_class)
+  
+      gcc_assert (me_arg->ts.type == BT_CLASS);
+      if (CLASS_DATA (me_arg)->as && CLASS_DATA (me_arg)->as->rank > 0)
        {
-         gfc_error ("Non-polymorphic passed-object dummy argument of '%s'"
-                    " at %L", proc->name, &where);
+         gfc_error ("Passed-object dummy argument of '%s' at %L must be"
+                    " scalar", proc->name, &where);
+         goto error;
+       }
+      if (CLASS_DATA (me_arg)->attr.allocatable)
+       {
+         gfc_error ("Passed-object dummy argument of '%s' at %L must not"
+                    " be ALLOCATABLE", proc->name, &where);
+         goto error;
+       }
+      if (CLASS_DATA (me_arg)->attr.class_pointer)
+       {
+         gfc_error ("Passed-object dummy argument of '%s' at %L must not"
+                    " be POINTER", proc->name, &where);
          goto error;
        }
     }
@@ -9204,7 +10476,7 @@ resolve_typebound_procedure (gfc_symtree* stree)
     {
       gfc_symtree* overridden;
       overridden = gfc_find_typebound_proc (super_type, NULL,
-                                           stree->name, true);
+                                           stree->name, true, NULL);
 
       if (overridden && overridden->n.tb)
        stree->n.tb->overridden = overridden->n.tb;
@@ -9244,7 +10516,6 @@ static gfc_try
 resolve_typebound_procedures (gfc_symbol* derived)
 {
   int op;
-  bool found_op;
 
   if (!derived->f2k_derived || !derived->f2k_derived->tb_sym_root)
     return SUCCESS;
@@ -9256,7 +10527,6 @@ resolve_typebound_procedures (gfc_symbol* derived)
     gfc_traverse_symtree (derived->f2k_derived->tb_sym_root,
                          &resolve_typebound_procedure);
 
-  found_op = (derived->f2k_derived->tb_uop_root != NULL);
   if (derived->f2k_derived->tb_uop_root)
     gfc_traverse_symtree (derived->f2k_derived->tb_uop_root,
                          &resolve_typebound_user_op);
@@ -9267,17 +10537,6 @@ resolve_typebound_procedures (gfc_symbol* derived)
       if (p && resolve_typebound_intrinsic_op (derived, (gfc_intrinsic_op) op,
                                               p) == FAILURE)
        resolve_bindings_result = FAILURE;
-      if (p)
-       found_op = true;
-    }
-
-  /* FIXME: Remove this (and found_op) once calls are fully implemented.  */
-  if (found_op)
-    {
-      gfc_error ("Derived type '%s' at %L contains type-bound OPERATOR's,"
-                " they are not yet implemented.",
-                derived->name, &derived->declared_at);
-      resolve_bindings_result = FAILURE;
     }
 
   return resolve_bindings_result;
@@ -9322,8 +10581,10 @@ ensure_not_abstract_walker (gfc_symbol* sub, gfc_symtree* st)
   if (st->n.tb && st->n.tb->deferred)
     {
       gfc_symtree* overriding;
-      overriding = gfc_find_typebound_proc (sub, NULL, st->name, true);
-      gcc_assert (overriding && overriding->n.tb);
+      overriding = gfc_find_typebound_proc (sub, NULL, st->name, true, NULL);
+      if (!overriding)
+       return FAILURE;
+      gcc_assert (overriding->n.tb);
       if (overriding->n.tb->deferred)
        {
          gfc_error ("Derived-type '%s' declared at %L must be ABSTRACT because"
@@ -9346,7 +10607,10 @@ ensure_not_abstract (gfc_symbol* sub, gfc_symbol* ancestor)
      This is not the most efficient way to do this, but it should be ok and is
      clearer than something sophisticated.  */
 
-  gcc_assert (ancestor && ancestor->attr.abstract && !sub->attr.abstract);
+  gcc_assert (ancestor && !sub->attr.abstract);
+  
+  if (!ancestor->attr.abstract)
+    return SUCCESS;
 
   /* Walk bindings of this ancestor.  */
   if (ancestor->f2k_derived)
@@ -9379,13 +10643,35 @@ resolve_fl_derived (gfc_symbol *sym)
   int i;
 
   super_type = gfc_get_derived_super_type (sym);
+  
+  if (sym->attr.is_class && sym->ts.u.derived == NULL)
+    {
+      /* Fix up incomplete CLASS symbols.  */
+      gfc_component *data = gfc_find_component (sym, "$data", true, true);
+      gfc_component *vptr = gfc_find_component (sym, "$vptr", true, true);
+      if (vptr->ts.u.derived == NULL)
+       {
+         gfc_symbol *vtab = gfc_find_derived_vtab (data->ts.u.derived, false);
+         gcc_assert (vtab);
+         vptr->ts.u.derived = vtab->ts.u.derived;
+       }
+    }
+
+  /* F2008, C432. */
+  if (super_type && sym->attr.coarray_comp && !super_type->attr.coarray_comp)
+    {
+      gfc_error ("As extending type '%s' at %L has a coarray component, "
+                "parent type '%s' shall also have one", sym->name,
+                &sym->declared_at, super_type->name);
+      return FAILURE;
+    }
 
   /* Ensure the extended type gets resolved before we do.  */
   if (super_type && resolve_fl_derived (super_type) == FAILURE)
     return FAILURE;
 
   /* An ABSTRACT type must be extensible.  */
-  if (sym->attr.abstract && !type_is_extensible (sym))
+  if (sym->attr.abstract && !gfc_type_is_extensible (sym))
     {
       gfc_error ("Non-extensible derived-type '%s' at %L must not be ABSTRACT",
                 sym->name, &sym->declared_at);
@@ -9394,9 +10680,38 @@ resolve_fl_derived (gfc_symbol *sym)
 
   for (c = sym->components; c != NULL; c = c->next)
     {
+      /* F2008, C442.  */
+      if (c->attr.codimension /* FIXME: c->as check due to PR 43412.  */
+         && (!c->attr.allocatable || (c->as && c->as->type != AS_DEFERRED)))
+       {
+         gfc_error ("Coarray component '%s' at %L must be allocatable with "
+                    "deferred shape", c->name, &c->loc);
+         return FAILURE;
+       }
+
+      /* F2008, C443.  */
+      if (c->attr.codimension && c->ts.type == BT_DERIVED
+         && c->ts.u.derived->ts.is_iso_c)
+       {
+         gfc_error ("Component '%s' at %L of TYPE(C_PTR) or TYPE(C_FUNPTR) "
+                    "shall not be a coarray", c->name, &c->loc);
+         return FAILURE;
+       }
+
+      /* F2008, C444.  */
+      if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.coarray_comp
+         && (c->attr.codimension || c->attr.pointer || c->attr.dimension
+             || c->attr.allocatable))
+       {
+         gfc_error ("Component '%s' at %L with coarray component "
+                    "shall be a nonpointer, nonallocatable scalar",
+                    c->name, &c->loc);
+         return FAILURE;
+       }
+
       if (c->attr.proc_pointer && c->ts.interface)
        {
-         if (c->ts.interface->attr.procedure)
+         if (c->ts.interface->attr.procedure && !sym->attr.vtype)
            gfc_error ("Interface '%s', used by procedure pointer component "
                       "'%s' at %L, is declared in a later PROCEDURE statement",
                       c->ts.interface->name, c->name, &c->loc);
@@ -9452,11 +10767,15 @@ resolve_fl_derived (gfc_symbol *sym)
              /* Copy char length.  */
              if (ifc->ts.type == BT_CHARACTER && ifc->ts.u.cl)
                {
-                 c->ts.u.cl = gfc_new_charlen (sym->ns, ifc->ts.u.cl);
-                 /* TODO: gfc_expr_replace_symbols (c->ts.u.cl->length, c);*/
+                 gfc_charlen *cl = gfc_new_charlen (sym->ns, ifc->ts.u.cl);
+                 gfc_expr_replace_comp (cl->length, c);
+                 if (cl->length && !cl->resolved
+                       && gfc_resolve_expr (cl->length) == FAILURE)
+                   return FAILURE;
+                 c->ts.u.cl = cl;
                }
            }
-         else if (c->ts.interface->name[0] != '\0')
+         else if (c->ts.interface->name[0] != '\0' && !sym->attr.vtype)
            {
              gfc_error ("Interface '%s' of procedure pointer component "
                         "'%s' at %L must be explicit", c->ts.interface->name,
@@ -9466,12 +10785,14 @@ resolve_fl_derived (gfc_symbol *sym)
        }
       else if (c->attr.proc_pointer && c->ts.type == BT_UNKNOWN)
        {
-         c->ts = *gfc_get_default_type (c->name, NULL);
-         c->attr.implicit_type = 1;
+         /* Since PPCs are not implicitly typed, a PPC without an explicit
+            interface must be a subroutine.  */
+         gfc_add_subroutine (&c->attr, c->name, &c->loc);
        }
 
       /* Procedure pointer components: Check PASS arg.  */
-      if (c->attr.proc_pointer && !c->tb->nopass && c->tb->pass_arg_num == 0)
+      if (c->attr.proc_pointer && !c->tb->nopass && c->tb->pass_arg_num == 0
+         && !sym->attr.vtype)
        {
          gfc_symbol* me_arg;
 
@@ -9521,8 +10842,10 @@ resolve_fl_derived (gfc_symbol *sym)
 
          /* Now check that the argument-type matches.  */
          gcc_assert (me_arg);
-         if (me_arg->ts.type != BT_DERIVED
-             || me_arg->ts.u.derived != sym)
+         if ((me_arg->ts.type != BT_DERIVED && me_arg->ts.type != BT_CLASS)
+             || (me_arg->ts.type == BT_DERIVED && me_arg->ts.u.derived != sym)
+             || (me_arg->ts.type == BT_CLASS
+                 && CLASS_DATA (me_arg)->ts.u.derived != sym))
            {
              gfc_error ("Argument '%s' of '%s' with PASS(%s) at %L must be of"
                         " the derived type '%s'", me_arg->name, c->name,
@@ -9559,9 +10882,9 @@ resolve_fl_derived (gfc_symbol *sym)
              return FAILURE;
            }
 
-         if (type_is_extensible (sym) && !me_arg->ts.is_class)
+         if (gfc_type_is_extensible (sym) && me_arg->ts.type != BT_CLASS)
            gfc_error ("Non-polymorphic passed-object dummy argument of '%s'"
-                        " at %L", c->name, &c->loc);
+                      " at %L", c->name, &c->loc);
 
        }
 
@@ -9570,10 +10893,16 @@ resolve_fl_derived (gfc_symbol *sym)
          && resolve_typespec_used (&c->ts, &c->loc, c->name) == FAILURE)
        return FAILURE;
 
+      /* If this type is an extension, set the accessibility of the parent
+        component.  */
+      if (super_type && c == sym->components
+         && strcmp (super_type->name, c->name) == 0)
+       c->attr.access = super_type->attr.access;
+      
       /* If this type is an extension, see if this component has the same name
         as an inherited type-bound procedure.  */
-      if (super_type
-         && gfc_find_typebound_proc (super_type, NULL, c->name, true))
+      if (super_type && !sym->attr.is_class
+         && gfc_find_typebound_proc (super_type, NULL, c->name, true, NULL))
        {
          gfc_error ("Component '%s' of '%s' at %L has the same name as an"
                     " inherited type-bound procedure",
@@ -9581,7 +10910,7 @@ resolve_fl_derived (gfc_symbol *sym)
          return FAILURE;
        }
 
-      if (c->ts.type == BT_CHARACTER)
+      if (c->ts.type == BT_CHARACTER && !c->attr.proc_pointer)
        {
         if (c->ts.u.cl->length == NULL
             || (resolve_charlen (c->ts.u.cl) == FAILURE)
@@ -9619,7 +10948,7 @@ resolve_fl_derived (gfc_symbol *sym)
            }
        }
 
-      if (c->ts.type == BT_DERIVED && c->attr.pointer
+      if (!sym->attr.is_class && c->ts.type == BT_DERIVED && c->attr.pointer
          && c->ts.u.derived->components == NULL
          && !c->ts.u.derived->attr.zero_comp)
        {
@@ -9629,9 +10958,19 @@ resolve_fl_derived (gfc_symbol *sym)
          return FAILURE;
        }
 
+      if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.pointer
+         && CLASS_DATA (c)->ts.u.derived->components == NULL
+         && !CLASS_DATA (c)->ts.u.derived->attr.zero_comp)
+       {
+         gfc_error ("The pointer component '%s' of '%s' at %L is a type "
+                    "that has not been declared", c->name, sym->name,
+                    &c->loc);
+         return FAILURE;
+       }
+
       /* C437.  */
-      if (c->ts.type == BT_DERIVED && c->ts.is_class
-         && !(c->attr.pointer || c->attr.allocatable))
+      if (c->ts.type == BT_CLASS
+         && !(CLASS_DATA (c)->attr.pointer || CLASS_DATA (c)->attr.allocatable))
        {
          gfc_error ("Component '%s' with CLASS at %L must be allocatable "
                     "or pointer", c->name, &c->loc);
@@ -9859,6 +11198,10 @@ resolve_symbol (gfc_symbol *sym)
   gfc_namespace *ns;
   gfc_component *c;
 
+  /* Avoid double resolution of function result symbols.  */
+  if ((sym->result || sym->attr.result) && (sym->ns != gfc_current_ns))
+    return;
+  
   if (sym->attr.flavor == FL_UNKNOWN)
     {
 
@@ -9956,6 +11299,9 @@ resolve_symbol (gfc_symbol *sym)
            {
              sym->ts.u.cl = gfc_new_charlen (sym->ns, ifc->ts.u.cl);
              gfc_expr_replace_symbols (sym->ts.u.cl->length, sym);
+             if (sym->ts.u.cl->length && !sym->ts.u.cl->resolved
+                   && gfc_resolve_expr (sym->ts.u.cl->length) == FAILURE)
+               return;
            }
        }
       else if (sym->ts.interface->name[0] != '\0')
@@ -9966,6 +11312,19 @@ resolve_symbol (gfc_symbol *sym)
        }
     }
 
+  if (sym->attr.is_protected && !sym->attr.proc_pointer
+      && (sym->attr.procedure || sym->attr.external))
+    {
+      if (sym->attr.external)
+       gfc_error ("PROTECTED attribute conflicts with EXTERNAL attribute "
+                  "at %L", &sym->declared_at);
+      else
+       gfc_error ("PROCEDURE attribute conflicts with PROTECTED attribute "
+                  "at %L", &sym->declared_at);
+
+      return;
+    }
+
   if (sym->attr.flavor == FL_DERIVED && resolve_fl_derived (sym) == FAILURE)
     return;
 
@@ -10022,7 +11381,7 @@ resolve_symbol (gfc_symbol *sym)
      arguments.  */
 
   if (sym->as != NULL
-      && (sym->as->type == AS_ASSUMED_SIZE
+      && ((sym->as->type == AS_ASSUMED_SIZE && !sym->as->cp_was_assumed)
          || sym->as->type == AS_ASSUMED_SHAPE)
       && sym->attr.dummy == 0)
     {
@@ -10214,6 +11573,62 @@ resolve_symbol (gfc_symbol *sym)
        }
     }
 
+  /* F2008, C526.  */
+  if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
+       || sym->attr.codimension)
+      && sym->attr.result)
+    gfc_error ("Function result '%s' at %L shall not be a coarray or have "
+              "a coarray component", sym->name, &sym->declared_at);
+
+  /* F2008, C524.  */
+  if (sym->attr.codimension && sym->ts.type == BT_DERIVED
+      && sym->ts.u.derived->ts.is_iso_c)
+    gfc_error ("Variable '%s' at %L of TYPE(C_PTR) or TYPE(C_FUNPTR) "
+              "shall not be a coarray", sym->name, &sym->declared_at);
+
+  /* F2008, C525.  */
+  if (sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp
+      && (sym->attr.codimension || sym->attr.pointer || sym->attr.dimension
+         || sym->attr.allocatable))
+    gfc_error ("Variable '%s' at %L with coarray component "
+              "shall be a nonpointer, nonallocatable scalar",
+              sym->name, &sym->declared_at);
+
+  /* F2008, C526.  The function-result case was handled above.  */
+  if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
+       || sym->attr.codimension)
+      && !(sym->attr.allocatable || sym->attr.dummy || sym->attr.save
+          || sym->ns->proc_name->attr.flavor == FL_MODULE
+          || sym->ns->proc_name->attr.is_main_program
+          || sym->attr.function || sym->attr.result || sym->attr.use_assoc))
+    gfc_error ("Variable '%s' at %L is a coarray or has a coarray "
+              "component and is not ALLOCATABLE, SAVE nor a "
+              "dummy argument", sym->name, &sym->declared_at);
+  /* F2008, C528.  */  /* FIXME: sym->as check due to PR 43412.  */
+  else if (sym->attr.codimension && !sym->attr.allocatable
+      && sym->as && sym->as->cotype == AS_DEFERRED)
+    gfc_error ("Coarray variable '%s' at %L shall not have codimensions with "
+               "deferred shape", sym->name, &sym->declared_at);
+  else if (sym->attr.codimension && sym->attr.allocatable
+      && (sym->as->type != AS_DEFERRED || sym->as->cotype != AS_DEFERRED))
+    gfc_error ("Allocatable coarray variable '%s' at %L must have "
+              "deferred shape", sym->name, &sym->declared_at);
+
+
+  /* F2008, C541.  */
+  if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
+       || (sym->attr.codimension && sym->attr.allocatable))
+      && sym->attr.dummy && sym->attr.intent == INTENT_OUT)
+    gfc_error ("Variable '%s' at %L is INTENT(OUT) and can thus not be an "
+              "allocatable coarray or have coarray components",
+              sym->name, &sym->declared_at);
+
+  if (sym->attr.codimension && sym->attr.dummy
+      && sym->ns->proc_name && sym->ns->proc_name->attr.is_bind_c)
+    gfc_error ("Coarray dummy variable '%s' at %L not allowed in BIND(C) "
+              "procedure '%s'", sym->name, &sym->declared_at,
+              sym->ns->proc_name->name);
+
   switch (sym->attr.flavor)
     {
     case FL_VARIABLE:
@@ -10257,7 +11672,7 @@ resolve_symbol (gfc_symbol *sym)
 
   /* Resolve formal namespaces.  */
   if (sym->formal_ns && sym->formal_ns != gfc_current_ns
-      && !sym->attr.contained)
+      && !sym->attr.contained && !sym->attr.intrinsic)
     gfc_resolve (sym->formal_ns);
 
   /* Make sure the formal namespace is present.  */
@@ -10327,9 +11742,6 @@ next_data_value (void)
 {
   while (mpz_cmp_ui (values.left, 0) == 0)
     {
-      if (!gfc_is_constant_expr (values.vnode->expr))
-       gfc_error ("non-constant DATA value at %L",
-                  &values.vnode->expr->where);
 
       if (values.vnode->next == NULL)
        return FAILURE;
@@ -10389,6 +11801,13 @@ check_data_variable (gfc_data_variable *var, locus *where)
       if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer)
        has_pointer = 1;
 
+      if (ref->type == REF_ARRAY && ref->u.ar.codimen)
+       {
+         gfc_error ("DATA element '%s' at %L cannot have a coindex",
+                    sym->name, where);
+         return FAILURE;
+       }
+
       if (has_pointer
            && ref->type == REF_ARRAY
            && ref->u.ar.type != AR_FULL)
@@ -10485,11 +11904,14 @@ check_data_variable (gfc_data_variable *var, locus *where)
              mpz_set_ui (size, 0);
            }
 
-         gfc_assign_data_value_range (var->expr, values.vnode->expr,
-                                      offset, range);
+         t = gfc_assign_data_value_range (var->expr, values.vnode->expr,
+                                          offset, range);
 
          mpz_add (offset, offset, range);
          mpz_clear (range);
+
+         if (t == FAILURE)
+           break;
        }
 
       /* Assign initial value to symbol.  */
@@ -10538,6 +11960,7 @@ traverse_data_list (gfc_data_variable *var, locus *where)
   gfc_try retval = SUCCESS;
 
   mpz_init (frame.value);
+  mpz_init (trip);
 
   start = gfc_copy_expr (var->iter.start);
   end = gfc_copy_expr (var->iter.end);
@@ -10546,26 +11969,29 @@ traverse_data_list (gfc_data_variable *var, locus *where)
   if (gfc_simplify_expr (start, 1) == FAILURE
       || start->expr_type != EXPR_CONSTANT)
     {
-      gfc_error ("iterator start at %L does not simplify", &start->where);
+      gfc_error ("start of implied-do loop at %L could not be "
+                "simplified to a constant value", &start->where);
       retval = FAILURE;
       goto cleanup;
     }
   if (gfc_simplify_expr (end, 1) == FAILURE
       || end->expr_type != EXPR_CONSTANT)
     {
-      gfc_error ("iterator end at %L does not simplify", &end->where);
+      gfc_error ("end of implied-do loop at %L could not be "
+                "simplified to a constant value", &start->where);
       retval = FAILURE;
       goto cleanup;
     }
   if (gfc_simplify_expr (step, 1) == FAILURE
       || step->expr_type != EXPR_CONSTANT)
     {
-      gfc_error ("iterator step at %L does not simplify", &step->where);
+      gfc_error ("step of implied-do loop at %L could not be "
+                "simplified to a constant value", &start->where);
       retval = FAILURE;
       goto cleanup;
     }
 
-  mpz_init_set (trip, end->value.integer);
+  mpz_set (trip, end->value.integer);
   mpz_sub (trip, trip, start->value.integer);
   mpz_add (trip, trip, step->value.integer);
 
@@ -10581,7 +12007,6 @@ traverse_data_list (gfc_data_variable *var, locus *where)
     {
       if (traverse_data_var (var->list, where) == FAILURE)
        {
-         mpz_clear (trip);
          retval = FAILURE;
          goto cleanup;
        }
@@ -10590,7 +12015,6 @@ traverse_data_list (gfc_data_variable *var, locus *where)
       if (gfc_simplify_expr (e, 1) == FAILURE)
        {
          gfc_free_expr (e);
-         mpz_clear (trip);
          retval = FAILURE;
          goto cleanup;
        }
@@ -10600,9 +12024,9 @@ traverse_data_list (gfc_data_variable *var, locus *where)
       mpz_sub_ui (trip, trip, 1);
     }
 
-  mpz_clear (trip);
 cleanup:
   mpz_clear (frame.value);
+  mpz_clear (trip);
 
   gfc_free_expr (start);
   gfc_free_expr (end);
@@ -10704,12 +12128,19 @@ int
 gfc_impure_variable (gfc_symbol *sym)
 {
   gfc_symbol *proc;
+  gfc_namespace *ns;
 
   if (sym->attr.use_assoc || sym->attr.in_common)
     return 1;
 
-  if (sym->ns != gfc_current_ns)
-    return !sym->attr.function;
+  /* Check if the symbol's ns is inside the pure procedure.  */
+  for (ns = gfc_current_ns; ns; ns = ns->parent)
+    {
+      if (ns == sym->ns)
+       break;
+      if (ns->proc_name->attr.flavor == FL_PROCEDURE && !sym->attr.function)
+       return 1;
+    }
 
   proc = sym->ns->proc_name;
   if (sym->attr.dummy && gfc_pure (proc)
@@ -10725,18 +12156,30 @@ gfc_impure_variable (gfc_symbol *sym)
 }
 
 
-/* Test whether a symbol is pure or not.  For a NULL pointer, checks the
-   symbol of the current procedure.  */
+/* Test whether a symbol is pure or not.  For a NULL pointer, checks if the
+   current namespace is inside a pure procedure.  */
 
 int
 gfc_pure (gfc_symbol *sym)
 {
   symbol_attribute attr;
+  gfc_namespace *ns;
 
   if (sym == NULL)
-    sym = gfc_current_ns->proc_name;
-  if (sym == NULL)
-    return 0;
+    {
+      /* Check if the current namespace or one of its parents
+       belongs to a pure procedure.  */
+      for (ns = gfc_current_ns; ns; ns = ns->parent)
+       {
+         sym = ns->proc_name;
+         if (sym == NULL)
+           return 0;
+         attr = sym->attr;
+         if (attr.flavor == FL_PROCEDURE && (attr.pure || attr.elemental))
+           return 1;
+       }
+      return 0;
+    }
 
   attr = sym->attr;
 
@@ -10881,7 +12324,7 @@ resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e)
       return FAILURE;
     }
 
-  if (sym->attr.in_common && has_default_initializer (sym->ts.u.derived))
+  if (sym->attr.in_common && gfc_has_default_initializer (sym->ts.u.derived))
     {
       gfc_error ("Derived type variable '%s' at %L with default "
                 "initialization cannot be in EQUIVALENCE with a variable "
@@ -10933,10 +12376,8 @@ resolve_equivalence (gfc_equiv *eq)
   seq_type eq_type, last_eq_type;
   gfc_typespec *last_ts;
   int object, cnt_protected;
-  const char *value_name;
   const char *msg;
 
-  value_name = NULL;
   last_ts = &eq->expr->symtree->n.sym->ts;
 
   first_sym = eq->expr->symtree->n.sym;
@@ -10987,7 +12428,8 @@ resolve_equivalence (gfc_equiv *eq)
                {
                  ref->type = REF_SUBSTRING;
                  if (start == NULL)
-                   start = gfc_int_expr (1);
+                   start = gfc_get_int_expr (gfc_default_integer_kind,
+                                             NULL, 1);
                  ref->u.ss.start = start;
                  if (end == NULL && e->ts.u.cl)
                    end = gfc_copy_expr (e->ts.u.cl->length);
@@ -11395,7 +12837,11 @@ resolve_codes (gfc_namespace *ns)
     resolve_codes (n);
 
   gfc_current_ns = ns;
-  cs_base = NULL;
+
+  /* Don't clear 'cs_base' if this is the namespace of a BLOCK construct.  */
+  if (!(ns->proc_name && ns->proc_name->attr.flavor == FL_LABEL))
+    cs_base = NULL;
+
   /* Set to an out of range value.  */
   current_entry_id = -1;