OSDN Git Service

2010-03-17 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index 445753e..de316da 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
 
@@ -367,15 +367,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);
+       }
     }
 }
 
@@ -765,7 +776,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);
@@ -831,13 +842,20 @@ 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;
     }
 
+  /* 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; comp = comp->next, cons = cons->next)
     {
       int rank;
@@ -903,6 +921,16 @@ 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))
+       {
+         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;
@@ -926,7 +954,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)
     return 1;
 
   return 0;
@@ -1106,6 +1135,9 @@ is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context)
   gfc_symbol* context_proc;
   gfc_namespace* real_context;
 
+  if (sym->attr.flavor == FL_PROGRAM)
+    return false;
+
   gcc_assert (sym->attr.flavor == FL_PROCEDURE);
 
   /* If we've got an ENTRY, find real procedure.  */
@@ -1307,6 +1339,8 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
                e->rank = comp->as->rank;
              e->expr_type = EXPR_FUNCTION;
            }
+         if (gfc_resolve_expr (e) == FAILURE)                          
+           return FAILURE; 
          goto argument_list;
        }
 
@@ -1384,10 +1418,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.  */
@@ -1817,6 +1848,21 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
        gfc_error ("The reference to function '%s' at %L either needs an "
                   "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);
+           }
+       }
 
       if (gfc_option.flag_whole_file == 1
            || ((gfc_option.warn_std & GFC_STD_LEGACY)
@@ -2505,6 +2551,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;
@@ -2515,7 +2565,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);
@@ -3127,6 +3179,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))
@@ -3292,7 +3353,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;
        }
 
@@ -3379,7 +3440,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;
@@ -3907,6 +3968,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;
 
@@ -3955,6 +4017,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)
@@ -4250,7 +4315,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 "
@@ -4724,6 +4791,7 @@ extract_compcall_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;
     }
 
   if (gfc_resolve_expr (po) == FAILURE)
@@ -4751,12 +4819,6 @@ 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 || e->value.compcall.ignore_pass)
     {
       gfc_free_expr (po);
@@ -4784,11 +4846,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;
 
@@ -4851,13 +4914,30 @@ check_typebound_baseobject (gfc_expr* e)
     return FAILURE;
 
   gcc_assert (base->ts.type == BT_DERIVED || base->ts.type == BT_CLASS);
-  if (base->ts.u.derived->attr.abstract)
+
+  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;
 }
 
@@ -4996,28 +5076,42 @@ resolve_typebound_call (gfc_code* c)
   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.  */
-
+/* Resolve a component-call expression.  This originally was intended
+   only to see functions.  However, it is convenient to use it in 
+   resolving subroutine class methods, since we do not have to add a
+   gfc_code each time. */
 static gfc_try
