OSDN Git Service

2010-08-04 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / resolve.c
index d92c69c..c422eeb 100644 (file)
@@ -703,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)
@@ -751,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);
@@ -916,12 +901,73 @@ resolve_structure_cons (gfc_expr *expr)
            t = gfc_convert_type (cons->expr, &comp->ts, 1);
        }
 
+      /* For strings, the length of the constructor should be the same as
+        the one of the structure, ensure this if the lengths are known at
+        compile time and when we are dealing with PARAMETER or structure
+        constructors.  */
+      if (cons->expr->ts.type == BT_CHARACTER && comp->ts.u.cl
+         && comp->ts.u.cl->length
+         && comp->ts.u.cl->length->expr_type == EXPR_CONSTANT
+         && cons->expr->ts.u.cl && cons->expr->ts.u.cl->length
+         && cons->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT
+         && mpz_cmp (cons->expr->ts.u.cl->length->value.integer,
+                     comp->ts.u.cl->length->value.integer) != 0)
+       {
+         if (cons->expr->expr_type == EXPR_VARIABLE
+             && cons->expr->symtree->n.sym->attr.flavor == FL_PARAMETER)
+           {
+             /* Wrap the parameter in an array constructor (EXPR_ARRAY)
+                to make use of the gfc_resolve_character_array_constructor
+                machinery.  The expression is later simplified away to
+                an array of string literals.  */
+             gfc_expr *para = cons->expr;
+             cons->expr = gfc_get_expr ();
+             cons->expr->ts = para->ts;
+             cons->expr->where = para->where;
+             cons->expr->expr_type = EXPR_ARRAY;
+             cons->expr->rank = para->rank;
+             cons->expr->shape = gfc_copy_shape (para->shape, para->rank);
+             gfc_constructor_append_expr (&cons->expr->value.constructor,
+                                          para, &cons->expr->where);
+           }
+         if (cons->expr->expr_type == EXPR_ARRAY)
+           {
+             gfc_constructor *p;
+             p = gfc_constructor_first (cons->expr->value.constructor);
+             if (cons->expr->ts.u.cl != p->expr->ts.u.cl)
+               {
+                 gfc_charlen *cl, *cl2;
+
+                 cl2 = NULL;
+                 for (cl = gfc_current_ns->cl_list; cl; cl = cl->next)
+                   {
+                     if (cl == cons->expr->ts.u.cl)
+                       break;
+                     cl2 = cl;
+                   }
+
+                 gcc_assert (cl);
+
+                 if (cl2)
+                   cl2->next = cl->next;
+
+                 gfc_free_expr (cl->length);
+                 gfc_free (cl);
+               }
+
+             cons->expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
+             cons->expr->ts.u.cl->length_from_typespec = true;
+             cons->expr->ts.u.cl->length = gfc_copy_expr (comp->ts.u.cl->length);
+             gfc_resolve_character_array_constructor (cons->expr);
+           }
+       }
+
       if (cons->expr->expr_type == EXPR_NULL
          && !(comp->attr.pointer || comp->attr.allocatable
               || comp->attr.proc_pointer
               || (comp->ts.type == BT_CLASS
-                  && (comp->ts.u.derived->components->attr.pointer
-                      || comp->ts.u.derived->components->attr.allocatable))))
+                  && (CLASS_DATA (comp)->attr.class_pointer
+                      || CLASS_DATA (comp)->attr.allocatable))))
        {
          t = FAILURE;
          gfc_error ("The NULL in the derived type constructor at %L is "
@@ -1831,7 +1877,8 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
     gfc_global_used (gsym, where);
 
   if (gfc_option.flag_whole_file
-       && sym->attr.if_source == IFSRC_UNKNOWN
+       && (sym->attr.if_source == IFSRC_UNKNOWN
+           || sym->attr.if_source == IFSRC_IFBODY)
        && gsym->type != GSYM_UNKNOWN
        && gsym->ns
        && gsym->ns->resolved != -1
@@ -1839,20 +1886,9 @@ 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;
-           }
-       }
+      gfc_symbol *def_sym;
 
+      /* Resolve the gsymbol namespace if needed.  */
       if (!gsym->ns->resolved)
        {
          gfc_dt_list *old_dt_list;
@@ -1872,36 +1908,177 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
          gfc_derived_types = old_dt_list;
        }
 
-      if (gsym->ns->proc_name->attr.function
-           && gsym->ns->proc_name->as
-           && gsym->ns->proc_name->as->rank
-           && (!sym->as || sym->as->rank != gsym->ns->proc_name->as->rank))
-       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)
+      /* 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;
+           }
+       }
+
+      def_sym = gsym->ns->proc_name;
+      if (def_sym->attr.entry_master)
        {
-         gfc_charlen *cl = sym->ts.u.cl;
+         gfc_entry_list *entry;
+         for (entry = gsym->ns->entries; entry; entry = entry->next)
+           if (strcmp (entry->sym->name, sym->name) == 0)
+             {
+               def_sym = entry->sym;
+               break;
+             }
+       }
+
+      /* 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 = def_sym->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, &def_sym->ts))
+       gfc_error ("Return type mismatch of function '%s' at %L (%s/%s)",
+                  sym->name, &sym->declared_at, gfc_typename (&sym->ts),
+                  gfc_typename (&def_sym->ts));
+
+      if (def_sym->formal && sym->attr.if_source != IFSRC_IFBODY)
+       {
+         gfc_formal_arglist *arg = def_sym->formal;
+         for ( ; arg; arg = arg->next)
+           if (!arg->sym)
+             continue;
+           /* F2003, 12.3.1.1 (2a); F2008, 12.4.2.2 (2a)  */
+           else if (arg->sym->attr.allocatable
+                    || arg->sym->attr.asynchronous
+                    || arg->sym->attr.optional
+                    || arg->sym->attr.pointer
+                    || arg->sym->attr.target
+                    || arg->sym->attr.value
+                    || arg->sym->attr.volatile_)
+             {
+               gfc_error ("Dummy argument '%s' of procedure '%s' at %L "
+                          "has an attribute that requires an explicit "
+                          "interface for this procedure", arg->sym->name,
+                          sym->name, &sym->declared_at);
+               break;
+             }
+           /* F2003, 12.3.1.1 (2b); F2008, 12.4.2.2 (2b)  */
+           else if (arg->sym && arg->sym->as
+                    && arg->sym->as->type == AS_ASSUMED_SHAPE)
+             {
+               gfc_error ("Procedure '%s' at %L with assumed-shape dummy "
+                          "argument '%s' must have an explicit interface",
+                          sym->name, &sym->declared_at, arg->sym->name);
+               break;
+             }
+           /* F2008, 12.4.2.2 (2c)  */
+           else if (arg->sym->attr.codimension)
+             {
+               gfc_error ("Procedure '%s' at %L with coarray dummy argument "
+                          "'%s' must have an explicit interface",
+                          sym->name, &sym->declared_at, arg->sym->name);
+               break;
+             }
+           /* F2003, 12.3.1.1 (2c); F2008, 12.4.2.2 (2d)   */
+           else if (false) /* TODO: is a parametrized derived type  */
+             {
+               gfc_error ("Procedure '%s' at %L with parametrized derived "
+                          "type argument '%s' must have an explicit "
+                          "interface", sym->name, &sym->declared_at,
+                          arg->sym->name);
+               break;
+             }
+           /* F2003, 12.3.1.1 (2d); F2008, 12.4.2.2 (2e)   */
+           else if (arg->sym->ts.type == BT_CLASS)
+             {
+               gfc_error ("Procedure '%s' at %L with polymorphic dummy "
+                          "argument '%s' must have an explicit interface",
+                          sym->name, &sym->declared_at, arg->sym->name);
+               break;
+             }
+       }
 
-         if (!sym->attr.entry_master && sym->attr.if_source == IFSRC_UNKNOWN
-              && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT)
+      if (def_sym->attr.function)
+       {
+         /* F2003, 12.3.1.1 (3a); F2008, 12.4.2.2 (3a) */
+         if (def_sym->as && def_sym->as->rank
+             && (!sym->as || sym->as->rank != def_sym->as->rank))
+           gfc_error ("The reference to function '%s' at %L either needs an "
+                      "explicit INTERFACE or the rank is incorrect", sym->name,
+                      where);
+
+         /* F2003, 12.3.1.1 (3b); F2008, 12.4.2.2 (3b) */
+         if ((def_sym->result->attr.pointer
+              || def_sym->result->attr.allocatable)
+              && (sym->attr.if_source != IFSRC_IFBODY
+                  || def_sym->result->attr.pointer
+                       != sym->result->attr.pointer
+                  || def_sym->result->attr.allocatable
+                       != sym->result->attr.allocatable))
+           gfc_error ("Function '%s' at %L with a POINTER or ALLOCATABLE "
+                      "result must have an explicit interface", sym->name,
+                      where);
+
+         /* F2003, 12.3.1.1 (3c); F2008, 12.4.2.2 (3c)  */
+         if (sym->ts.type == BT_CHARACTER && sym->attr.if_source != IFSRC_IFBODY
+             && def_sym->ts.u.cl->length != NULL)
            {
-              gfc_error ("Nonconstant character-length function '%s' at %L "
-                        "must have an explicit interface", sym->name,
-                        &sym->declared_at);
+             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);
+               }
            }
        }
 
+      /* F2003, 12.3.1.1 (4); F2008, 12.4.2.2 (4) */
+      if (def_sym->attr.elemental && !sym->attr.elemental)
+       {
+         gfc_error ("ELEMENTAL procedure '%s' at %L must have an explicit "
+                    "interface", sym->name, &sym->declared_at);
+       }
+
+      /* F2003, 12.3.1.1 (5); F2008, 12.4.2.2 (5) */
+      if (def_sym->attr.is_bind_c && !sym->attr.is_bind_c)
+       {
+         gfc_error ("Procedure '%s' at %L with BIND(C) attribute must have "
+                    "an explicit interface", sym->name, &sym->declared_at);
+       }
+
       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);