-resolve_compcall (gfc_expr* e)
+resolve_compcall (gfc_expr* e, bool fcn, bool class_members)
 {
   gfc_actual_arglist* newactual;
   gfc_symtree* target;
 
   /* Check that's really a FUNCTION.  */
-  if (!e->value.compcall.tbp->function)
+  if (fcn && !e->value.compcall.tbp->function)
     {
       gfc_error ("'%s' at %L should be a FUNCTION",
                 e->value.compcall.name, &e->where);
       return FAILURE;
     }
+  else if (!fcn && !e->value.compcall.tbp->subroutine)
+    {
+      /* To resolve class member calls, we borrow this bit
+         of code to select the specific procedures.  */
+      gfc_error ("'%s' at %L should be a SUBROUTINE",
+                e->value.compcall.name, &e->where);
+      return FAILURE;
+    }
 
   /* These must not be assign-calls!  */
   gcc_assert (!e->value.compcall.assign);
@@ -5040,14 +5134,338 @@ 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.class_esym = NULL;
   e->value.function.isym = NULL;
   e->symtree = target;
   e->ts = target->n.sym->ts;
   e->expr_type = EXPR_FUNCTION;
 
-  return gfc_resolve_expr (e);
+  /* Resolution is not necessary when constructing component calls
+     for class members, since this must only be done for the
+     declared type, which is done afterwards.  */
+  return !class_members ? gfc_resolve_expr (e) : SUCCESS;
+}
+
+
+/* Resolve a typebound call for the members in a class.  This group of
+   functions implements dynamic dispatch in the provisional version
+   of f03 OOP.  As soon as vtables are in place and contain pointers
+   to methods, this will no longer be necessary.  */
+static gfc_expr *list_e;
+static void check_class_members (gfc_symbol *);
+static gfc_try class_try;
+static bool fcn_flag;
+
+
+static void
+check_members (gfc_symbol *derived)
+{
+  if (derived->attr.flavor == FL_DERIVED)
+    check_class_members (derived);
+}
+
+
+static void 
+check_class_members (gfc_symbol *derived)
+{
+  gfc_expr *e;
+  gfc_symtree *tbp;
+  gfc_class_esym_list *etmp;
+
+  e = gfc_copy_expr (list_e);
+
+  tbp = gfc_find_typebound_proc (derived, &class_try,
+                                e->value.compcall.name,
+                                false, &e->where);
+
+  if (tbp == NULL)
+    {
+      gfc_error ("no typebound available procedure named '%s' at %L",
+                e->value.compcall.name, &e->where);
+      return;
+    }
+
+  /* If we have to match a passed class member, force the actual
+      expression to have the correct type.  */
+  if (!tbp->n.tb->nopass)
+    {
+      if (e->value.compcall.base_object == NULL)
+       e->value.compcall.base_object = extract_compcall_passed_object (e);
+
+      if (!derived->attr.abstract)
+       {
+         e->value.compcall.base_object->ts.type = BT_DERIVED;
+         e->value.compcall.base_object->ts.u.derived = derived;
+       }
+    }
+
+  e->value.compcall.tbp = tbp->n.tb;
+  e->value.compcall.name = tbp->name;
+
+  /* Let the original expresssion catch the assertion in
+     resolve_compcall, since this flag does not appear to be reset or
+     copied in some systems.  */
+  e->value.compcall.assign = 0;
+
+  /* Do the renaming, PASSing, generic => specific and other
+     good things for each class member.  */
+  class_try = (resolve_compcall (e, fcn_flag, true) == SUCCESS)
+                               ? class_try : FAILURE;
+
+  /* Now transfer the found symbol to the esym list.  */
+  if (class_try == SUCCESS)
+    {
+      etmp = list_e->value.function.class_esym;
+      list_e->value.function.class_esym
+               = gfc_get_class_esym_list();
+      list_e->value.function.class_esym->next = etmp;
+      list_e->value.function.class_esym->derived = derived;
+      list_e->value.function.class_esym->esym
+               = e->value.function.esym;
+    }
+
+  gfc_free_expr (e);
+  
+  /* Burrow down into grandchildren types.  */
+  if (derived->f2k_derived)
+    gfc_traverse_ns (derived->f2k_derived, check_members);
+}
+
+
+/* Eliminate esym_lists where all the members point to the
+   typebound procedure of the declared type; ie. one where
+   type selection has no effect..  */
+static void
+resolve_class_esym (gfc_expr *e)
+{
+  gfc_class_esym_list *p, *q;
+  bool empty = true;
+
+  gcc_assert (e && e->expr_type == EXPR_FUNCTION);
+
+  p = e->value.function.class_esym;
+  if (p == NULL)
+    return;
+
+  for (; p; p = p->next)
+    empty = empty && (e->value.function.esym == p->esym);
+
+  if (empty)
+    {
+      p = e->value.function.class_esym;
+      for (; p; p = q)
+       {
+         q = p->next;
+         gfc_free (p);
+       }
+      e->value.function.class_esym = NULL;
+   }
+}
+
+
+/* Generate an expression for the hash value, given the reference to
+   the class of the final expression (class_ref), the base of the
+   full reference list (new_ref), the declared type and the class
+   object (st).  */
+static gfc_expr*
+hash_value_expr (gfc_ref *class_ref, gfc_ref *new_ref, gfc_symtree *st)
+{
+  gfc_expr *hash_value;
+
+  /* Build an expression for the correct hash_value; ie. that of the last
+     CLASS reference.  */
+  if (class_ref)
+    {
+      class_ref->next = NULL;
+    }
+  else
+    {
+      gfc_free_ref_list (new_ref);
+      new_ref = NULL;
+    }
+  hash_value = gfc_get_expr ();
+  hash_value->expr_type = EXPR_VARIABLE;
+  hash_value->symtree = st;
+  hash_value->symtree->n.sym->refs++;
+  hash_value->ref = new_ref;
+  gfc_add_component_ref (hash_value, "$vptr");
+  gfc_add_component_ref (hash_value, "$hash");
+
+  return hash_value;
+}
+
+
+/* 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;
+  *class_ref = NULL;
+  *new_ref = gfc_copy_ref (e->ref);
+  for (ref = *new_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;
+         *class_ref = ref;
+       }
+    }
+
+  if (declared == NULL)
+    declared = e->symtree->n.sym->ts.u.derived;
+
+  return declared;
+}
+
+
+/* Resolve the argument expressions so that any arguments expressions
+   that include class methods are resolved before the current call.
+   This is necessary because of the static variables used in CLASS
+   method resolution.  */
+static void
+resolve_arg_exprs (gfc_actual_arglist *arg)
+{ 
+  /* Resolve the actual arglist expressions.  */
+  for (; arg; arg = arg->next)
+    {
+      if (arg->expr)
+       gfc_resolve_expr (arg->expr);
+    }
+}
+
+
+/* Resolve a typebound function, or 'method'.  First separate all
+   the non-CLASS references by calling resolve_compcall directly.
+   Then treat the CLASS references by resolving for each of the class
+   members in turn.  */
+
+static gfc_try
+resolve_typebound_function (gfc_expr* e)
+{
+  gfc_symbol *derived, *declared;
+  gfc_ref *new_ref;
+  gfc_ref *class_ref;
+  gfc_symtree *st;
+
+  st = e->symtree;
+  if (st == NULL)
+    return resolve_compcall (e, true, false);
+
+  /* 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, true, false);
+    }
+
+  /* Resolve the argument expressions,  */
+  resolve_arg_exprs (e->value.function.actual); 
+
+  /* Get the data component, which is of the declared type.  */
+  derived = declared->components->ts.u.derived;
+
+  /* Resolve the function call for each member of the class.  */
+  class_try = SUCCESS;
+  fcn_flag = true;
+  list_e = gfc_copy_expr (e);
+  check_class_members (derived);
+
+  class_try = (resolve_compcall (e, true, false) == SUCCESS)
+                ? class_try : FAILURE;
+
+  /* Transfer the class list to the original expression.  Note that
+     the class_esym list is cleaned up in trans-expr.c, as the calls
+     are translated.  */
+  e->value.function.class_esym = list_e->value.function.class_esym;
+  list_e->value.function.class_esym = NULL;
+  gfc_free_expr (list_e);
+
+  resolve_class_esym (e);
+
+  /* More than one typebound procedure so transmit an expression for
+     the hash_value as the selector.  */
+  if (e->value.function.class_esym != NULL)
+    e->value.function.class_esym->hash_value
+               = hash_value_expr (class_ref, new_ref, st);
+
+  return class_try;
+}
+
+/* Resolve a typebound subroutine, or 'method'.  First separate all
+   the non-CLASS references by calling resolve_typebound_call directly.
+   Then treat the CLASS references by resolving for each of the class
+   members in turn.  */
+
+static gfc_try
+resolve_typebound_subroutine (gfc_code *code)
+{
+  gfc_symbol *derived, *declared;
+  gfc_ref *new_ref;
+  gfc_ref *class_ref;
+  gfc_symtree *st;
+
+  st = code->expr1->symtree;
+  if (st == NULL)
+    return resolve_typebound_call (code);
+
+  /* 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);
+    } 
+
+  /* Resolve the argument expressions,  */
+  resolve_arg_exprs (code->expr1->value.compcall.actual); 
+
+  /* Get the data component, which is of the declared type.  */
+  derived = declared->components->ts.u.derived;
+
+  class_try = SUCCESS;
+  fcn_flag = false;
+  list_e = gfc_copy_expr (code->expr1);
+  check_class_members (derived);
+
+  class_try = (resolve_typebound_call (code) == SUCCESS)
+                ? class_try : FAILURE;
+
+  /* Transfer the class list to the original expression.  Note that
+     the class_esym list is cleaned up in trans-expr.c, as the calls
+     are translated.  */
+  code->expr1->value.function.class_esym
+                       = list_e->value.function.class_esym;
+  list_e->value.function.class_esym = NULL;
+  gfc_free_expr (list_e);
+
+  resolve_class_esym (code->expr1);
+
+  /* More than one typebound procedure so transmit an expression for
+     the hash_value as the selector.  */
+  if (code->expr1->value.function.class_esym != NULL)
+    code->expr1->value.function.class_esym->hash_value
+               = hash_value_expr (class_ref, new_ref, st);
+
+  return class_try;
 }
 
 