+      if (sym->attr.if_source != IFSRC_IFBODY)  
+       gfc_procedure_use (def_sym, actual, where);
 
       gfc_errors_to_warnings (0);
     }
@@ -2163,6 +2340,7 @@ is_external_proc (gfc_symbol *sym)
        && !(sym->attr.intrinsic
              || gfc_is_intrinsic (sym, sym->attr.subroutine, sym->declared_at))
        && sym->attr.proc != PROC_ST_FUNCTION
+       && !sym->attr.proc_pointer
        && !sym->attr.use_assoc
        && sym->name)
     return true;
@@ -2343,10 +2521,11 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
   char binding_label[GFC_MAX_BINDING_LABEL_LEN + 1];
-  int optional_arg = 0, is_pointer = 0;
+  int optional_arg = 0;
   gfc_try retval = SUCCESS;
   gfc_symbol *args_sym;
   gfc_typespec *arg_ts;
+  symbol_attribute arg_attr;
 
   if (args->expr->expr_type == EXPR_CONSTANT
       || args->expr->expr_type == EXPR_OP
@@ -2363,8 +2542,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
      and not necessarily that of the expr symbol (args_sym), because
      the actual expression could be a part-ref of the expr symbol.  */
   arg_ts = &(args->expr->ts);
-
-  is_pointer = gfc_is_data_pointer (args->expr);
+  arg_attr = gfc_expr_attr (args->expr);
     
   if (sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)
     {
@@ -2407,7 +2585,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
       else if (sym->intmod_sym_id == ISOCBINDING_LOC)
         {
           /* Make sure we have either the target or pointer attribute.  */
-         if (!args_sym->attr.target && !is_pointer)
+         if (!arg_attr.target && !arg_attr.pointer)
             {
               gfc_error_now ("Parameter '%s' to '%s' at %L must be either "
                              "a TARGET or an associated pointer",
@@ -2490,7 +2668,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
                          }
                     }
                 }
-              else if (is_pointer
+              else if (arg_attr.pointer
                       && is_scalar_expr_ptr (args->expr) != SUCCESS)
                 {
                   /* Case 1c, section 15.1.2.5, J3/04-007: an associated
@@ -2525,6 +2703,13 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
                                  &(args->expr->where));
                   retval = FAILURE;
                 }
+             else if (arg_ts->type == BT_CLASS)
+               {
+                 gfc_error_now ("Parameter '%s' to '%s' at %L must not be "
+                                "polymorphic", args_sym->name, sym->name,
+                                &(args->expr->where));
+                 retval = FAILURE;
+               }
             }
         }
       else if (sym->intmod_sym_id == ISOCBINDING_FUNLOC)
@@ -3578,11 +3763,11 @@ resolve_operator (gfc_expr *e)
              e->rank = op1->rank;
              if (e->shape == NULL)
                {
-                 t = compare_shapes(op1, op2);
+                 t = compare_shapes (op1, op2);
                  if (t == FAILURE)
                    e->shape = NULL;
                  else
-               e->shape = gfc_copy_shape (op1->shape, op1->rank);
+                   e->shape = gfc_copy_shape (op1->shape, op1->rank);
                }
            }
          else
@@ -4094,7 +4279,7 @@ find_array_spec (gfc_expr *e)
   gfc_ref *ref;
 
   if (e->symtree->n.sym->ts.type == BT_CLASS)
-    as = e->symtree->n.sym->ts.u.derived->components->as;
+    as = CLASS_DATA (e->symtree->n.sym)->as;
   else
     as = e->symtree->n.sym->as;
   derived = NULL;
@@ -4675,6 +4860,15 @@ resolve_variable (gfc_expr *e)
        sym->entry_id = current_entry_id + 1;
     }
 
+  /* If a symbol has been host_associated mark it.  This is used latter,
+     to identify if aliasing is possible via host association.  */
+  if (sym->attr.flavor == FL_VARIABLE
+       && gfc_current_ns->parent
+       && (gfc_current_ns->parent == sym->ns
+             || (gfc_current_ns->parent->parent
+                   && gfc_current_ns->parent->parent == sym->ns)))
+    sym->attr.host_assoc = 1;
+
 resolve_procedure:
   if (t == SUCCESS && resolve_procedure_expression (e) == FAILURE)
     t = FAILURE;
@@ -5123,6 +5317,43 @@ 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.  */
@@ -5132,6 +5363,8 @@ 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;
@@ -5184,10 +5417,11 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
          if (matches)
            {
              e->value.compcall.tbp = g->specific;
+             genname = g->specific_st->name;
              /* Pass along the name for CLASS methods, where the vtab
                 procedure pointer component has to be referenced.  */
              if (name)
-               *name = g->specific_st->name;
+               *name = genname;
              goto success;
            }
        }
@@ -5199,6 +5433,13 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
   return FAILURE;
 
 success:
+  /* Make sure that we have the right specific instance for the 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;
 }
 
@@ -5306,38 +5547,6 @@ resolve_compcall (gfc_expr* e, const char **name)
 }
 
 
-/* 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 a typebound function, or 'method'. First separate all
    the non-CLASS references by calling resolve_compcall directly.  */
@@ -5351,13 +5560,44 @@ resolve_typebound_function (gfc_expr* e)
   gfc_ref *class_ref;
   gfc_symtree *st;
   const char *name;
-  const char *genname;
   gfc_typespec ts;
+  gfc_expr *expr;
 
   st = e->symtree;
+
+  /* Deal with typebound operators for CLASS objects.  */
+  expr = e->value.compcall.base_object;
+  if (expr && expr->symtree->n.sym->ts.type == BT_CLASS
+       && e->value.compcall.name)
+    {
+      /* Since the typebound operators are generic, we have to ensure
+        that any delays in resolution are corrected and that the vtab
+        is present.  */
+      ts = expr->symtree->n.sym->ts;
+      declared = ts.u.derived;
+      c = gfc_find_component (declared, "$vptr", true, true);
+      if (c->ts.u.derived == NULL)
+       c->ts.u.derived = gfc_find_derived_vtab (declared);
+
+      if (resolve_compcall (e, &name) == FAILURE)
+       return FAILURE;
+
+      /* Use the generic name if it is there.  */
+      name = name ? name : e->value.function.esym->name;
+      e->symtree = expr->symtree;
+      expr->symtree->n.sym->ts.u.derived = declared;
+      gfc_add_component_ref (e, "$vptr");
+      gfc_add_component_ref (e, name);
+      e->value.function.esym = NULL;
+      return SUCCESS;
+    }
+
   if (st == NULL)
     return resolve_compcall (e, NULL);
 
+  if (resolve_ref (e) == FAILURE)
+    return FAILURE;
+
   /* Get the CLASS declared type.  */
   declared = get_declared_from_expr (&class_ref, &new_ref, e);
 
@@ -5372,37 +5612,21 @@ resolve_typebound_function (gfc_expr* e)
   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);
+  if (resolve_compcall (e, &name) == FAILURE)
+    return FAILURE;
   ts = e->ts;
 
   /* Then convert the expression to a procedure pointer component call.  */
   e->value.function.esym = NULL;
   e->symtree = st;
 
-  if (class_ref)  
-    {
-      gfc_free_ref_list (class_ref->next);
-      e->ref = new_ref;
-    }
+  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
@@ -5425,16 +5649,47 @@ resolve_typebound_subroutine (gfc_code *code)
   gfc_ref *new_ref;
   gfc_ref *class_ref;
   gfc_symtree *st;
-  const char *genname;
   const char *name;
   gfc_typespec ts;
+  gfc_expr *expr;
 
   st = code->expr1->symtree;
+
+  /* Deal with typebound operators for CLASS objects.  */
+  expr = code->expr1->value.compcall.base_object;
+  if (expr && expr->symtree->n.sym->ts.type == BT_CLASS
+       && code->expr1->value.compcall.name)
+    {
+      /* Since the typebound operators are generic, we have to ensure
+        that any delays in resolution are corrected and that the vtab
+        is present.  */
+      ts = expr->symtree->n.sym->ts;
+      declared = ts.u.derived;
+      c = gfc_find_component (declared, "$vptr", true, true);
+      if (c->ts.u.derived == NULL)
+       c->ts.u.derived = gfc_find_derived_vtab (declared);
+
+      if (resolve_typebound_call (code, &name) == FAILURE)
+       return FAILURE;
+
+      /* Use the generic name if it is there.  */
+      name = name ? name : code->expr1->value.function.esym->name;
+      code->expr1->symtree = expr->symtree;
+      expr->symtree->n.sym->ts.u.derived = declared;
+      gfc_add_component_ref (code->expr1, "$vptr");
+      gfc_add_component_ref (code->expr1, name);
+      code->expr1->value.function.esym = NULL;
+      return SUCCESS;
+    }
+
   if (st == NULL)
     return resolve_typebound_call (code, NULL);
 
+  if (resolve_ref (code->expr1) == FAILURE)
+    return FAILURE;
+
   /* Get the CLASS declared type.  */
-  declared = get_declared_from_expr (&class_ref, &new_ref, code->expr1);
+  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)
@@ -5442,40 +5697,21 @@ resolve_typebound_subroutine (gfc_code *code)
     {
       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);
+  if (resolve_typebound_call (code, &name) == FAILURE)
+    return FAILURE;
   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 (class_ref)  
-    {
-      gfc_free_ref_list (class_ref->next);
-      code->expr1->ref = new_ref;
-    }
+  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
@@ -5657,7 +5893,7 @@ gfc_resolve_expr (gfc_expr *e)
        {
          expression_rank (e);
          if (gfc_is_constant_expr (e) || gfc_is_expandable_expr (e))
-           gfc_expand_constructor (e);
+           gfc_expand_constructor (e, false);
        }
 
       /* This provides the opportunity for the length of constructors with
@@ -5667,7 +5903,7 @@ gfc_resolve_expr (gfc_expr *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);
+         gfc_expand_constructor (e, false);
          t = gfc_resolve_character_array_constructor (e);
        }
 
@@ -5967,8 +6203,8 @@ resolve_deallocate_expr (gfc_expr *e)
 
   if (sym->ts.type == BT_CLASS)
     {
-      allocatable = sym->ts.u.derived->components->attr.allocatable;
-      pointer = sym->ts.u.derived->components->attr.pointer;
+      allocatable = CLASS_DATA (sym)->attr.allocatable;
+      pointer = CLASS_DATA (sym)->attr.class_pointer;
     }
   else
     {
@@ -5991,8 +6227,8 @@ resolve_deallocate_expr (gfc_expr *e)
          c = ref->u.c.component;
          if (c->ts.type == BT_CLASS)
            {
-             allocatable = c->ts.u.derived->components->attr.allocatable;
-             pointer = c->ts.u.derived->components->attr.pointer;
+             allocatable = CLASS_DATA (c)->attr.allocatable;
+             pointer = CLASS_DATA (c)->attr.class_pointer;
            }
          else
            {
@@ -6014,6 +6250,7 @@ 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 && sym->attr.intent == INTENT_IN)
@@ -6088,8 +6325,11 @@ gfc_expr_to_initialize (gfc_expr *e)
 static gfc_try
 conformable_arrays (gfc_expr *e1, gfc_expr *e2)
 {
+  gfc_ref *tail;
+  for (tail = e2->ref; tail && tail->next; tail = tail->next);
+  
   /* First compare rank.  */
-  if (e2->ref && e1->rank != e2->ref->u.ar.as->rank)
+  if (tail && e1->rank != tail->u.ar.as->rank)
     {
       gfc_error ("Source-expr at %L must be scalar or have the "
                 "same rank as the allocate-object at %L",
@@ -6106,15 +6346,15 @@ conformable_arrays (gfc_expr *e1, gfc_expr *e2)
 
       for (i = 0; i < e1->rank; i++)
        {
-         if (e2->ref->u.ar.end[i])
+         if (tail->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_set (s, tail->u.ar.end[i]->value.integer);
+             mpz_sub (s, s, tail->u.ar.start[i]->value.integer);
              mpz_add_ui (s, s, 1);
            }
          else
            {
-             mpz_set (s, e2->ref->u.ar.start[i]->value.integer);
+             mpz_set (s, tail->u.ar.start[i]->value.integer);
            }
 
          if (mpz_cmp (e1->shape[i], s) != 0)
@@ -6145,10 +6385,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
   symbol_attribute attr;
   gfc_ref *ref, *ref2;
   gfc_array_ref *ar;
-  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;
@@ -6187,11 +6426,11 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
     {
       if (sym->ts.type == BT_CLASS)
        {
-         allocatable = sym->ts.u.derived->components->attr.allocatable;
-         pointer = sym->ts.u.derived->components->attr.pointer;
-         dimension = sym->ts.u.derived->components->attr.dimension;
-         codimension = sym->ts.u.derived->components->attr.codimension;
-         is_abstract = sym->ts.u.derived->components->attr.abstract;
+         allocatable = CLASS_DATA (sym)->attr.allocatable;
+         pointer = CLASS_DATA (sym)->attr.class_pointer;
+         dimension = CLASS_DATA (sym)->attr.dimension;
+         codimension = CLASS_DATA (sym)->attr.codimension;
+         is_abstract = CLASS_DATA (sym)->attr.abstract;
        }
       else
        {
@@ -6225,11 +6464,11 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
                c = ref->u.c.component;
                if (c->ts.type == BT_CLASS)
                  {
-                   allocatable = c->ts.u.derived->components->attr.allocatable;
-                   pointer = c->ts.u.derived->components->attr.pointer;
-                   dimension = c->ts.u.derived->components->attr.dimension;
-                   codimension = c->ts.u.derived->components->attr.codimension;
-                   is_abstract = c->ts.u.derived->components->attr.abstract;
+                   allocatable = CLASS_DATA (c)->attr.allocatable;
+                   pointer = CLASS_DATA (c)->attr.class_pointer;
+                   dimension = CLASS_DATA (c)->attr.dimension;
+                   codimension = CLASS_DATA (c)->attr.codimension;
+                   is_abstract = CLASS_DATA (c)->attr.abstract;
                  }
                else
                  {
@@ -6281,11 +6520,14 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
          goto failure;
        }
     }
-  else if (is_abstract&& code->ext.alloc.ts.type == BT_UNKNOWN)
+
+  /* Check F08:C629.  */
+  if (is_abstract && code->ext.alloc.ts.type == BT_UNKNOWN
+      && !code->expr3)
     {
       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);
+                "type-spec or source-expr", sym->name, &e->where);
       goto failure;
     }
 
@@ -6296,25 +6538,26 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
       goto failure;
     }
     
-  if (!code->expr3)
+  if (!code->expr3 || code->expr3->mold)
     {
       /* 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 (&e->ts.u.derived->components->ts)))
-                  || (code->ext.alloc.ts.type == BT_DERIVED
-                      && (init_e = gfc_default_initializer (&code->ext.alloc.ts)))))
+      gfc_expr *init_e = NULL;
+      gfc_typespec ts;
+
+      if (code->ext.alloc.ts.type == BT_DERIVED)
+       ts = code->ext.alloc.ts;
+      else if (code->expr3)
+       ts = code->expr3->ts;
+      else
+       ts = e->ts;
+
+      if (ts.type == BT_DERIVED)
+       init_e = gfc_default_initializer (&ts);
+      /* FIXME: Use default init of dynamic type (cf. PR 44541).  */
+      else if (e->ts.type == BT_CLASS)
+       init_e = gfc_default_initializer (&ts.u.derived->components->ts);
+
+      if (init_e)
        {
          gfc_code *init_st = gfc_get_code ();
          init_st->loc = code->loc;
@@ -6466,8 +6709,29 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
 
       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);
+         {
+           gfc_ref *ref1, *ref2;
+           bool found = true;
+
+           for (ref1 = p->expr->ref, ref2 = stat->ref; ref1 && ref2;
+                ref1 = ref1->next, ref2 = ref2->next)
+             {
+               if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT)
+                 continue;
+               if (ref1->u.c.component->name != ref2->u.c.component->name)
+                 {
+                   found = false;
+                   break;
+                 }
+             }
+
+           if (found)
+             {
+               gfc_error ("Stat-variable at %L shall not be %sd within "
+                          "the same %s statement", &stat->where, fcn, fcn);
+               break;
+             }
+         }
     }
 
   /* Check the errmsg variable.  */
@@ -6495,8 +6759,29 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
 
       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);
+         {
+           gfc_ref *ref1, *ref2;
+           bool found = true;
+
+           for (ref1 = p->expr->ref, ref2 = errmsg->ref; ref1 && ref2;
+                ref1 = ref1->next, ref2 = ref2->next)
+             {
+               if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT)
+                 continue;
+               if (ref1->u.c.component->name != ref2->u.c.component->name)
+                 {
+                   found = false;
+                   break;
+                 }
+             }
+
+           if (found)
+             {
+               gfc_error ("Errmsg-variable at %L shall not be %sd within "
+                          "the same %s statement", &errmsg->where, fcn, fcn);
+               break;
+             }
+         }
     }
 
   /* Check that an allocate-object appears only once in the statement.  
@@ -6747,8 +7032,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);
 
@@ -6834,6 +7120,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
@@ -6856,7 +7167,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);
@@ -6907,8 +7217,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;
@@ -6930,7 +7240,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;
@@ -7075,13 +7385,26 @@ resolve_select_type (gfc_code *code)
   gfc_namespace *ns;
   int error = 0;
 
-  ns = code->ext.ns;
+  ns = code->ext.block.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)
-    selector_type = code->expr2->ts.u.derived->components->ts.u.derived;
+    {
+      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 = code->expr1->ts.u.derived->components->ts.u.derived;
+    selector_type = CLASS_DATA (code->expr1)->ts.u.derived;
 
   /* Loop over TYPE IS / CLASS IS cases.  */
   for (body = code->block; body; body = body->block)