@@ -5124,6 +5542,32 @@ 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.  */
+      for (con = e->value.constructor; con; con = con->next)
+       {
+         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.  */
@@ -5161,7 +5605,7 @@ gfc_resolve_expr (gfc_expr *e)
       break;
 
     case EXPR_COMPCALL:
-      t = resolve_compcall (e);
+      t = resolve_typebound_function (e);
       break;
 
     case EXPR_SUBSTRING:
@@ -5187,14 +5631,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;
 
@@ -5604,6 +6054,58 @@ gfc_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.  */
@@ -5611,14 +6113,14 @@ gfc_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;
   symbol_attribute attr;
   gfc_ref *ref, *ref2;
   gfc_array_ref *ar;
-  gfc_code *init_st;
   gfc_symbol *sym;
   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;
@@ -5633,6 +6135,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
   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)
     {
       allocatable = 0;
@@ -5647,6 +6152,7 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
          allocatable = sym->ts.u.derived->components->attr.allocatable;
          pointer = sym->ts.u.derived->components->attr.pointer;
          dimension = sym->ts.u.derived->components->attr.dimension;
+         is_abstract = sym->ts.u.derived->components->attr.abstract;
        }
       else
        {
@@ -5674,12 +6180,14 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
                    allocatable = c->ts.u.derived->components->attr.allocatable;
                    pointer = c->ts.u.derived->components->attr.pointer;
                    dimension = c->ts.u.derived->components->attr.dimension;
+                   is_abstract = c->ts.u.derived->components->attr.abstract;
                  }
                else
                  {
                    allocatable = c->attr.allocatable;
                    pointer = c->attr.pointer;
                    dimension = c->attr.dimension;
+                   is_abstract = c->attr.abstract;
                  }
                break;
 