@@ -7149,6 +7472,7 @@ resolve_select_type (gfc_code *code)
   else
     ns->code->next = new_st;
   code->op = EXEC_BLOCK;
+  code->ext.block.assoc = NULL;
   code->expr1 = code->expr2 =  NULL;
   code->block = NULL;
 
@@ -7289,7 +7613,7 @@ resolve_select_type (gfc_code *code)
          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);
+         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);
@@ -7892,10 +8216,11 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
 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.  */
+  /* For an ASSOCIATE block, the associations (and their targets) are already
+     resolved during gfc_resolve_symbol.  */
 
-  gfc_resolve (code->ext.ns);
+  /* Resolve the BLOCK's namespace.  */
+  gfc_resolve (code->ext.block.ns);
 }
 
 
@@ -8018,7 +8343,7 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
         and rhs is the same symbol as the lhs.  */
       if ((*rhsptr)->expr_type == EXPR_VARIABLE
            && (*rhsptr)->symtree->n.sym->ts.type == BT_DERIVED
-           && has_default_initializer ((*rhsptr)->symtree->n.sym->ts.u.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);
 
@@ -8216,7 +8541,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
              gfc_resolve_omp_do_blocks (code, ns);
              break;
            case EXEC_SELECT_TYPE:
-             gfc_current_ns = code->ext.ns;
+             gfc_current_ns = code->ext.block.ns;
              gfc_resolve_blocks (code->block, gfc_current_ns);
              gfc_current_ns = ns;
              break;
@@ -8380,7 +8705,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          break;
 
        case EXEC_BLOCK:
-         gfc_resolve (code->ext.ns);
+         gfc_resolve (code->ext.block.ns);
          break;
 
        case EXEC_DO:
@@ -8922,7 +9247,7 @@ build_default_init_expr (gfc_symbol *sym)
     {    
     case BT_INTEGER:
       if (gfc_option.flag_init_integer != GFC_INIT_INTEGER_OFF)
-       mpz_init_set_si (init_expr->value.integer, 
+       mpz_set_si (init_expr->value.integer, 
                         gfc_option.flag_init_integer_value);
       else
        {
@@ -8932,7 +9257,6 @@ build_default_init_expr (gfc_symbol *sym)
       break;
 
     case BT_REAL:
-      mpfr_init (init_expr->value.real);
       switch (gfc_option.flag_init_real)
        {
        case GFC_INIT_REAL_SNAN:
@@ -8962,7 +9286,6 @@ build_default_init_expr (gfc_symbol *sym)
       break;
          
     case BT_COMPLEX:
-      mpc_init2 (init_expr->value.complex, mpfr_get_default_prec());
       switch (gfc_option.flag_init_real)
        {
        case GFC_INIT_REAL_SNAN:
@@ -9105,6 +9428,30 @@ resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag)
          return FAILURE;
         }
     }
+
+  /* Constraints on polymorphic variables.  */
+  if (sym->ts.type == BT_CLASS && !(sym->result && sym->result != sym))
+    {
+      /* F03:C502.  */
+      if (sym->attr.class_ok
+         && !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;
+       }
+
+      /* 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;
 }
 
@@ -9143,40 +9490,19 @@ 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_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)
-    {
-      /* C502.  */
-      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->components->ts.u.derived->name,
-                    sym->name, &sym->declared_at);
-         return FAILURE;
-       }
-
-      /* 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;
-       }
-    }
-
   /* Assign default initializer.  */
   if (!(sym->value || sym->attr.pointer || sym->attr.allocatable)
       && (!no_init_flag || sym->attr.intent == INTENT_OUT))
@@ -9996,7 +10322,7 @@ resolve_tb_generic_targets (gfc_symbol* super_type,
        target_name = target->specific_st->name;
 
        /* Defined for this type directly.  */
-       if (target->specific_st->n.tb)
+       if (target->specific_st->n.tb && !target->specific_st->n.tb->error)
          {
            target->specific = target->specific_st->n.tb;
            goto specific_found;
@@ -10347,7 +10673,7 @@ resolve_typebound_procedure (gfc_symtree* stree)
          goto error;
        }
 
-      if (me_arg->ts.u.derived->components->ts.u.derived
+      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"
@@ -10357,20 +10683,19 @@ resolve_typebound_procedure (gfc_symtree* stree)
        }
   
       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)
+      if (CLASS_DATA (me_arg)->as && CLASS_DATA (me_arg)->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)
+      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 (me_arg->ts.u.derived->components->attr.class_pointer)
+      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);
@@ -10516,7 +10841,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)
@@ -10546,9 +10874,21 @@ resolve_fl_derived (gfc_symbol *sym)
 {
   gfc_symbol* super_type;
   gfc_component *c;
-  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);
+         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)
@@ -10602,6 +10942,14 @@ resolve_fl_derived (gfc_symbol *sym)
          return FAILURE;
        }
 