@@ -5698,46 +6206,74 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
       return FAILURE;
     }
 
+  /* Some checks for the SOURCE tag.  */
+  if (code->expr3)
+    {
+      /* 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);
+         return FAILURE;
+       }
+
+      /* Check F03:C632 and restriction following Note 6.18.  */
+      if (code->expr3->rank > 0
+         && conformable_arrays (code->expr3, e) == FAILURE)
+       return 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);
+         return 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);
+      return FAILURE;
+    }
+
   if (check_intent_in && sym->attr.intent == INTENT_IN)
     {
       gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L",
                 sym->name, &e->where);
       return FAILURE;
     }
-
-  if (e->ts.type == BT_CLASS)
+    
+  if (!code->expr3)
     {
-      /* Initialize VINDEX for CLASS objects.  */
-      init_st = gfc_get_code ();
-      init_st->loc = code->loc;
-      init_st->expr1 = gfc_expr_to_initialize (e);
-      init_st->op = EXEC_ASSIGN;
-      gfc_add_component_ref (init_st->expr1, "$vindex");
-      if (code->expr3 && code->expr3->ts.type == BT_CLASS)
+      /* Add default initializer for those derived types that need them.  */
+      if (e->ts.type == BT_DERIVED
+         && (init_e = gfc_default_initializer (&e->ts)))
        {
-         /* vindex must be determined at run time.  */
-         init_st->expr2 = gfc_copy_expr (code->expr3);
-         gfc_add_component_ref (init_st->expr2, "$vindex");
+         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
+      else if (e->ts.type == BT_CLASS
+              && ((code->ext.alloc.ts.type == BT_UNKNOWN
+                   && (init_e = gfc_default_initializer (&e->ts.u.derived->components->ts)))
+                  || (code->ext.alloc.ts.type == BT_DERIVED
+                      && (init_e = gfc_default_initializer (&code->ext.alloc.ts)))))
        {
-         /* vindex is fixed at compile time.  */
-         int vindex;
-         if (code->expr3)
-           vindex = code->expr3->ts.u.derived->vindex;
-         else if (code->ext.alloc.ts.type == BT_DERIVED)
-           vindex = code->ext.alloc.ts.u.derived->vindex;
-         else if (e->ts.type == BT_CLASS)
-           vindex = e->ts.u.derived->components->ts.u.derived->vindex;
-         else
-           vindex = e->ts.u.derived->vindex;
-         init_st->expr2 = gfc_int_expr (vindex);
+         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;
        }
-      init_st->expr2->where = init_st->expr1->where = init_st->loc;
-      init_st->next = code->next;
-      code->next = init_st;
-      /* Only allocate the DATA component.  */
-      gfc_add_component_ref (e, "$data");
     }
 
   if (pointer || dimension == 0)
@@ -5789,7 +6325,7 @@ check_symbols:
          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
@@ -6439,15 +6975,21 @@ static void
 resolve_select_type (gfc_code *code)
 {
   gfc_symbol *selector_type;
-  gfc_code *body, *new_st;
-  gfc_case *c, *default_case;
+  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;
 
-  selector_type = code->expr1->ts.u.derived->components->ts.u.derived;
+  ns = code->ext.ns;
+  gfc_resolve (ns);
 
-  /* Assume there is no DEFAULT case.  */
-  default_case = NULL;
+  if (code->expr2)
+    selector_type = code->expr2->ts.u.derived->components->ts.u.derived;
+  else
+    selector_type = code->expr1->ts.u.derived->components->ts.u.derived;
 
   /* Loop over TYPE IS / CLASS IS cases.  */
   for (body = code->block; body; body = body->block)
@@ -6460,6 +7002,7 @@ resolve_select_type (gfc_code *code)
        {
          gfc_error ("Derived type '%s' at %L must be extensible",
                     c->ts.u.derived->name, &c->where);
+         error++;
          continue;
        }
 
@@ -6469,6 +7012,7 @@ resolve_select_type (gfc_code *code)
        {
          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;
        }
 
@@ -6476,57 +7020,197 @@ resolve_select_type (gfc_code *code)
       if (c->ts.type == BT_UNKNOWN)
        {
          /* Check F03:C818.  */
-         if (default_case != NULL)
-           gfc_error ("The DEFAULT CASE at %L cannot be followed "
-                      "by a second DEFAULT CASE at %L",
-                      &default_case->where, &c->where);
+         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 = c;
-         continue;
+           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, "$vindex");
+  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_int_expr (c->ts.u.derived->vindex);
-      else if (c->ts.type == BT_CLASS)
-       /* Currently IS CLASS blocks are simply ignored.
-          TODO: Implement IS CLASS.  */
-       c->unreachable = 1;
-
-      if (c->ts.type != BT_DERIVED)
+       c->low = c->high = gfc_int_expr (c->ts.u.derived->hash_value);
+      else if (c->ts.type == BT_UNKNOWN)
        continue;
+      
       /* Assign temporary to selector.  */
-      sprintf (name, "tmp$%s", c->ts.u.derived->name);
-      st = gfc_find_symtree (code->expr1->symtree->n.sym->ns->sym_root, name);
+      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->op = EXEC_POINTER_ASSIGN;
       new_st->expr1 = gfc_get_variable_expr (st);
       new_st->expr2 = gfc_get_variable_expr (code->expr1->symtree);
-      gfc_add_component_ref (new_st->expr2, "$data");
+      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;
+    }
 
-  /* Eliminate dead blocks.  */
-  for (body = code; body && body->block; body = body->block)
+  if (class_is)
     {
-      if (body->block->ext.case_list->unreachable)
+      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)
        {
-         /* Cut the unreachable block from the code chain.  */
-         gfc_code *cd = body->block;
-         body->block = cd->block;
-         /* Kill the dead block, but not the blocks below it.  */
-         cd->block = NULL;
-         gfc_free_statements (cd);
+         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);
+         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);
@@ -7149,14 +7833,12 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
 
   if (gfc_extend_assign (code, ns) == SUCCESS)
     {
-      gfc_symbol* assign_proc;
       gfc_expr** rhsptr;
 
       if (code->op == EXEC_ASSIGN_CALL)
        {
          lhs = code->ext.actual->expr;
          rhsptr = &code->ext.actual->next->expr;
-         assign_proc = code->symtree->n.sym;
        }
       else
        {
@@ -7171,7 +7853,6 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
 
          tbp = code->expr1->value.compcall.tbp;
          gcc_assert (!tbp->is_generic);
-         assign_proc = tbp->u.specific->n.sym;
        }
 
       /* Make a temporary rhs when there is a default initializer
@@ -7276,6 +7957,7 @@ 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
+           && rhs->expr_type == EXPR_VARIABLE
            && gfc_impure_variable (rhs->symtree->n.sym))
        {
          gfc_error ("The impure variable at %L is assigned to "
@@ -7286,45 +7968,19 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
        }
     }
 
+  /* F03:7.4.1.2.  */
+  if (lhs->ts.type == BT_CLASS)
+    {
+      gfc_error ("Variable must not be polymorphic in assignment at %L",
+                &lhs->where);
+      return false;
+    }
+
   gfc_check_assign (lhs, rhs, 1);
   return false;
 }
 
 