+      /* F2008, C448.  */
+      if (c->attr.contiguous && (!c->attr.dimension || !c->attr.pointer))
+       {
+         gfc_error ("Component '%s' at %L has the CONTIGUOUS attribute but "
+                    "is not an array pointer", c->name, &c->loc);
+         return FAILURE;
+       }
+
       if (c->attr.proc_pointer && c->ts.interface)
        {
          if (c->ts.interface->attr.procedure && !sym->attr.vtype)
@@ -10668,7 +11016,7 @@ resolve_fl_derived (gfc_symbol *sym)
                  c->ts.u.cl = cl;
                }
            }
-         else if (c->ts.interface->name[0] != '\0' && !sym->attr.vtype)
+         else if (!sym->attr.vtype && c->ts.interface->name[0] != '\0')
            {
              gfc_error ("Interface '%s' of procedure pointer component "
                         "'%s' at %L must be explicit", c->ts.interface->name,
@@ -10738,7 +11086,7 @@ resolve_fl_derived (gfc_symbol *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
-                 && me_arg->ts.u.derived->components->ts.u.derived != sym))
+                 && 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,
@@ -10851,9 +11199,9 @@ resolve_fl_derived (gfc_symbol *sym)
          return FAILURE;
        }
 
-      if (c->ts.type == BT_CLASS && c->ts.u.derived->components->attr.pointer
-         && c->ts.u.derived->components->ts.u.derived->components == NULL
-         && !c->ts.u.derived->components->ts.u.derived->attr.zero_comp)
+      if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.class_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,
@@ -10863,8 +11211,8 @@ resolve_fl_derived (gfc_symbol *sym)
 
       /* C437.  */
       if (c->ts.type == BT_CLASS
-         && !(c->ts.u.derived->components->attr.pointer
-              || c->ts.u.derived->components->attr.allocatable))
+         && !(CLASS_DATA (c)->attr.class_pointer
+              || CLASS_DATA (c)->attr.allocatable))
        {
          gfc_error ("Component '%s' with CLASS at %L must be allocatable "
                     "or pointer", c->name, &c->loc);
@@ -10881,25 +11229,10 @@ resolve_fl_derived (gfc_symbol *sym)
            && sym != c->ts.u.derived)
        add_dt_to_dt_list (c->ts.u.derived);
 
-      if (c->attr.pointer || c->attr.proc_pointer || c->attr.allocatable
-         || c->as == NULL)
-       continue;
-
-      for (i = 0; i < c->as->rank; i++)
-       {
-         if (c->as->lower[i] == NULL
-             || (resolve_index_expr (c->as->lower[i]) == FAILURE)
-             || !gfc_is_constant_expr (c->as->lower[i])
-             || c->as->upper[i] == NULL
-             || (resolve_index_expr (c->as->upper[i]) == FAILURE)
-             || !gfc_is_constant_expr (c->as->upper[i]))
-           {
-             gfc_error ("Component '%s' of '%s' at %L must have "
-                        "constant array bounds",
-                        c->name, sym->name, &c->loc);
-             return FAILURE;
-           }
-       }
+      if (gfc_resolve_array_spec (c->as, !(c->attr.pointer
+                                          || c->attr.proc_pointer
+                                          || c->attr.allocatable)) == FAILURE)
+       return FAILURE;
     }
 
   /* Resolve the type-bound procedures.  */
@@ -10913,6 +11246,7 @@ resolve_fl_derived (gfc_symbol *sym)
   /* If this is a non-ABSTRACT type extending an ABSTRACT one, ensure that
      all DEFERRED bindings are overridden.  */
   if (super_type && super_type->attr.abstract && !sym->attr.abstract
+      && !sym->attr.is_class
       && ensure_not_abstract (sym, super_type) == FAILURE)
     return FAILURE;
 