-/* Check an assignment to a CLASS object (pointer or ordinary assignment).  */
-
-static void
-resolve_class_assign (gfc_code *code)
-{
-  gfc_code *assign_code = gfc_get_code ();
-
-  /* Insert an additional assignment which sets the vindex.  */
-  assign_code->next = code->next;
-  code->next = assign_code;
-  assign_code->op = EXEC_ASSIGN;
-  assign_code->expr1 = gfc_copy_expr (code->expr1);
-  gfc_add_component_ref (assign_code->expr1, "$vindex");
-  if (code->expr2->ts.type == BT_DERIVED)
-    /* vindex is constant, determined at compile time.  */
-    assign_code->expr2 = gfc_int_expr (code->expr2->ts.u.derived->vindex);
-  else if (code->expr2->ts.type == BT_CLASS)
-    {
-      /* vindex must be determined at run time.  */
-      assign_code->expr2 = gfc_copy_expr (code->expr2);
-      gfc_add_component_ref (assign_code->expr2, "$vindex");
-    }
-  else if (code->expr2->expr_type == EXPR_NULL)
-    assign_code->expr2 = gfc_int_expr (0);
-  else
-    gcc_unreachable ();
-
-  /* Modify the actual pointer assignment.  */
-  gfc_add_component_ref (code->expr1, "$data");
-  if (code->expr2->ts.type == BT_CLASS)
-    gfc_add_component_ref (code->expr2, "$data");
-}
-
-
 /* Given a block of code, recursively resolve everything pointed to by this
    code block.  */
 
@@ -7374,6 +8030,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;
@@ -7395,6 +8056,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:
@@ -7447,9 +8112,6 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          if (t == FAILURE)
            break;
 
-         if (code->expr1->ts.type == BT_CLASS)
-           resolve_class_assign (code);
-
          if (resolve_ordinary_assign (code, ns))
            {
              if (code->op == EXEC_COMPCALL)
@@ -7457,7 +8119,6 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
              else
                goto call;
            }
-
          break;
 
        case EXEC_LABEL_ASSIGN:
@@ -7478,11 +8139,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          if (t == FAILURE)
            break;
 
-         if (code->expr1->ts.type == BT_CLASS)
-           resolve_class_assign (code);
-
          gfc_check_pointer_assign (code->expr1, code->expr2);
-
          break;
 
        case EXEC_ARITHMETIC_IF:
@@ -7512,7 +8169,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
 
        case EXEC_COMPCALL:
        compcall:
-         resolve_typebound_call (code);
+         resolve_typebound_subroutine (code);
          break;
 
        case EXEC_CALL_PPC:
@@ -7925,8 +8582,10 @@ 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);
+      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_int_expr (0));
     }
 
@@ -8113,12 +8772,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:
@@ -8140,12 +8794,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:
@@ -8214,7 +8863,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);
@@ -8309,13 +8959,12 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
       && 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;