@@ -11092,6 +11426,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)
     {
 
@@ -11105,9 +11443,7 @@ resolve_symbol (gfc_symbol *sym)
            {
              this_symtree = gfc_find_symtree (gfc_current_ns->sym_root,
                                               sym->name);
-             sym->refs--;
-             if (!sym->refs)
-               gfc_free_symbol (sym);
+             gfc_release_symbol (sym);
              symtree->n.sym->refs++;
              this_symtree->n.sym = symtree->n.sym;
              return;
@@ -11170,6 +11506,7 @@ resolve_symbol (gfc_symbol *sym)
          sym->attr.pure = ifc->attr.pure;
          sym->attr.elemental = ifc->attr.elemental;
          sym->attr.dimension = ifc->attr.dimension;
+         sym->attr.contiguous = ifc->attr.contiguous;
          sym->attr.recursive = ifc->attr.recursive;
          sym->attr.always_explicit = ifc->attr.always_explicit;
           sym->attr.ext_attr |= ifc->attr.ext_attr;
@@ -11202,6 +11539,31 @@ 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;
+    }
+
+
+  /* F2008, C530. */
+  if (sym->attr.contiguous
+      && (!sym->attr.dimension || (sym->as->type != AS_ASSUMED_SHAPE
+                                  && !sym->attr.pointer)))
+    {
+      gfc_error ("'%s' at %L has the CONTIGUOUS attribute but is not an "
+                 "array pointer or an assumed-shape array", sym->name,
+                 &sym->declared_at);
+      return;
+    }
+
   if (sym->attr.flavor == FL_DERIVED && resolve_fl_derived (sym) == FAILURE)
     return;
 
@@ -11212,7 +11574,6 @@ resolve_symbol (gfc_symbol *sym)
      can.  */
   mp_flag = (sym->result != NULL && sym->result != sym);
 
-
   /* Make sure that the intrinsic is consistent with its internal 
      representation. This needs to be done before assigning a default 
      type to avoid spurious warnings.  */
@@ -11220,6 +11581,18 @@ resolve_symbol (gfc_symbol *sym)
       && resolve_intrinsic (sym, &sym->declared_at) == FAILURE)
     return;
 
+  /* For associate names, resolve corresponding expression and make sure
+     they get their type-spec set this way.  */
+  if (sym->assoc)
+    {
+      gcc_assert (sym->attr.flavor == FL_VARIABLE);
+      if (gfc_resolve_expr (sym->assoc->target) != SUCCESS)
+       return;
+
+      sym->ts = sym->assoc->target->ts;
+      gcc_assert (sym->ts.type != BT_UNKNOWN);
+    }
+
   /* Assign default type to symbols that need one and don't have one.  */
   if (sym->ts.type == BT_UNKNOWN)
     {
@@ -11249,6 +11622,7 @@ resolve_symbol (gfc_symbol *sym)
                  sym->attr.dimension = sym->result->attr.dimension;
                  sym->attr.pointer = sym->result->attr.pointer;
                  sym->attr.allocatable = sym->result->attr.allocatable;
+                 sym->attr.contiguous = sym->result->attr.contiguous;
                }
            }
        }
@@ -11781,11 +12155,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.  */
@@ -11834,6 +12211,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);
@@ -11842,26 +12220,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);
 
@@ -11877,7 +12258,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;
        }
@@ -11886,7 +12266,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;
        }
@@ -11896,9 +12275,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);
@@ -12196,7 +12575,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 "
@@ -12752,4 +13131,6 @@ gfc_resolve (gfc_namespace *ns)
   gfc_current_ns = old_ns;
   cs_base = old_cs_base;
   ns->resolved = 1;
+
+  gfc_run_passes (ns);
 }