-    }
+      && 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;
 
   if (sym->ts.type == BT_CLASS)
     {
@@ -8323,14 +8972,14 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
       if (!gfc_type_is_extensible (sym->ts.u.derived->components->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);
+                    sym->ts.u.derived->components->ts.u.derived->name,
+                    sym->name, &sym->declared_at);
          return FAILURE;
        }
 
       /* C509.  */
-      if (!(sym->attr.dummy || sym->attr.allocatable || sym->attr.pointer
-             || sym->ts.u.derived->components->attr.allocatable
-             || sym->ts.u.derived->components->attr.pointer))
+      /* 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);
@@ -8485,10 +9134,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;
@@ -8501,23 +9146,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;
        }
     }
 
@@ -9053,8 +9687,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;
        }
@@ -9131,7 +9765,7 @@ check_generic_tbp_ambiguity (gfc_tbp_generic* t1, gfc_tbp_generic* t2,
     }
 
   /* Compare the interfaces.  */
-  if (gfc_compare_interfaces (sym1, sym2, NULL, 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);
@@ -9511,8 +10145,11 @@ 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_CLASS)
        {
          gfc_error ("Non-polymorphic passed-object dummy argument of '%s'"
@@ -9528,7 +10165,27 @@ resolve_typebound_procedure (gfc_symtree* stree)
                     me_arg->name, &where, resolve_bindings_derived->name);
          goto error;
        }
-
+  
+      gcc_assert (me_arg->ts.type == BT_CLASS);
+      if (me_arg->ts.u.derived->components->as
+         && me_arg->ts.u.derived->components->as->rank > 0)
+       {
+         gfc_error ("Passed-object dummy argument of '%s' at %L must be"
+                    " scalar", proc->name, &where);
+         goto error;
+       }
+      if (me_arg->ts.u.derived->components->attr.allocatable)
+       {
+         gfc_error ("Passed-object dummy argument of '%s' at %L must not"
+                    " be ALLOCATABLE", proc->name, &where);
+         goto error;
+       }
+      if (me_arg->ts.u.derived->components->attr.class_pointer)
+       {
+         gfc_error ("Passed-object dummy argument of '%s' at %L must not"
+                    " be POINTER", proc->name, &where);
+         goto error;
+       }
     }
 
   /* If we are extending some type, check that we don't override a procedure
@@ -9787,8 +10444,9 @@ 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.  */
@@ -9893,6 +10551,12 @@ 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
@@ -10346,7 +11010,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)
     {
@@ -10651,9 +11315,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;
@@ -11028,12 +11689,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)
@@ -11049,18 +11717,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;
 
@@ -11257,10 +11937,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;
@@ -11719,7 +12397,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;