OSDN Git Service

2012-06-14 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / decl.c
index b1c1517..8afccd5 100644 (file)
@@ -1,5 +1,5 @@
 /* Declaration statement matcher
-   Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
@@ -25,7 +25,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "match.h"
 #include "parse.h"
 #include "flags.h"
-
+#include "constructor.h"
+#include "tree.h"
 
 /* Macros to access allocate memory for gfc_data_variable,
    gfc_data_value and gfc_data.  */
@@ -34,6 +35,9 @@ along with GCC; see the file COPYING3.  If not see
 #define gfc_get_data() XCNEW (gfc_data)
 
 
+static gfc_try set_binding_label (const char **, const char *, int);
+
+
 /* This flag is set if an old-style length selector is matched
    during a type-declaration statement.  */
 
@@ -51,7 +55,7 @@ static gfc_array_spec *current_as;
 static int colon_seen;
 
 /* The current binding label (if any).  */
-static char curr_binding_label[GFC_MAX_BINDING_LABEL_LEN + 1];
+static const char* curr_binding_label;
 /* Need to know how many identifiers are on the current data declaration
    line in case we're given the BIND(C) attribute with a NAME= specifier.  */
 static int num_idents_on_line;
@@ -119,7 +123,7 @@ free_variable (gfc_data_variable *p)
       gfc_free_expr (p->expr);
       gfc_free_iterator (&p->iter, 0);
       free_variable (p->list);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -134,8 +138,9 @@ free_value (gfc_data_value *p)
   for (; p; p = q)
     {
       q = p->next;
+      mpz_clear (p->repeat);
       gfc_free_expr (p->expr);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -152,7 +157,7 @@ gfc_free_data (gfc_data *p)
       q = p->next;
       free_variable (p->var);
       free_value (p->value);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -167,7 +172,7 @@ gfc_free_data_all (gfc_namespace *ns)
   for (;ns->data;)
     {
       d = ns->data->next;
-      gfc_free (ns->data);
+      free (ns->data);
       ns->data = d;
     }
 }
@@ -322,7 +327,7 @@ static match
 match_data_constant (gfc_expr **result)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
-  gfc_symbol *sym;
+  gfc_symbol *sym, *dt_sym = NULL;
   gfc_expr *expr;
   match m;
   locus old_loc;
@@ -365,15 +370,19 @@ match_data_constant (gfc_expr **result)
   if (gfc_find_symbol (name, NULL, 1, &sym))
     return MATCH_ERROR;
 
+  if (sym && sym->attr.generic)
+    dt_sym = gfc_find_dt_in_generic (sym);
+
   if (sym == NULL
-      || (sym->attr.flavor != FL_PARAMETER && sym->attr.flavor != FL_DERIVED))
+      || (sym->attr.flavor != FL_PARAMETER
+         && (!dt_sym || dt_sym->attr.flavor != FL_DERIVED)))
     {
       gfc_error ("Symbol '%s' must be a PARAMETER in DATA statement at %C",
                 name);
       return MATCH_ERROR;
     }
-  else if (sym->attr.flavor == FL_DERIVED)
-    return gfc_match_structure_constructor (sym, result, false);
+  else if (dt_sym && dt_sym->attr.flavor == FL_DERIVED)
+    return gfc_match_structure_constructor (dt_sym, result);
 
   /* Check to see if the value is an initialization array expression.  */
   if (sym->value->expr_type == EXPR_ARRAY)
@@ -490,21 +499,24 @@ match_old_style_init (const char *name)
   m = top_val_list (newdata);
   if (m != MATCH_YES)
     {
-      gfc_free (newdata);
+      free (newdata);
       return m;
     }
 
   if (gfc_pure (NULL))
     {
       gfc_error ("Initialization at %C is not allowed in a PURE procedure");
-      gfc_free (newdata);
+      free (newdata);
       return MATCH_ERROR;
     }
 
+  if (gfc_implicit_pure (NULL))
+    gfc_current_ns->proc_name->attr.implicit_pure = 0;
+
   /* Mark the variable as having appeared in a data statement.  */
   if (gfc_add_data (&sym->attr, sym->name, &sym->declared_at) == FAILURE)
     {
-      gfc_free (newdata);
+      free (newdata);
       return MATCH_ERROR;
     }
 
@@ -559,6 +571,9 @@ gfc_match_data (void)
       return MATCH_ERROR;
     }
 
+  if (gfc_implicit_pure (NULL))
+    gfc_current_ns->proc_name->attr.implicit_pure = 0;
+
   return MATCH_YES;
 
 cleanup:
@@ -570,6 +585,62 @@ cleanup:
 
 /************************ Declaration statements *********************/
 
+
+/* Auxilliary function to merge DIMENSION and CODIMENSION array specs.  */
+
+static void
+merge_array_spec (gfc_array_spec *from, gfc_array_spec *to, bool copy)
+{
+  int i;
+
+  if (to->rank == 0 && from->rank > 0)
+    {
+      to->rank = from->rank;
+      to->type = from->type;
+      to->cray_pointee = from->cray_pointee;
+      to->cp_was_assumed = from->cp_was_assumed;
+
+      for (i = 0; i < to->corank; i++)
+       {
+         to->lower[from->rank + i] = to->lower[i];
+         to->upper[from->rank + i] = to->upper[i];
+       }
+      for (i = 0; i < from->rank; i++)
+       {
+         if (copy)
+           {
+             to->lower[i] = gfc_copy_expr (from->lower[i]);
+             to->upper[i] = gfc_copy_expr (from->upper[i]);
+           }
+         else
+           {
+             to->lower[i] = from->lower[i];
+             to->upper[i] = from->upper[i];
+           }
+       }
+    }
+  else if (to->corank == 0 && from->corank > 0)
+    {
+      to->corank = from->corank;
+      to->cotype = from->cotype;
+
+      for (i = 0; i < from->corank; i++)
+       {
+         if (copy)
+           {
+             to->lower[to->rank + i] = gfc_copy_expr (from->lower[i]);
+             to->upper[to->rank + i] = gfc_copy_expr (from->upper[i]);
+           }
+         else
+           {
+             to->lower[to->rank + i] = from->lower[i];
+             to->upper[to->rank + i] = from->upper[i];
+           }
+       }
+    }
+}
+
+
 /* Match an intent specification.  Since this can only happen after an
    INTENT word, a legal intent-spec must follow.  */
 
@@ -590,16 +661,27 @@ match_intent_spec (void)
 
 
 /* Matches a character length specification, which is either a
-   specification expression or a '*'.  */
+   specification expression, '*', or ':'.  */
 
 static match
-char_len_param_value (gfc_expr **expr)
+char_len_param_value (gfc_expr **expr, bool *deferred)
 {
   match m;
 
+  *expr = NULL;
+  *deferred = false;
+
   if (gfc_match_char ('*') == MATCH_YES)
+    return MATCH_YES;
+
+  if (gfc_match_char (':') == MATCH_YES)
     {
-      *expr = NULL;
+      if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: deferred type "
+                         "parameter at %C") == FAILURE)
+       return MATCH_ERROR;
+
+      *deferred = true;
+
       return MATCH_YES;
     }
 
@@ -640,11 +722,12 @@ syntax:
    char_len_param_value in parenthesis.  */
 
 static match
-match_char_length (gfc_expr **expr)
+match_char_length (gfc_expr **expr, bool *deferred)
 {
   int length;
   match m;
 
+  *deferred = false; 
   m = gfc_match_char ('*');
   if (m != MATCH_YES)
     return m;
@@ -658,14 +741,14 @@ match_char_length (gfc_expr **expr)
       if (gfc_notify_std (GFC_STD_F95_OBS, "Obsolescent feature: "
                          "Old-style character length at %C") == FAILURE)
        return MATCH_ERROR;
-      *expr = gfc_int_expr (length);
+      *expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, length);
       return m;
     }
 
   if (gfc_match_char ('(') == MATCH_NO)
     goto syntax;
 
-  m = char_len_param_value (expr);
+  m = char_len_param_value (expr, deferred);
   if (m != MATCH_YES && gfc_matching_function)
     {
       gfc_undo_symbols ();
@@ -886,7 +969,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry)
    across platforms.  */
 
 gfc_try
-verify_c_interop_param (gfc_symbol *sym)
+gfc_verify_c_interop_param (gfc_symbol *sym)
 {
   int is_c_interop = 0;
   gfc_try retval = SUCCESS;
@@ -925,20 +1008,24 @@ verify_c_interop_param (gfc_symbol *sym)
     {
       if (sym->ns->proc_name->attr.is_bind_c == 1)
        {
-         is_c_interop =
-           (verify_c_interop (&(sym->ts))
-            == SUCCESS ? 1 : 0);
+         is_c_interop = (gfc_verify_c_interop (&(sym->ts)) == SUCCESS ? 1 : 0);
 
          if (is_c_interop != 1)
            {
              /* Make personalized messages to give better feedback.  */
              if (sym->ts.type == BT_DERIVED)
-               gfc_error ("Type '%s' at %L is a parameter to the BIND(C) "
-                          " procedure '%s' but is not C interoperable "
+               gfc_error ("Variable '%s' at %L is a dummy argument to the "
+                          "BIND(C) procedure '%s' but is not C interoperable "
                           "because derived type '%s' is not C interoperable",
                           sym->name, &(sym->declared_at),
                           sym->ns->proc_name->name, 
                           sym->ts.u.derived->name);
+             else if (sym->ts.type == BT_CLASS)
+               gfc_error ("Variable '%s' at %L is a dummy argument to the "
+                          "BIND(C) procedure '%s' but is not C interoperable "
+                          "because it is polymorphic",
+                          sym->name, &(sym->declared_at),
+                          sym->ns->proc_name->name);
              else
                gfc_warning ("Variable '%s' at %L is a parameter to the "
                             "BIND(C) procedure '%s' but may not be C "
@@ -985,14 +1072,22 @@ verify_c_interop_param (gfc_symbol *sym)
              retval = FAILURE;
            }
 
-         if (sym->attr.optional == 1)
+         if (sym->attr.optional == 1 && sym->attr.value)
            {
-             gfc_error ("Variable '%s' at %L cannot have the "
-                        "OPTIONAL attribute because procedure '%s'"
-                        " is BIND(C)", sym->name, &(sym->declared_at),
+             gfc_error ("Variable '%s' at %L cannot have both the OPTIONAL "
+                        "and the VALUE attribute because procedure '%s' "
+                        "is BIND(C)", sym->name, &(sym->declared_at),
                         sym->ns->proc_name->name);
              retval = FAILURE;
            }
+         else if (sym->attr.optional == 1
+                  && gfc_notify_std (GFC_STD_F2008_TS, "TS29113: Variable '%s' "
+                                     "at %L with OPTIONAL attribute in "
+                                     "procedure '%s' which is BIND(C)",
+                                     sym->name, &(sym->declared_at),
+                                     sym->ns->proc_name->name)
+                     == FAILURE)
+           retval = FAILURE;
 
           /* Make sure that if it has the dimension attribute, that it is
             either assumed size or explicit shape.  */
@@ -1025,10 +1120,11 @@ verify_c_interop_param (gfc_symbol *sym)
 }
 
 
+
 /* Function called by variable_decl() that adds a name to the symbol table.  */
 
 static gfc_try
-build_sym (const char *name, gfc_charlen *cl,
+build_sym (const char *name, gfc_charlen *cl, bool cl_deferred,
           gfc_array_spec **as, locus *var_locus)
 {
   symbol_attribute attr;
@@ -1045,7 +1141,10 @@ build_sym (const char *name, gfc_charlen *cl,
     return FAILURE;
 
   if (sym->ts.type == BT_CHARACTER)
-    sym->ts.u.cl = cl;
+    {
+      sym->ts.u.cl = cl;
+      sym->ts.deferred = cl_deferred;
+    }
 
   /* Add dimension attribute if present.  */
   if (gfc_set_array_spec (sym, *as, var_locus) == FAILURE)
@@ -1056,6 +1155,7 @@ build_sym (const char *name, gfc_charlen *cl,
      dimension attribute.  */
   attr = current_attr;
   attr.dimension = 0;
+  attr.codimension = 0;
 
   if (gfc_copy_attr (&sym->attr, &attr, var_locus) == FAILURE)
     return FAILURE;
@@ -1068,11 +1168,11 @@ build_sym (const char *name, gfc_charlen *cl,
      with a bind(c) and make sure the binding label is set correctly.  */
   if (sym->attr.is_bind_c == 1)
     {
-      if (sym->binding_label[0] == '\0')
+      if (!sym->binding_label)
         {
          /* Set the binding label and verify that if a NAME= was specified
             then only one identifier was in the entity-decl-list.  */
-         if (set_binding_label (sym->binding_label, sym->name,
+         if (set_binding_label (&sym->binding_label, sym->name,
                                 num_idents_on_line) == FAILURE)
             return FAILURE;
         }
@@ -1097,6 +1197,9 @@ build_sym (const char *name, gfc_charlen *cl,
 
   sym->attr.implied_index = 0;
 
+  if (sym->ts.type == BT_CLASS)
+    return gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false);
+
   return SUCCESS;
 }
 
@@ -1137,7 +1240,7 @@ gfc_set_constant_character_len (int len, gfc_expr *expr, int check_len)
                        &expr->where, slen, check_len);
 
       s[len] = '\0';
-      gfc_free (expr->value.character.string);
+      free (expr->value.character.string);
       expr->value.character.string = s;
       expr->value.character.length = len;
     }
@@ -1192,7 +1295,7 @@ gfc_free_enum_history (void)
   while (current != NULL)
     {
       next = current->next;
-      gfc_free (current);
+      free (current);
       current = next;
     }
   max_enum = NULL;
@@ -1248,8 +1351,10 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
        }
 
       /* Check if the assignment can happen. This has to be put off
-        until later for a derived type variable.  */
+        until later for derived type variables and procedure pointers.  */
       if (sym->ts.type != BT_DERIVED && init->ts.type != BT_DERIVED
+         && sym->ts.type != BT_CLASS && init->ts.type != BT_CLASS
+         && !sym->attr.proc_pointer 
          && gfc_check_assign_symbol (sym, init) == FAILURE)
        return FAILURE;
 
@@ -1265,20 +1370,25 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
              int clen;
              /* If there are multiple CHARACTER variables declared on the
                 same line, we don't want them to share the same length.  */
-             sym->ts.u.cl = gfc_new_charlen (gfc_current_ns);
+             sym->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
 
              if (sym->attr.flavor == FL_PARAMETER)
                {
                  if (init->expr_type == EXPR_CONSTANT)
                    {
                      clen = init->value.character.length;
-                     sym->ts.u.cl->length = gfc_int_expr (clen);
+                     sym->ts.u.cl->length
+                               = gfc_get_int_expr (gfc_default_integer_kind,
+                                                   NULL, clen);
                    }
                  else if (init->expr_type == EXPR_ARRAY)
                    {
-                     gfc_expr *p = init->value.constructor->expr;
-                     clen = p->value.character.length;
-                     sym->ts.u.cl->length = gfc_int_expr (clen);
+                     gfc_constructor *c;
+                     c = gfc_constructor_first (init->value.constructor);
+                     clen = c->expr->value.character.length;
+                     sym->ts.u.cl->length
+                               = gfc_get_int_expr (gfc_default_integer_kind,
+                                                   NULL, clen);
                    }
                  else if (init->ts.u.cl && init->ts.u.cl->length)
                    sym->ts.u.cl->length =
@@ -1289,21 +1399,68 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
          else if (sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
            {
              int len = mpz_get_si (sym->ts.u.cl->length->value.integer);
-             gfc_constructor * p;
 
              if (init->expr_type == EXPR_CONSTANT)
                gfc_set_constant_character_len (len, init, -1);
              else if (init->expr_type == EXPR_ARRAY)
                {
+                 gfc_constructor *c;
+
                  /* Build a new charlen to prevent simplification from
                     deleting the length before it is resolved.  */
-                 init->ts.u.cl = gfc_new_charlen (gfc_current_ns);
+                 init->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
                  init->ts.u.cl->length = gfc_copy_expr (sym->ts.u.cl->length);
 
-                 for (p = init->value.constructor; p; p = p->next)
-                   gfc_set_constant_character_len (len, p->expr, -1);
+                 for (c = gfc_constructor_first (init->value.constructor);
+                      c; c = gfc_constructor_next (c))
+                   gfc_set_constant_character_len (len, c->expr, -1);
+               }
+           }
+       }
+
+      /* If sym is implied-shape, set its upper bounds from init.  */
+      if (sym->attr.flavor == FL_PARAMETER && sym->attr.dimension
+         && sym->as->type == AS_IMPLIED_SHAPE)
+       {
+         int dim;
+
+         if (init->rank == 0)
+           {
+             gfc_error ("Can't initialize implied-shape array at %L"
+                        " with scalar", &sym->declared_at);
+             return FAILURE;
+           }
+         gcc_assert (sym->as->rank == init->rank);
+
+         /* Shape should be present, we get an initialization expression.  */
+         gcc_assert (init->shape);
+
+         for (dim = 0; dim < sym->as->rank; ++dim)
+           {
+             int k;
+             gfc_expr* lower;
+             gfc_expr* e;
+             
+             lower = sym->as->lower[dim];
+             if (lower->expr_type != EXPR_CONSTANT)
+               {
+                 gfc_error ("Non-constant lower bound in implied-shape"
+                            " declaration at %L", &lower->where);
+                 return FAILURE;
                }
+
+             /* All dimensions must be without upper bound.  */
+             gcc_assert (!sym->as->upper[dim]);
+
+             k = lower->ts.kind;
+             e = gfc_get_constant_expr (BT_INTEGER, k, &sym->declared_at);
+             mpz_add (e->value.integer,
+                      lower->value.integer, init->shape[dim]);
+             mpz_sub_ui (e->value.integer, e->value.integer, 1);
+             sym->as->upper[dim] = e;
            }
+
+         sym->as->type = AS_EXPLICIT;
        }
 
       /* Need to check if the expression we initialized this
@@ -1325,38 +1482,27 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
          if (init->ts.is_iso_c)
            sym->ts.f90_type = init->ts.f90_type;
        }
-      
+
       /* Add initializer.  Make sure we keep the ranks sane.  */
       if (sym->attr.dimension && init->rank == 0)
        {
          mpz_t size;
          gfc_expr *array;
-         gfc_constructor *c;
          int n;
          if (sym->attr.flavor == FL_PARAMETER
                && init->expr_type == EXPR_CONSTANT
                && spec_size (sym->as, &size) == SUCCESS
                && mpz_cmp_si (size, 0) > 0)
            {
-             array = gfc_start_constructor (init->ts.type, init->ts.kind,
-                                            &init->where);
-
-             array->value.constructor = c = NULL;
+             array = gfc_get_array_expr (init->ts.type, init->ts.kind,
+                                         &init->where);
              for (n = 0; n < (int)mpz_get_si (size); n++)
-               {
-                 if (array->value.constructor == NULL)
-                   {
-                     array->value.constructor = c = gfc_get_constructor ();
-                     c->expr = init;
-                   }
-                 else
-                   {
-                     c->next = gfc_get_constructor ();
-                     c = c->next;
-                     c->expr = gfc_copy_expr (init);
-                   }
-               }
-
+               gfc_constructor_append_expr (&array->value.constructor,
+                                            n == 0
+                                               ? init
+                                               : gfc_copy_expr (init),
+                                            &init->where);
+               
              array->shape = gfc_get_shape (sym->as->rank);
              for (n = 0; n < sym->as->rank; n++)
                spec_dimen_size (sym->as, n, &array->shape[n]);
@@ -1385,10 +1531,11 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
              gfc_array_spec **as)
 {
   gfc_component *c;
+  gfc_try t = SUCCESS;
 
-  /* If the current symbol is of the same derived type that we're
+  /* F03:C438/C439. If the current symbol is of the same derived type that we're
      constructing, it must have the pointer attribute.  */
-  if (current_ts.type == BT_DERIVED
+  if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
       && current_ts.u.derived == gfc_current_block ()
       && current_attr.pointer == 0)
     {
@@ -1419,12 +1566,18 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
 
   c->as = *as;
   if (c->as != NULL)
-    c->attr.dimension = 1;
+    {
+      if (c->as->corank)
+       c->attr.codimension = 1;
+      if (c->as->rank)
+       c->attr.dimension = 1;
+    }
   *as = NULL;
 
   /* Should this ever get more complicated, combine with similar section
      in add_init_expr_to_sym into a separate function.  */
-  if (c->ts.type == BT_CHARACTER && !c->attr.pointer && c->initializer && c->ts.u.cl
+  if (c->ts.type == BT_CHARACTER && !c->attr.pointer && c->initializer
+      && c->ts.u.cl
       && c->ts.u.cl->length && c->ts.u.cl->length->expr_type == EXPR_CONSTANT)
     {
       int len;
@@ -1440,15 +1593,14 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
       else if (mpz_cmp (c->ts.u.cl->length->value.integer,
                        c->initializer->ts.u.cl->length->value.integer))
        {
-         bool has_ts;
-         gfc_constructor *ctor = c->initializer->value.constructor;
-
-         has_ts = (c->initializer->ts.u.cl
-                   && c->initializer->ts.u.cl->length_from_typespec);
+         gfc_constructor *ctor;
+         ctor = gfc_constructor_first (c->initializer->value.constructor);
 
          if (ctor)
            {
              int first_len;
+             bool has_ts = (c->initializer->ts.u.cl
+                            && c->initializer->ts.u.cl->length_from_typespec);
 
              /* Remember the length of the first element for checking
                 that all elements *in the constructor* have the same
@@ -1457,11 +1609,12 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
              gcc_assert (ctor->expr->ts.type == BT_CHARACTER);
              first_len = ctor->expr->value.character.length;
 
-             for (; ctor; ctor = ctor->next)
+             for ( ; ctor; ctor = gfc_constructor_next (ctor))
+               if (ctor->expr->expr_type == EXPR_CONSTANT)
                {
-                 if (ctor->expr->expr_type == EXPR_CONSTANT)
-                   gfc_set_constant_character_len (len, ctor->expr,
-                                                   has_ts ? -1 : first_len);
+                 gfc_set_constant_character_len (len, ctor->expr,
+                                                 has_ts ? -1 : first_len);
+                 ctor->expr->ts.u.cl->length = gfc_copy_expr (c->ts.u.cl->length);
                }
            }
        }
@@ -1469,15 +1622,7 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
 
   /* Check array components.  */
   if (!c->attr.dimension)
-    {
-      if (c->attr.allocatable)
-       {
-         gfc_error ("Allocatable component at %C must be an array");
-         return FAILURE;
-       }
-      else
-       return SUCCESS;
-    }
+    goto scalar;
 
   if (c->attr.pointer)
     {
@@ -1485,7 +1630,7 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
        {
          gfc_error ("Pointer array component of structure at %C must have a "
                     "deferred shape");
-         return FAILURE;
+         t = FAILURE;
        }
     }
   else if (c->attr.allocatable)
@@ -1494,7 +1639,7 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
        {
          gfc_error ("Allocatable component of structure at %C must have a "
                     "deferred shape");
-         return FAILURE;
+         t = FAILURE;
        }
     }
   else
@@ -1503,11 +1648,20 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
        {
          gfc_error ("Array component of structure at %C must have an "
                     "explicit shape");
-         return FAILURE;
+         t = FAILURE;
        }
     }
 
-  return SUCCESS;
+scalar:
+  if (c->ts.type == BT_CLASS)
+    {
+      bool delayed = (gfc_state_stack->sym == c->ts.u.derived)
+                    || (!c->ts.u.derived->components
+                        && !c->ts.u.derived->attr.zero_comp);
+      return gfc_build_class_symbol (&c->ts, &c->attr, &c->as, delayed);
+    }
+
+  return t;
 }
 
 
@@ -1517,7 +1671,6 @@ match
 gfc_match_null (gfc_expr **result)
 {
   gfc_symbol *sym;
-  gfc_expr *e;
   match m;
 
   m = gfc_match (" null ( )");
@@ -1539,17 +1692,80 @@ gfc_match_null (gfc_expr **result)
          || gfc_add_function (&sym->attr, sym->name, NULL) == FAILURE))
     return MATCH_ERROR;
 
-  e = gfc_get_expr ();
-  e->where = gfc_current_locus;
-  e->expr_type = EXPR_NULL;
-  e->ts.type = BT_UNKNOWN;
+  *result = gfc_get_null_expr (&gfc_current_locus);
+
+  return MATCH_YES;
+}
+
+
+/* Match the initialization expr for a data pointer or procedure pointer.  */
+
+static match
+match_pointer_init (gfc_expr **init, int procptr)
+{
+  match m;
+
+  if (gfc_pure (NULL) && gfc_state_stack->state != COMP_DERIVED)
+    {
+      gfc_error ("Initialization of pointer at %C is not allowed in "
+                "a PURE procedure");
+      return MATCH_ERROR;
+    }
+
+  /* Match NULL() initilization.  */
+  m = gfc_match_null (init);
+  if (m != MATCH_NO)
+    return m;
+
+  /* Match non-NULL initialization.  */
+  gfc_matching_ptr_assignment = !procptr;
+  gfc_matching_procptr_assignment = procptr;
+  m = gfc_match_rvalue (init);
+  gfc_matching_ptr_assignment = 0;
+  gfc_matching_procptr_assignment = 0;
+  if (m == MATCH_ERROR)
+    return MATCH_ERROR;
+  else if (m == MATCH_NO)
+    {
+      gfc_error ("Error in pointer initialization at %C");
+      return MATCH_ERROR;
+    }
 
-  *result = e;
+  if (!procptr)
+    gfc_resolve_expr (*init);
+  
+  if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: non-NULL pointer "
+                     "initialization at %C") == FAILURE)
+    return MATCH_ERROR;
 
   return MATCH_YES;
 }
 
 
+static gfc_try
+check_function_name (char *name)
+{
+  /* In functions that have a RESULT variable defined, the function name always
+     refers to function calls.  Therefore, the name is not allowed to appear in
+     specification statements. When checking this, be careful about
+     'hidden' procedure pointer results ('ppr@').  */
+
+  if (gfc_current_state () == COMP_FUNCTION)
+    {
+      gfc_symbol *block = gfc_current_block ();
+      if (block && block->result && block->result != block
+         && strcmp (block->result->name, "ppr@") != 0
+         && strcmp (block->name, name) == 0)
+       {
+         gfc_error ("Function name '%s' not allowed at %C", name);
+         return FAILURE;
+       }
+    }
+
+  return SUCCESS;
+}
+
+
 /* Match a variable name with an optional initializer.  When this
    subroutine is called, a variable is expected to be parsed next.
    Depending on what is happening at the moment, updates either the
@@ -1563,16 +1779,15 @@ variable_decl (int elem)
   gfc_array_spec *as;
   gfc_array_spec *cp_as; /* Extra copy for Cray Pointees.  */
   gfc_charlen *cl;
+  bool cl_deferred;
   locus var_locus;
   match m;
   gfc_try t;
   gfc_symbol *sym;
-  locus old_locus;
 
   initializer = NULL;
   as = NULL;
   cp_as = NULL;
-  old_locus = gfc_current_locus;
 
   /* When we get here, we've just matched a list of attributes and
      maybe a type and a double colon.  The next thing we expect to see
@@ -1584,24 +1799,56 @@ variable_decl (int elem)
   var_locus = gfc_current_locus;
 
   /* Now we could see the optional array spec. or character length.  */
-  m = gfc_match_array_spec (&as);
-  if (gfc_option.flag_cray_pointer && m == MATCH_YES)
-    cp_as = gfc_copy_array_spec (as);
-  else if (m == MATCH_ERROR)
+  m = gfc_match_array_spec (&as, true, true);
+  if (m == MATCH_ERROR)
     goto cleanup;
 
   if (m == MATCH_NO)
     as = gfc_copy_array_spec (current_as);
+  else if (current_as)
+    merge_array_spec (current_as, as, true);
+
+  if (gfc_option.flag_cray_pointer)
+    cp_as = gfc_copy_array_spec (as);
+
+  /* At this point, we know for sure if the symbol is PARAMETER and can thus
+     determine (and check) whether it can be implied-shape.  If it
+     was parsed as assumed-size, change it because PARAMETERs can not
+     be assumed-size.  */
+  if (as)
+    {
+      if (as->type == AS_IMPLIED_SHAPE && current_attr.flavor != FL_PARAMETER)
+       {
+         m = MATCH_ERROR;
+         gfc_error ("Non-PARAMETER symbol '%s' at %L can't be implied-shape",
+                    name, &var_locus);
+         goto cleanup;
+       }
+
+      if (as->type == AS_ASSUMED_SIZE && as->rank == 1
+         && current_attr.flavor == FL_PARAMETER)
+       as->type = AS_IMPLIED_SHAPE;
+
+      if (as->type == AS_IMPLIED_SHAPE
+         && gfc_notify_std (GFC_STD_F2008,
+                            "Fortran 2008: Implied-shape array at %L",
+                            &var_locus) == FAILURE)
+       {
+         m = MATCH_ERROR;
+         goto cleanup;
+       }
+    }
 
   char_len = NULL;
   cl = NULL;
+  cl_deferred = false;
 
   if (current_ts.type == BT_CHARACTER)
     {
-      switch (match_char_length (&char_len))
+      switch (match_char_length (&char_len, &cl_deferred))
        {
        case MATCH_YES:
-         cl = gfc_new_charlen (gfc_current_ns);
+         cl = gfc_new_charlen (gfc_current_ns, NULL);
 
          cl->length = char_len;
          break;
@@ -1613,12 +1860,14 @@ variable_decl (int elem)
              && (current_ts.u.cl->length == NULL
                  || current_ts.u.cl->length->expr_type != EXPR_CONSTANT))
            {
-             cl = gfc_new_charlen (gfc_current_ns);
+             cl = gfc_new_charlen (gfc_current_ns, NULL);
              cl->length = gfc_copy_expr (current_ts.u.cl->length);
            }
          else
            cl = current_ts.u.cl;
 
+         cl_deferred = current_ts.deferred;
+
          break;
 
        case MATCH_ERROR:
@@ -1694,7 +1943,7 @@ variable_decl (int elem)
      create a symbol for those yet.  If we fail to create the symbol,
      bail out.  */
   if (gfc_current_state () != COMP_DERIVED
-      && build_sym (name, cl, &as, &var_locus) == FAILURE)
+      && build_sym (name, cl, cl_deferred, &as, &var_locus) == FAILURE)
     {
       m = MATCH_ERROR;
       goto cleanup;
@@ -1705,7 +1954,7 @@ variable_decl (int elem)
      specified in the procedure definition, except that the interface
      may specify a procedure that is not pure if the procedure is
      defined to be pure(12.3.2).  */
-  if (current_ts.type == BT_DERIVED
+  if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
       && gfc_current_ns->proc_name
       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
       && current_ts.u.derived->ns != gfc_current_ns)
@@ -1714,26 +1963,18 @@ variable_decl (int elem)
       st = gfc_find_symtree (gfc_current_ns->sym_root, current_ts.u.derived->name);
       if (!(current_ts.u.derived->attr.imported
                && st != NULL
-               && st->n.sym == current_ts.u.derived)
+               && gfc_find_dt_in_generic (st->n.sym) == current_ts.u.derived)
            && !gfc_current_ns->has_import_set)
        {
-           gfc_error ("the type of '%s' at %C has not been declared within the "
+           gfc_error ("The type of '%s' at %C has not been declared within the "
                       "interface", name);
            m = MATCH_ERROR;
            goto cleanup;
        }
     }
-
-  /* In functions that have a RESULT variable defined, the function
-     name always refers to function calls.  Therefore, the name is
-     not allowed to appear in specification statements.  */
-  if (gfc_current_state () == COMP_FUNCTION
-      && gfc_current_block () != NULL
-      && gfc_current_block ()->result != NULL
-      && gfc_current_block ()->result != gfc_current_block ()
-      && strcmp (gfc_current_block ()->name, name) == 0)
+    
+  if (check_function_name (name) == FAILURE)
     {
-      gfc_error ("Function name '%s' not allowed at %C", name);
       m = MATCH_ERROR;
       goto cleanup;
     }
@@ -1769,23 +2010,9 @@ variable_decl (int elem)
              goto cleanup;
            }
 
-         m = gfc_match_null (&initializer);
-         if (m == MATCH_NO)
-           {
-             gfc_error ("Pointer initialization requires a NULL() at %C");
-             m = MATCH_ERROR;
-           }
-
-         if (gfc_pure (NULL))
-           {
-             gfc_error ("Initialization of pointer at %C is not allowed in "
-                        "a PURE procedure");
-             m = MATCH_ERROR;
-           }
-
+         m = match_pointer_init (&initializer, 0);
          if (m != MATCH_YES)
            goto cleanup;
-
        }
       else if (gfc_match_char ('=') == MATCH_YES)
        {
@@ -1804,7 +2031,8 @@ variable_decl (int elem)
              m = MATCH_ERROR;
            }
 
-         if (current_attr.flavor != FL_PARAMETER && gfc_pure (NULL))
+         if (current_attr.flavor != FL_PARAMETER && gfc_pure (NULL)
+             && gfc_state_stack->state != COMP_DERIVED)
            {
              gfc_error ("Initialization of variable at %C is not allowed in "
                         "a PURE procedure");
@@ -1878,6 +2106,33 @@ gfc_match_old_kind_spec (gfc_typespec *ts)
          return MATCH_ERROR;
        }
       ts->kind /= 2;
+
+    }
+
+  if (ts->type == BT_INTEGER && ts->kind == 4 && gfc_option.flag_integer4_kind == 8)
+    ts->kind = 8;
+
+  if (ts->type == BT_REAL || ts->type == BT_COMPLEX)
+    {
+      if (ts->kind == 4)
+       {
+         if (gfc_option.flag_real4_kind == 8)
+           ts->kind =  8;
+         if (gfc_option.flag_real4_kind == 10)
+           ts->kind = 10;
+         if (gfc_option.flag_real4_kind == 16)
+           ts->kind = 16;
+       }
+
+      if (ts->kind == 8)
+       {
+         if (gfc_option.flag_real8_kind == 4)
+           ts->kind = 4;
+         if (gfc_option.flag_real8_kind == 10)
+           ts->kind = 10;
+         if (gfc_option.flag_real8_kind == 16)
+           ts->kind = 16;
+       }
     }
 
   if (gfc_validate_kind (ts->type, ts->kind, true) < 0)
@@ -2023,7 +2278,33 @@ kind_expr:
 
   if(m == MATCH_ERROR)
      gfc_current_locus = where;
-  
+
+  if (ts->type == BT_INTEGER && ts->kind == 4 && gfc_option.flag_integer4_kind == 8)
+    ts->kind =  8;
+
+  if (ts->type == BT_REAL || ts->type == BT_COMPLEX)
+    {
+      if (ts->kind == 4)
+       {
+         if (gfc_option.flag_real4_kind == 8)
+           ts->kind =  8;
+         if (gfc_option.flag_real4_kind == 10)
+           ts->kind = 10;
+         if (gfc_option.flag_real4_kind == 16)
+           ts->kind = 16;
+       }
+
+      if (ts->kind == 8)
+       {
+         if (gfc_option.flag_real8_kind == 4)
+           ts->kind = 4;
+         if (gfc_option.flag_real8_kind == 10)
+           ts->kind = 10;
+         if (gfc_option.flag_real8_kind == 16)
+           ts->kind = 16;
+       }
+    }
+
   /* Return what we know from the test(s).  */
   return m;
 
@@ -2104,26 +2385,29 @@ no_match:
   return m;
 }
 
+
 /* Match the various kind/length specifications in a CHARACTER
    declaration.  We don't return MATCH_NO.  */
 
-static match
-match_char_spec (gfc_typespec *ts)
+match
+gfc_match_char_spec (gfc_typespec *ts)
 {
   int kind, seen_length, is_iso_c;
   gfc_charlen *cl;
   gfc_expr *len;
   match m;
+  bool deferred;
 
   len = NULL;
   seen_length = 0;
   kind = 0;
   is_iso_c = 0;
+  deferred = false;
 
   /* Try the old-style specification first.  */
   old_char_selector = 0;
 
-  m = match_char_length (&len);
+  m = match_char_length (&len, &deferred);
   if (m != MATCH_NO)
     {
       if (m == MATCH_YES)
@@ -2152,7 +2436,7 @@ match_char_spec (gfc_typespec *ts)
       if (gfc_match (" , len =") == MATCH_NO)
        goto rparen;
 
-      m = char_len_param_value (&len);
+      m = char_len_param_value (&len, &deferred);
       if (m == MATCH_NO)
        goto syntax;
       if (m == MATCH_ERROR)
@@ -2165,7 +2449,7 @@ match_char_spec (gfc_typespec *ts)
   /* Try to match "LEN = <len-param>" or "LEN = <len-param>, KIND = <int>".  */
   if (gfc_match (" len =") == MATCH_YES)
     {
-      m = char_len_param_value (&len);
+      m = char_len_param_value (&len, &deferred);
       if (m == MATCH_NO)
        goto syntax;
       if (m == MATCH_ERROR)
@@ -2185,7 +2469,7 @@ match_char_spec (gfc_typespec *ts)
     }
 
   /* Try to match ( <len-param> ) or ( <len-param> , [ KIND = ] <int> ).  */
-  m = char_len_param_value (&len);
+  m = char_len_param_value (&len, &deferred);
   if (m == MATCH_NO)
     goto syntax;
   if (m == MATCH_ERROR)
@@ -2235,15 +2519,16 @@ done:
     }
 
   /* Do some final massaging of the length values.  */
-  cl = gfc_new_charlen (gfc_current_ns);
+  cl = gfc_new_charlen (gfc_current_ns, NULL);
 
   if (seen_length == 0)
-    cl->length = gfc_int_expr (1);
+    cl->length = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
   else
     cl->length = len;
 
   ts->u.cl = cl;
   ts->kind = kind == 0 ? gfc_default_character_kind : kind;
+  ts->deferred = deferred;
 
   /* We have to know if it was a c interoperable kind so we can
      do accurate type checking of bind(c) procs, etc.  */
@@ -2266,8 +2551,8 @@ done:
 }
 
 
-/* Matches a type specification.  If successful, sets the ts structure
-   to the matched specification.  This is necessary for FUNCTION and
+/* Matches a declaration-type-spec (F03:R502).  If successful, sets the ts
+   structure to the matched specification.  This is necessary for FUNCTION and
    IMPLICIT statements.
 
    If implicit_flag is nonzero, then we don't check for the optional
@@ -2275,13 +2560,14 @@ done:
    statement correctly.  */
 
 match
-gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
+gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
-  gfc_symbol *sym;
+  gfc_symbol *sym, *dt_sym;
   match m;
   char c;
-  bool seen_deferred_kind;
+  bool seen_deferred_kind, matched_type;
+  const char *dt_name;
 
   /* A belt and braces check that the typespec is correctly being treated
      as a deferred characteristic association.  */
@@ -2293,11 +2579,11 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
     ts->kind = -1;
 
   /* Clear the current binding label, in case one is given.  */
-  curr_binding_label[0] = '\0';
+  curr_binding_label = NULL;
 
   if (gfc_match (" byte") == MATCH_YES)
     {
-      if (gfc_notify_std(GFC_STD_GNU, "Extension: BYTE type at %C")
+      if (gfc_notify_std (GFC_STD_GNU, "Extension: BYTE type at %C")
          == FAILURE)
        return MATCH_ERROR;
 
@@ -2313,47 +2599,88 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
       return MATCH_YES;
     }
 
-  if (gfc_match (" integer") == MATCH_YES)
+
+  m = gfc_match (" type ( %n", name);
+  matched_type = (m == MATCH_YES);
+  
+  if ((matched_type && strcmp ("integer", name) == 0)
+      || (!matched_type && gfc_match (" integer") == MATCH_YES))
     {
       ts->type = BT_INTEGER;
       ts->kind = gfc_default_integer_kind;
       goto get_kind;
     }
 
-  if (gfc_match (" character") == MATCH_YES)
+  if ((matched_type && strcmp ("character", name) == 0)
+      || (!matched_type && gfc_match (" character") == MATCH_YES))
     {
+      if (matched_type
+         && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+                         "intrinsic-type-spec at %C") == FAILURE)
+       return MATCH_ERROR;
+
       ts->type = BT_CHARACTER;
       if (implicit_flag == 0)
-       return match_char_spec (ts);
+       m = gfc_match_char_spec (ts);
       else
-       return MATCH_YES;
+       m = MATCH_YES;
+
+      if (matched_type && m == MATCH_YES && gfc_match_char (')') != MATCH_YES)
+       m = MATCH_ERROR;
+
+      return m;
     }
 
-  if (gfc_match (" real") == MATCH_YES)
+  if ((matched_type && strcmp ("real", name) == 0)
+      || (!matched_type && gfc_match (" real") == MATCH_YES))
     {
       ts->type = BT_REAL;
       ts->kind = gfc_default_real_kind;
       goto get_kind;
     }
 
-  if (gfc_match (" double precision") == MATCH_YES)
+  if ((matched_type
+       && (strcmp ("doubleprecision", name) == 0
+          || (strcmp ("double", name) == 0
+              && gfc_match (" precision") == MATCH_YES)))
+      || (!matched_type && gfc_match (" double precision") == MATCH_YES))
     {
+      if (matched_type
+         && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+                         "intrinsic-type-spec at %C") == FAILURE)
+       return MATCH_ERROR;
+      if (matched_type && gfc_match_char (')') != MATCH_YES)
+       return MATCH_ERROR;
+
       ts->type = BT_REAL;
       ts->kind = gfc_default_double_kind;
       return MATCH_YES;
     }
 
-  if (gfc_match (" complex") == MATCH_YES)
+  if ((matched_type && strcmp ("complex", name) == 0)
+      || (!matched_type && gfc_match (" complex") == MATCH_YES))
     {
       ts->type = BT_COMPLEX;
       ts->kind = gfc_default_complex_kind;
       goto get_kind;
     }
 
-  if (gfc_match (" double complex") == MATCH_YES)
+  if ((matched_type
+       && (strcmp ("doublecomplex", name) == 0
+          || (strcmp ("double", name) == 0
+              && gfc_match (" complex") == MATCH_YES)))
+      || (!matched_type && gfc_match (" double complex") == MATCH_YES))
     {
-      if (gfc_notify_std (GFC_STD_GNU, "DOUBLE COMPLEX at %C does not "
-                         "conform to the Fortran 95 standard") == FAILURE)
+      if (gfc_notify_std (GFC_STD_GNU, "Extension: DOUBLE COMPLEX at %C")
+         == FAILURE)
+       return MATCH_ERROR;
+
+      if (matched_type
+         && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+                         "intrinsic-type-spec at %C") == FAILURE)
+       return MATCH_ERROR;
+
+      if (matched_type && gfc_match_char (')') != MATCH_YES)
        return MATCH_ERROR;
 
       ts->type = BT_COMPLEX;
@@ -2361,28 +2688,41 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
       return MATCH_YES;
     }
 
-  if (gfc_match (" logical") == MATCH_YES)
+  if ((matched_type && strcmp ("logical", name) == 0)
+      || (!matched_type && gfc_match (" logical") == MATCH_YES))
     {
       ts->type = BT_LOGICAL;
       ts->kind = gfc_default_logical_kind;
       goto get_kind;
     }
 
-  m = gfc_match (" type ( %n )", name);
-  if (m != MATCH_YES)
+  if (matched_type)
+    m = gfc_match_char (')');
+
+  if (m == MATCH_YES)
+    ts->type = BT_DERIVED;
+  else
     {
+      /* Match CLASS declarations.  */
+      m = gfc_match (" class ( * )");
+      if (m == MATCH_ERROR)
+       return MATCH_ERROR;
+      else if (m == MATCH_YES)
+       {
+         gfc_fatal_error ("Unlimited polymorphism at %C not yet supported");
+         return MATCH_ERROR;
+       }
+
       m = gfc_match (" class ( %n )", name);
       if (m != MATCH_YES)
        return m;
-      ts->is_class = 1;
+      ts->type = BT_CLASS;
 
-      /* TODO: Implement Polymorphism.  */
-      gfc_warning ("Polymorphic entities are not yet implemented. "
-                  "CLASS will be treated like TYPE at %C");
+      if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: CLASS statement at %C")
+                         == FAILURE)
+       return MATCH_ERROR;
     }
 
-  ts->type = BT_DERIVED;
-
   /* Defer association of the derived type until the end of the
      specification block.  However, if the derived type can be
      found, add it to the typespec.  */  
@@ -2391,61 +2731,137 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
       ts->u.derived = NULL;
       if (gfc_current_state () != COMP_INTERFACE
            && !gfc_find_symbol (name, NULL, 1, &sym) && sym)
-       ts->u.derived = sym;
+       {
+         sym = gfc_find_dt_in_generic (sym);
+         ts->u.derived = sym;
+       }
       return MATCH_YES;
     }
 
   /* Search for the name but allow the components to be defined later.  If
      type = -1, this typespec has been seen in a function declaration but
-     the type could not be accessed at that point.  */
+     the type could not be accessed at that point.  The actual derived type is
+     stored in a symtree with the first letter of the name captialized; the
+     symtree with the all lower-case name contains the associated
+     generic function.  */
+  dt_name = gfc_get_string ("%c%s",
+                           (char) TOUPPER ((unsigned char) name[0]),
+                           (const char*)&name[1]);
   sym = NULL;
-  if (ts->kind != -1 && gfc_get_ha_symbol (name, &sym))
+  dt_sym = NULL;
+  if (ts->kind != -1)
     {
-      gfc_error ("Type name '%s' at %C is ambiguous", name);
-      return MATCH_ERROR;
+      gfc_get_ha_symbol (name, &sym);
+      if (sym->generic && gfc_find_symbol (dt_name, NULL, 0, &dt_sym))
+       {
+         gfc_error ("Type name '%s' at %C is ambiguous", name);
+         return MATCH_ERROR;
+       }
+      if (sym->generic && !dt_sym)
+       dt_sym = gfc_find_dt_in_generic (sym);
     }
   else if (ts->kind == -1)
     {
       int iface = gfc_state_stack->previous->state != COMP_INTERFACE
                    || gfc_current_ns->has_import_set;
-      if (gfc_find_symbol (name, NULL, iface, &sym))
+      gfc_find_symbol (name, NULL, iface, &sym);
+      if (sym && sym->generic && gfc_find_symbol (dt_name, NULL, 1, &dt_sym))
        {       
          gfc_error ("Type name '%s' at %C is ambiguous", name);
          return MATCH_ERROR;
        }
+      if (sym && sym->generic && !dt_sym)
+       dt_sym = gfc_find_dt_in_generic (sym);
 
       ts->kind = 0;
       if (sym == NULL)
        return MATCH_NO;
     }
 
-  if (sym->attr.flavor != FL_DERIVED
-      && gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE)
-    return MATCH_ERROR;
+  if ((sym->attr.flavor != FL_UNKNOWN
+       && !(sym->attr.flavor == FL_PROCEDURE && sym->attr.generic))
+      || sym->attr.subroutine)
+    {
+      gfc_error ("Type name '%s' at %C conflicts with previously declared "
+                "entity at %L, which has the same name", name,
+                &sym->declared_at);
+      return MATCH_ERROR;
+    }
 
   gfc_set_sym_referenced (sym);
-  ts->u.derived = sym;
+  if (!sym->attr.generic
+      && gfc_add_generic (&sym->attr, sym->name, NULL) == FAILURE)
+    return MATCH_ERROR;
+
+  if (!sym->attr.function
+      && gfc_add_function (&sym->attr, sym->name, NULL) == FAILURE)
+    return MATCH_ERROR;
+
+  if (!dt_sym)
+    {
+      gfc_interface *intr, *head;
+
+      /* Use upper case to save the actual derived-type symbol.  */
+      gfc_get_symbol (dt_name, NULL, &dt_sym);
+      dt_sym->name = gfc_get_string (sym->name);
+      head = sym->generic;
+      intr = gfc_get_interface ();
+      intr->sym = dt_sym;
+      intr->where = gfc_current_locus;
+      intr->next = head;
+      sym->generic = intr;
+      sym->attr.if_source = IFSRC_DECL;
+    }
+
+  gfc_set_sym_referenced (dt_sym);
+
+  if (dt_sym->attr.flavor != FL_DERIVED
+      && gfc_add_flavor (&dt_sym->attr, FL_DERIVED, sym->name, NULL)
+                        == FAILURE)
+    return MATCH_ERROR;
+
+  ts->u.derived = dt_sym;
 
   return MATCH_YES;
 
 get_kind:
+  if (matched_type
+      && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+                        "intrinsic-type-spec at %C") == FAILURE)
+    return MATCH_ERROR;
+
   /* For all types except double, derived and character, look for an
      optional kind specifier.  MATCH_NO is actually OK at this point.  */
   if (implicit_flag == 1)
-    return MATCH_YES;
-
-  if (gfc_current_form == FORM_FREE)
     {
-      c = gfc_peek_ascii_char();
-      if (!gfc_is_whitespace(c) && c != '*' && c != '('
-         && c != ':' && c != ',')
-       return MATCH_NO;
-    }
+       if (matched_type && gfc_match_char (')') != MATCH_YES)
+         return MATCH_ERROR;
+
+       return MATCH_YES;
+    }
+
+  if (gfc_current_form == FORM_FREE)
+    {
+      c = gfc_peek_ascii_char ();
+      if (!gfc_is_whitespace (c) && c != '*' && c != '('
+         && c != ':' && c != ',')
+        {
+         if (matched_type && c == ')')
+           {
+             gfc_next_ascii_char ();
+             return MATCH_YES;
+           }
+         return MATCH_NO;
+       }
+    }
 
   m = gfc_match_kind_spec (ts, false);
   if (m == MATCH_NO && ts->type != BT_CHARACTER)
     m = gfc_match_old_kind_spec (ts);
 
+  if (matched_type && gfc_match_char (')') != MATCH_YES)
+    return MATCH_ERROR;
+
   /* Defer association of the KIND expression of function results
      until after USE and IMPORT statements.  */
   if ((gfc_current_state () == COMP_NONE && gfc_error_flag_test ())
@@ -2598,7 +3014,7 @@ gfc_match_implicit (void)
       gfc_clear_new_implicit ();
 
       /* A basic type is mandatory here.  */
-      m = gfc_match_type_spec (&ts, 1);
+      m = gfc_match_decl_type_spec (&ts, 1);
       if (m == MATCH_ERROR)
        goto error;
       if (m == MATCH_NO)
@@ -2618,8 +3034,9 @@ gfc_match_implicit (void)
              if (ts.type == BT_CHARACTER && !ts.u.cl)
                {
                  ts.kind = gfc_default_character_kind;
-                 ts.u.cl = gfc_new_charlen (gfc_current_ns);
-                 ts.u.cl->length = gfc_int_expr (1);
+                 ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
+                 ts.u.cl->length = gfc_get_int_expr (gfc_default_integer_kind,
+                                                     NULL, 1);
                }
 
              /* Record the Successful match.  */
@@ -2636,7 +3053,7 @@ gfc_match_implicit (void)
 
       /* Last chance -- check <TYPE> <SELECTOR> (<RANGE>).  */
       if (ts.type == BT_CHARACTER)
-       m = match_char_spec (&ts);
+       m = gfc_match_char_spec (&ts);
       else
        {
          m = gfc_match_kind_spec (&ts, false);
@@ -2716,6 +3133,7 @@ gfc_match_import (void)
 
   for(;;)
     {
+      sym = NULL;
       m = gfc_match (" %n", name);
       switch (m)
        {
@@ -2726,7 +3144,7 @@ gfc_match_import (void)
               gfc_error ("Type name '%s' at %C is ambiguous", name);
               return MATCH_ERROR;
            }
-         else if (gfc_current_ns->proc_name->ns->parent !=  NULL
+         else if (!sym && gfc_current_ns->proc_name->ns->parent !=  NULL
                   && gfc_find_symbol (name,
                                       gfc_current_ns->proc_name->ns->parent,
                                       1, &sym))
@@ -2754,6 +3172,20 @@ gfc_match_import (void)
          sym->refs++;
          sym->attr.imported = 1;
 
+         if (sym->attr.generic && (sym = gfc_find_dt_in_generic (sym)))
+           {
+             /* The actual derived type is stored in a symtree with the first
+                letter of the name captialized; the symtree with the all
+                lower-case name contains the associated generic function. */
+             st = gfc_new_symtree (&gfc_current_ns->sym_root,
+                       gfc_get_string ("%c%s",
+                               (char) TOUPPER ((unsigned char) sym->name[0]),
+                               &sym->name[1]));
+             st->n.sym = sym;
+             sym->refs++;
+             sym->attr.imported = 1;
+           }
+
          goto next_item;
 
        case MATCH_NO:
@@ -2813,8 +3245,8 @@ match_attr_spec (void)
     DECL_IN, DECL_OUT, DECL_INOUT, DECL_INTRINSIC, DECL_OPTIONAL,
     DECL_PARAMETER, DECL_POINTER, DECL_PROTECTED, DECL_PRIVATE,
     DECL_PUBLIC, DECL_SAVE, DECL_TARGET, DECL_VALUE, DECL_VOLATILE,
-    DECL_IS_BIND_C, DECL_NONE,
-    GFC_DECL_END /* Sentinel */
+    DECL_IS_BIND_C, DECL_CODIMENSION, DECL_ASYNCHRONOUS, DECL_CONTIGUOUS,
+    DECL_NONE, GFC_DECL_END /* Sentinel */
   }
   decl_types;
 
@@ -2858,8 +3290,25 @@ match_attr_spec (void)
          switch (gfc_peek_ascii_char ())
            {
            case 'a':
-             if (match_string_p ("allocatable"))
-               d = DECL_ALLOCATABLE;
+             gfc_next_ascii_char ();
+             switch (gfc_next_ascii_char ())
+               {
+               case 'l':
+                 if (match_string_p ("locatable"))
+                   {
+                     /* Matched "allocatable".  */
+                     d = DECL_ALLOCATABLE;
+                   }
+                 break;
+
+               case 's':
+                 if (match_string_p ("ynchronous"))
+                   {
+                     /* Matched "asynchronous".  */
+                     d = DECL_ASYNCHRONOUS;
+                   }
+                 break;
+               }
              break;
 
            case 'b':
@@ -2871,6 +3320,27 @@ match_attr_spec (void)
                goto cleanup;
              break;
 
+           case 'c':
+             gfc_next_ascii_char ();
+             if ('o' != gfc_next_ascii_char ())
+               break;
+             switch (gfc_next_ascii_char ())
+               {
+               case 'd':
+                 if (match_string_p ("imension"))
+                   {
+                     d = DECL_CODIMENSION;
+                     break;
+                   }
+               case 'n':
+                 if (match_string_p ("tiguous"))
+                   {
+                     d = DECL_CONTIGUOUS;
+                     break;
+                   }
+               }
+             break;
+
            case 'd':
              if (match_string_p ("dimension"))
                d = DECL_DIMENSION;
@@ -3016,13 +3486,27 @@ match_attr_spec (void)
       seen[d]++;
       seen_at[d] = gfc_current_locus;
 
-      if (d == DECL_DIMENSION)
+      if (d == DECL_DIMENSION || d == DECL_CODIMENSION)
        {
-         m = gfc_match_array_spec (&current_as);
+         gfc_array_spec *as = NULL;
+
+         m = gfc_match_array_spec (&as, d == DECL_DIMENSION,
+                                   d == DECL_CODIMENSION);
+
+         if (current_as == NULL)
+           current_as = as;
+         else if (m == MATCH_YES)
+           {
+             merge_array_spec (as, current_as, false);
+             free (as);
+           }
 
          if (m == MATCH_NO)
            {
-             gfc_error ("Missing dimension specification at %C");
+             if (d == DECL_CODIMENSION)
+               gfc_error ("Missing codimension specification at %C");
+             else
+               gfc_error ("Missing dimension specification at %C");
              m = MATCH_ERROR;
            }
 
@@ -3041,6 +3525,15 @@ match_attr_spec (void)
          case DECL_ALLOCATABLE:
            attr = "ALLOCATABLE";
            break;
+         case DECL_ASYNCHRONOUS:
+           attr = "ASYNCHRONOUS";
+           break;
+         case DECL_CODIMENSION:
+           attr = "CODIMENSION";
+           break;
+         case DECL_CONTIGUOUS:
+           attr = "CONTIGUOUS";
+           break;
          case DECL_DIMENSION:
            attr = "DIMENSION";
            break;
@@ -3109,9 +3602,9 @@ match_attr_spec (void)
        continue;
 
       if (gfc_current_state () == COMP_DERIVED
-         && d != DECL_DIMENSION && d != DECL_POINTER
-         && d != DECL_PRIVATE   && d != DECL_PUBLIC
-         && d != DECL_NONE)
+         && d != DECL_DIMENSION && d != DECL_CODIMENSION
+         && d != DECL_POINTER   && d != DECL_PRIVATE
+         && d != DECL_PUBLIC && d != DECL_CONTIGUOUS && d != DECL_NONE)
        {
          if (d == DECL_ALLOCATABLE)
            {
@@ -3167,6 +3660,28 @@ match_attr_spec (void)
          t = gfc_add_allocatable (&current_attr, &seen_at[d]);
          break;
 
+       case DECL_ASYNCHRONOUS:
+         if (gfc_notify_std (GFC_STD_F2003,
+                             "Fortran 2003: ASYNCHRONOUS attribute at %C")
+             == FAILURE)
+           t = FAILURE;
+         else
+           t = gfc_add_asynchronous (&current_attr, NULL, &seen_at[d]);
+         break;
+
+       case DECL_CODIMENSION:
+         t = gfc_add_codimension (&current_attr, NULL, &seen_at[d]);
+         break;
+
+       case DECL_CONTIGUOUS:
+         if (gfc_notify_std (GFC_STD_F2008,
+                             "Fortran 2008: CONTIGUOUS attribute at %C")
+             == FAILURE)
+           t = FAILURE;
+         else
+           t = gfc_add_contiguous (&current_attr, NULL, &seen_at[d]);
+         break;
+
        case DECL_DIMENSION:
          t = gfc_add_dimension (&current_attr, NULL, &seen_at[d]);
          break;
@@ -3231,7 +3746,7 @@ match_attr_spec (void)
          break;
 
        case DECL_SAVE:
-         t = gfc_add_save (&current_attr, NULL, &seen_at[d]);
+         t = gfc_add_save (&current_attr, SAVE_EXPLICIT, NULL, &seen_at[d]);
          break;
 
        case DECL_TARGET:
@@ -3271,6 +3786,11 @@ match_attr_spec (void)
        }
     }
 
+  /* Since Fortran 2008 module variables implicitly have the SAVE attribute.  */
+  if (gfc_current_state () == COMP_MODULE && !current_attr.save
+      && (gfc_option.allow_std & GFC_STD_F2008) != 0)
+    current_attr.save = SAVE_IMPLICIT;
+
   colon_seen = 1;
   return MATCH_YES;
 
@@ -3288,8 +3808,9 @@ cleanup:
    (J3/04-007, section 15.4.1).  If a binding label was given and
    there is more than one argument (num_idents), it is an error.  */
 
-gfc_try
-set_binding_label (char *dest_label, const char *sym_name, int num_idents)
+static gfc_try
+set_binding_label (const char **dest_label, const char *sym_name, 
+                  int num_idents)
 {
   if (num_idents > 1 && has_name_equals)
     {
@@ -3298,17 +3819,15 @@ set_binding_label (char *dest_label, const char *sym_name, int num_idents)
       return FAILURE;
     }
 
-  if (curr_binding_label[0] != '\0')
-    {
-      /* Binding label given; store in temp holder til have sym.  */
-      strcpy (dest_label, curr_binding_label);
-    }
+  if (curr_binding_label)
+    /* Binding label given; store in temp holder til have sym.  */
+    *dest_label = curr_binding_label;
   else
     {
       /* No binding label given, and the NAME= specifier did not exist,
          which means there was no NAME="".  */
       if (sym_name != NULL && has_name_equals == 0)
-        strcpy (dest_label, sym_name);
+        *dest_label = IDENTIFIER_POINTER (get_identifier (sym_name));
     }
    
   return SUCCESS;
@@ -3329,10 +3848,13 @@ set_com_block_bind_c (gfc_common_head *com_block, int is_bind_c)
 /* Verify that the given gfc_typespec is for a C interoperable type.  */
 
 gfc_try
-verify_c_interop (gfc_typespec *ts)
+gfc_verify_c_interop (gfc_typespec *ts)
 {
   if (ts->type == BT_DERIVED && ts->u.derived != NULL)
-    return (ts->u.derived->ts.is_c_interop ? SUCCESS : FAILURE);
+    return (ts->u.derived->ts.is_c_interop || ts->u.derived->attr.is_bind_c)
+          ? SUCCESS : FAILURE;
+  else if (ts->type == BT_CLASS)
+    return FAILURE;
   else if (ts->is_c_interop != 1)
     return FAILURE;
   
@@ -3405,7 +3927,7 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
      the given ts (current_ts), so look in both.  */
   if (tmp_sym->ts.type != BT_UNKNOWN || ts->type != BT_UNKNOWN) 
     {
-      if (verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
+      if (gfc_verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
        {
          /* See if we're dealing with a sym in a common block or not.  */
          if (is_in_common == 1)
@@ -3485,7 +4007,7 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
   /* See if the symbol has been marked as private.  If it has, make sure
      there is no binding label and warn the user if there is one.  */
   if (tmp_sym->attr.access == ACCESS_PRIVATE
-      && tmp_sym->binding_label[0] != '\0')
+      && tmp_sym->binding_label)
       /* Use gfc_warning_now because we won't say that the symbol fails
         just because of this.  */
       gfc_warning_now ("Symbol '%s' at %L is marked PRIVATE but has been "
@@ -3511,7 +4033,7 @@ set_verify_bind_c_sym (gfc_symbol *tmp_sym, int num_idents)
   /* Set the is_bind_c bit in symbol_attribute.  */
   gfc_add_is_bind_c (&(tmp_sym->attr), tmp_sym->name, &gfc_current_locus, 0);
 
-  if (set_binding_label (tmp_sym->binding_label, tmp_sym->name, 
+  if (set_binding_label (&tmp_sym->binding_label, tmp_sym->name,
                         num_idents) != SUCCESS)
     return FAILURE;
 
@@ -3528,7 +4050,8 @@ set_verify_bind_c_com_block (gfc_common_head *com_block, int num_idents)
   gfc_try retval = SUCCESS;
   
   /* destLabel, common name, typespec (which may have binding label).  */
-  if (set_binding_label (com_block->binding_label, com_block->name, num_idents)
+  if (set_binding_label (&com_block->binding_label, com_block->name, 
+                        num_idents)
       != SUCCESS)
     return FAILURE;
 
@@ -3639,7 +4162,7 @@ gfc_match_bind_c_stmt (void)
   /* This may not be necessary.  */
   gfc_clear_ts (ts);
   /* Clear the temporary binding label holder.  */
-  curr_binding_label[0] = '\0';
+  curr_binding_label = NULL;
 
   /* Look for the bind(c).  */
   found_match = gfc_match_bind_c (NULL, true);
@@ -3674,11 +4197,12 @@ gfc_match_data_decl (void)
 
   num_idents_on_line = 0;
   
-  m = gfc_match_type_spec (&current_ts, 0);
+  m = gfc_match_decl_type_spec (&current_ts, 0);
   if (m != MATCH_YES)
     return m;
 
-  if (current_ts.type == BT_DERIVED && gfc_current_state () != COMP_DERIVED)
+  if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
+       && gfc_current_state () != COMP_DERIVED)
     {
       sym = gfc_use_derived (current_ts.u.derived);
 
@@ -3698,7 +4222,8 @@ gfc_match_data_decl (void)
       goto cleanup;
     }
 
-  if (current_ts.type == BT_DERIVED && current_ts.u.derived->components == NULL
+  if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
+      && current_ts.u.derived->components == NULL
       && !current_ts.u.derived->attr.zero_comp)
     {
 
@@ -3770,45 +4295,81 @@ match
 gfc_match_prefix (gfc_typespec *ts)
 {
   bool seen_type;
+  bool seen_impure;
+  bool found_prefix;
 
   gfc_clear_attr (&current_attr);
-  seen_type = 0;
+  seen_type = false;
+  seen_impure = false;
 
   gcc_assert (!gfc_matching_prefix);
   gfc_matching_prefix = true;
 
-loop:
-  if (!seen_type && ts != NULL
-      && gfc_match_type_spec (ts, 0) == MATCH_YES
-      && gfc_match_space () == MATCH_YES)
+  do
     {
+      found_prefix = false;
 
-      seen_type = 1;
-      goto loop;
-    }
+      if (!seen_type && ts != NULL
+         && gfc_match_decl_type_spec (ts, 0) == MATCH_YES
+         && gfc_match_space () == MATCH_YES)
+       {
 
-  if (gfc_match ("elemental% ") == MATCH_YES)
-    {
-      if (gfc_add_elemental (&current_attr, NULL) == FAILURE)
-       goto error;
+         seen_type = true;
+         found_prefix = true;
+       }
+
+      if (gfc_match ("elemental% ") == MATCH_YES)
+       {
+         if (gfc_add_elemental (&current_attr, NULL) == FAILURE)
+           goto error;
+
+         found_prefix = true;
+       }
 
-      goto loop;
+      if (gfc_match ("pure% ") == MATCH_YES)
+       {
+         if (gfc_add_pure (&current_attr, NULL) == FAILURE)
+           goto error;
+
+         found_prefix = true;
+       }
+
+      if (gfc_match ("recursive% ") == MATCH_YES)
+       {
+         if (gfc_add_recursive (&current_attr, NULL) == FAILURE)
+           goto error;
+
+         found_prefix = true;
+       }
+
+      /* IMPURE is a somewhat special case, as it needs not set an actual
+        attribute but rather only prevents ELEMENTAL routines from being
+        automatically PURE.  */
+      if (gfc_match ("impure% ") == MATCH_YES)
+       {
+         if (gfc_notify_std (GFC_STD_F2008,
+                             "Fortran 2008: IMPURE procedure at %C")
+               == FAILURE)
+           goto error;
+
+         seen_impure = true;
+         found_prefix = true;
+       }
     }
+  while (found_prefix);
 
-  if (gfc_match ("pure% ") == MATCH_YES)
+  /* IMPURE and PURE must not both appear, of course.  */
+  if (seen_impure && current_attr.pure)
     {
-      if (gfc_add_pure (&current_attr, NULL) == FAILURE)
-       goto error;
-
-      goto loop;
+      gfc_error ("PURE and IMPURE must not appear both at %C");
+      goto error;
     }
 
-  if (gfc_match ("recursive% ") == MATCH_YES)
+  /* If IMPURE it not seen but the procedure is ELEMENTAL, mark it as PURE.  */
+  if (!seen_impure && current_attr.elemental && !current_attr.pure)
     {
-      if (gfc_add_recursive (&current_attr, NULL) == FAILURE)
+      if (gfc_add_pure (&current_attr, NULL) == FAILURE)
        goto error;
-
-      goto loop;
     }
 
   /* At this point, the next item is not a prefix.  */
@@ -4177,7 +4738,7 @@ match_procedure_interface (gfc_symbol **proc_if)
 
   /* Get the type spec. for the procedure interface.  */
   old_loc = gfc_current_locus;
-  m = gfc_match_type_spec (&current_ts, 0);
+  m = gfc_match_decl_type_spec (&current_ts, 0);
   gfc_gobble_whitespace ();
   if (m == MATCH_YES || (m == MATCH_NO && gfc_peek_ascii_char () == ')'))
     goto got_ts;
@@ -4309,7 +4870,8 @@ match_procedure_decl (void)
              return MATCH_ERROR;
            }
          /* Set binding label for BIND(C).  */
-         if (set_binding_label (sym->binding_label, sym->name, num) != SUCCESS)
+         if (set_binding_label (&sym->binding_label, sym->name, num) 
+             != SUCCESS)
            return MATCH_ERROR;
        }
 
@@ -4342,8 +4904,9 @@ match_procedure_decl (void)
            return MATCH_ERROR;
          sym->ts.interface = gfc_new_symbol ("", gfc_current_ns);
          sym->ts.interface->ts = current_ts;
+         sym->ts.interface->attr.flavor = FL_PROCEDURE;
          sym->ts.interface->attr.function = 1;
-         sym->attr.function = sym->ts.interface->attr.function;
+         sym->attr.function = 1;
          sym->attr.if_source = IFSRC_UNKNOWN;
        }
 
@@ -4356,20 +4919,7 @@ match_procedure_decl (void)
              goto cleanup;
            }
 
-         m = gfc_match_null (&initializer);
-         if (m == MATCH_NO)
-           {
-             gfc_error ("Pointer initialization requires a NULL() at %C");
-             m = MATCH_ERROR;
-           }
-
-         if (gfc_pure (NULL))
-           {
-             gfc_error ("Initialization of pointer at %C is not allowed in "
-                        "a PURE procedure");
-             m = MATCH_ERROR;
-           }
-
+         m = match_pointer_init (&initializer, 1);
          if (m != MATCH_YES)
            goto cleanup;
 
@@ -4448,6 +4998,10 @@ match_ppc_decl (void)
       return MATCH_ERROR;
     }
 
+  if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Procedure pointer "
+                     "component at %C") == FAILURE)
+    return MATCH_ERROR;
+
   /* Match PPC names.  */
   ts = current_ts;
   for(num=1;;num++)
@@ -4485,25 +5039,15 @@ match_ppc_decl (void)
          c->ts = ts;
          c->ts.interface = gfc_new_symbol ("", gfc_current_ns);
          c->ts.interface->ts = ts;
+         c->ts.interface->attr.flavor = FL_PROCEDURE;
          c->ts.interface->attr.function = 1;
-         c->attr.function = c->ts.interface->attr.function;
+         c->attr.function = 1;
          c->attr.if_source = IFSRC_UNKNOWN;
        }
 
       if (gfc_match (" =>") == MATCH_YES)
        {
-         m = gfc_match_null (&initializer);
-         if (m == MATCH_NO)
-           {
-             gfc_error ("Pointer initialization requires a NULL() at %C");
-             m = MATCH_ERROR;
-           }
-         if (gfc_pure (NULL))
-           {
-             gfc_error ("Initialization of pointer at %C is not allowed in "
-                        "a PURE procedure");
-             m = MATCH_ERROR;
-           }
+         m = match_pointer_init (&initializer, 1);
          if (m != MATCH_YES)
            {
              gfc_free_expr (initializer);
@@ -4583,6 +5127,7 @@ gfc_match_procedure (void)
     case COMP_MODULE:
     case COMP_SUBROUTINE:
     case COMP_FUNCTION:
+    case COMP_BLOCK:
       m = match_procedure_decl ();
       break;
     case COMP_INTERFACE:
@@ -4812,6 +5357,10 @@ gfc_match_entry (void)
   if (m != MATCH_YES)
     return m;
 
+  if (gfc_notify_std (GFC_STD_F2008_OBS, "Fortran 2008 obsolescent feature: "
+                     "ENTRY statement at %C") == FAILURE)
+    return MATCH_ERROR;
+
   state = gfc_current_state ();
   if (state != COMP_SUBROUTINE && state != COMP_FUNCTION)
     {
@@ -4840,6 +5389,7 @@ gfc_match_entry (void)
                       "an IF-THEN block");
            break;
          case COMP_DO:
+         case COMP_DO_CONCURRENT:
            gfc_error ("ENTRY statement at %C cannot appear within "
                       "a DO block");
            break;
@@ -5059,6 +5609,10 @@ gfc_match_subroutine (void)
   if (get_proc_name (name, &sym, false))
     return MATCH_ERROR;
 
+  /* Set declared_at as it might point to, e.g., a PUBLIC statement, if
+     the symbol existed before. */
+  sym->declared_at = gfc_current_locus;
+
   if (add_hidden_procptr_result (sym) == SUCCESS)
     sym = sym->result;
 
@@ -5161,7 +5715,7 @@ match
 gfc_match_bind_c (gfc_symbol *sym, bool allow_binding_name)
 {
   /* binding label, if exists */   
-  char binding_label[GFC_MAX_SYMBOL_LEN + 1];
+  const char* binding_label = NULL;
   match double_quote;
   match single_quote;
 
@@ -5169,10 +5723,6 @@ gfc_match_bind_c (gfc_symbol *sym, bool allow_binding_name)
      specifier or not.  */
   has_name_equals = 0;
 
-  /* Init the first char to nil so we can catch if we don't have
-     the label (name attr) or the symbol name yet.  */
-  binding_label[0] = '\0';
-   
   /* This much we have to be able to match, in this order, if
      there is a bind(c) label. */
   if (gfc_match (" bind ( c ") != MATCH_YES)
@@ -5207,7 +5757,7 @@ gfc_match_bind_c (gfc_symbol *sym, bool allow_binding_name)
       
       /* Grab the binding label, using functions that will not lower
         case the names automatically.  */
-      if (gfc_match_name_C (binding_label) != MATCH_YES)
+      if (gfc_match_name_C (&binding_label) != MATCH_YES)
         return MATCH_ERROR;
       
       /* Get the closing quotation.  */
@@ -5255,14 +5805,12 @@ gfc_match_bind_c (gfc_symbol *sym, bool allow_binding_name)
   /* Save the binding label to the symbol.  If sym is null, we're
      probably matching the typespec attributes of a declaration and
      haven't gotten the name yet, and therefore, no symbol yet.         */
-  if (binding_label[0] != '\0')
+  if (binding_label)
     {
       if (sym != NULL)
-      {
-       strcpy (sym->binding_label, binding_label);
-      }
+       sym->binding_label = binding_label;
       else
-       strcpy (curr_binding_label, binding_label);
+       curr_binding_label = binding_label;
     }
   else if (allow_binding_name)
     {
@@ -5271,7 +5819,7 @@ gfc_match_bind_c (gfc_symbol *sym, bool allow_binding_name)
         If name="" or allow_binding_name is false, no C binding name is
         created. */
       if (sym != NULL && sym->name != NULL && has_name_equals == 0)
-       strncpy (sym->binding_label, sym->name, strlen (sym->name) + 1);
+       sym->binding_label = IDENTIFIER_POINTER (get_identifier (sym->name));
     }
 
   if (has_name_equals && gfc_current_state () == COMP_INTERFACE
@@ -5335,8 +5883,8 @@ set_enum_kind(void)
 
 
 /* Match any of the various end-block statements.  Returns the type of
-   END to the caller.  The END INTERFACE, END IF, END DO and END
-   SELECT statements cannot be replaced by a single END statement.  */
+   END to the caller.  The END INTERFACE, END IF, END DO, END SELECT
+   and END BLOCK statements cannot be replaced by a single END statement.  */
 
 match
 gfc_match_end (gfc_statement *st)
@@ -5357,11 +5905,23 @@ gfc_match_end (gfc_statement *st)
   block_name = gfc_current_block () == NULL
             ? NULL : gfc_current_block ()->name;
 
-  if (state == COMP_CONTAINS || state == COMP_DERIVED_CONTAINS)
+  switch (state)
     {
+    case COMP_ASSOCIATE:
+    case COMP_BLOCK:
+      if (!strncmp (block_name, "block@", strlen("block@")))
+       block_name = NULL;
+      break;
+
+    case COMP_CONTAINS:
+    case COMP_DERIVED_CONTAINS:
       state = gfc_state_stack->previous->state;
       block_name = gfc_state_stack->previous->sym == NULL
                 ? NULL : gfc_state_stack->previous->sym->name;
+      break;
+
+    default:
+      break;
     }
 
   switch (state)
@@ -5410,6 +5970,18 @@ gfc_match_end (gfc_statement *st)
       eos_ok = 0;
       break;
 
+    case COMP_ASSOCIATE:
+      *st = ST_END_ASSOCIATE;
+      target = " associate";
+      eos_ok = 0;
+      break;
+
+    case COMP_BLOCK:
+      *st = ST_END_BLOCK;
+      target = " block";
+      eos_ok = 0;
+      break;
+
     case COMP_IF:
       *st = ST_ENDIF;
       target = " if";
@@ -5417,12 +5989,20 @@ gfc_match_end (gfc_statement *st)
       break;
 
     case COMP_DO:
+    case COMP_DO_CONCURRENT:
       *st = ST_ENDDO;
       target = " do";
       eos_ok = 0;
       break;
 
+    case COMP_CRITICAL:
+      *st = ST_END_CRITICAL;
+      target = " critical";
+      eos_ok = 0;
+      break;
+
     case COMP_SELECT:
+    case COMP_SELECT_TYPE:
       *st = ST_END_SELECT;
       target = " select";
       eos_ok = 0;
@@ -5456,7 +6036,14 @@ gfc_match_end (gfc_statement *st)
 
   if (gfc_match_eos () == MATCH_YES)
     {
-      if (!eos_ok)
+      if (!eos_ok && (*st == ST_END_SUBROUTINE || *st == ST_END_FUNCTION))
+       {
+         if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: END statement "
+                             "instead of %s statement at %L",
+                             gfc_ascii_statement (*st), &old_loc) == FAILURE)
+           goto cleanup;
+       }
+      else if (!eos_ok)
        {
          /* We would have required END [something].  */
          gfc_error ("%s statement expected at %L",
@@ -5479,10 +6066,11 @@ gfc_match_end (gfc_statement *st)
     {
 
       if (*st != ST_ENDDO && *st != ST_ENDIF && *st != ST_END_SELECT
-         && *st != ST_END_FORALL && *st != ST_END_WHERE)
+         && *st != ST_END_FORALL && *st != ST_END_WHERE && *st != ST_END_BLOCK
+         && *st != ST_END_ASSOCIATE && *st != ST_END_CRITICAL)
        return MATCH_YES;
 
-      if (gfc_current_block () == NULL)
+      if (!block_name)
        return MATCH_YES;
 
       gfc_error ("Expected block name of '%s' in %s statement at %C",
@@ -5560,15 +6148,25 @@ attr_decl1 (void)
   if (find_special (name, &sym, false))
     return MATCH_ERROR;
 
+  if (check_function_name (name) == FAILURE)
+    {
+      m = MATCH_ERROR;
+      goto cleanup;
+    }
+  
   var_locus = gfc_current_locus;
 
   /* Deal with possible array specification for certain attributes.  */
   if (current_attr.dimension
+      || current_attr.codimension
       || current_attr.allocatable
       || current_attr.pointer
       || current_attr.target)
     {
-      m = gfc_match_array_spec (&as);
+      m = gfc_match_array_spec (&as, !current_attr.codimension,
+                               !current_attr.dimension
+                               && !current_attr.pointer
+                               && !current_attr.target);
       if (m == MATCH_ERROR)
        goto cleanup;
 
@@ -5588,6 +6186,14 @@ attr_decl1 (void)
          goto cleanup;
        }
 
+      if (current_attr.codimension && m == MATCH_NO)
+       {
+         gfc_error ("Missing array specification at %L in CODIMENSION "
+                    "statement", &var_locus);
+         m = MATCH_ERROR;
+         goto cleanup;
+       }
+
       if ((current_attr.allocatable || current_attr.pointer)
          && (m == MATCH_YES) && (as->type != AS_DEFERRED))
        {
@@ -5597,10 +6203,30 @@ attr_decl1 (void)
        }
     }
 
-  /* Update symbol table.  DIMENSION attribute is set
-     in gfc_set_array_spec().  */
-  if (current_attr.dimension == 0
-      && gfc_copy_attr (&sym->attr, &current_attr, &var_locus) == FAILURE)
+  /* Update symbol table.  DIMENSION attribute is set in
+     gfc_set_array_spec().  For CLASS variables, this must be applied
+     to the first component, or '_data' field.  */
+  if (sym->ts.type == BT_CLASS && sym->ts.u.derived->attr.is_class)
+    {
+      if (gfc_copy_attr (&CLASS_DATA (sym)->attr, &current_attr, &var_locus)
+         == FAILURE)
+       {
+         m = MATCH_ERROR;
+         goto cleanup;
+       }
+    }
+  else
+    {
+      if (current_attr.dimension == 0 && current_attr.codimension == 0
+         && gfc_copy_attr (&sym->attr, &current_attr, &var_locus) == FAILURE)
+       {
+         m = MATCH_ERROR;
+         goto cleanup;
+       }
+    }
+    
+  if (sym->ts.type == BT_CLASS
+      && gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false) == FAILURE)
     {
       m = MATCH_ERROR;
       goto cleanup;
@@ -5697,7 +6323,7 @@ static match
 cray_pointer_decl (void)
 {
   match m;
-  gfc_array_spec *as;
+  gfc_array_spec *as = NULL;
   gfc_symbol *cptr; /* Pointer symbol.  */
   gfc_symbol *cpte; /* Pointee symbol.  */
   locus var_locus;
@@ -5766,7 +6392,7 @@ cray_pointer_decl (void)
        }
 
       /* Check for an optional array spec.  */
-      m = gfc_match_array_spec (&as);
+      m = gfc_match_array_spec (&as, true, false);
       if (m == MATCH_ERROR)
        {
          gfc_free_array_spec (as);
@@ -5845,6 +6471,13 @@ gfc_match_intent (void)
 {
   sym_intent intent;
 
+  /* This is not allowed within a BLOCK construct!  */
+  if (gfc_current_state () == COMP_BLOCK)
+    {
+      gfc_error ("INTENT is not allowed inside of BLOCK at %C");
+      return MATCH_ERROR;
+    }
+
   intent = match_intent_spec ();
   if (intent == INTENT_UNKNOWN)
     return MATCH_ERROR;
@@ -5870,6 +6503,12 @@ gfc_match_intrinsic (void)
 match
 gfc_match_optional (void)
 {
+  /* This is not allowed within a BLOCK construct!  */
+  if (gfc_current_state () == COMP_BLOCK)
+    {
+      gfc_error ("OPTIONAL is not allowed inside of BLOCK at %C");
+      return MATCH_ERROR;
+    }
 
   gfc_clear_attr (&current_attr);
   current_attr.optional = 1;
@@ -5913,6 +6552,30 @@ gfc_match_allocatable (void)
 
 
 match
+gfc_match_codimension (void)
+{
+  gfc_clear_attr (&current_attr);
+  current_attr.codimension = 1;
+
+  return attr_decl ();
+}
+
+
+match
+gfc_match_contiguous (void)
+{
+  if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: CONTIGUOUS statement at %C")
+      == FAILURE)
+    return MATCH_ERROR;
+
+  gfc_clear_attr (&current_attr);
+  current_attr.contiguous = 1;
+
+  return attr_decl ();
+}
+
+
+match
 gfc_match_dimension (void)
 {
   gfc_clear_attr (&current_attr);
@@ -5941,7 +6604,7 @@ access_attr_decl (gfc_statement st)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   interface_type type;
   gfc_user_op *uop;
-  gfc_symbol *sym;
+  gfc_symbol *sym, *dt_sym;
   gfc_intrinsic_op op;
   match m;
 
@@ -5971,13 +6634,31 @@ access_attr_decl (gfc_statement st)
                              sym->name, NULL) == FAILURE)
            return MATCH_ERROR;
 
+         if (sym->attr.generic && (dt_sym = gfc_find_dt_in_generic (sym))
+             && gfc_add_access (&dt_sym->attr,
+                                (st == ST_PUBLIC) ? ACCESS_PUBLIC
+                                                  : ACCESS_PRIVATE,
+                                sym->name, NULL) == FAILURE)
+           return MATCH_ERROR;
+
          break;
 
        case INTERFACE_INTRINSIC_OP:
          if (gfc_current_ns->operator_access[op] == ACCESS_UNKNOWN)
            {
+             gfc_intrinsic_op other_op;
+
              gfc_current_ns->operator_access[op] =
                (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+
+             /* Handle the case if there is another op with the same
+                function, for INTRINSIC_EQ vs. INTRINSIC_EQ_OS and so on.  */
+             other_op = gfc_equivalent_op (op);
+
+             if (other_op != INTRINSIC_NONE)
+               gfc_current_ns->operator_access[other_op] =
+                 (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+
            }
          else
            {
@@ -6161,6 +6842,7 @@ do_parm (void)
   gfc_symbol *sym;
   gfc_expr *init;
   match m;
+  gfc_try t;
 
   m = gfc_match_symbol (&sym, 0);
   if (m == MATCH_NO)
@@ -6202,35 +6884,8 @@ do_parm (void)
       goto cleanup;
     }
 
-  if (sym->ts.type == BT_CHARACTER
-      && sym->ts.u.cl != NULL
-      && sym->ts.u.cl->length != NULL
-      && sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
-      && init->expr_type == EXPR_CONSTANT
-      && init->ts.type == BT_CHARACTER)
-    gfc_set_constant_character_len (
-      mpz_get_si (sym->ts.u.cl->length->value.integer), init, -1);
-  else if (sym->ts.type == BT_CHARACTER && sym->ts.u.cl != NULL
-          && sym->ts.u.cl->length == NULL)
-       {
-         int clen;
-         if (init->expr_type == EXPR_CONSTANT)
-           {
-             clen = init->value.character.length;
-             sym->ts.u.cl->length = gfc_int_expr (clen);
-           }
-         else if (init->expr_type == EXPR_ARRAY)
-           {
-             gfc_expr *p = init->value.constructor->expr;
-             clen = p->value.character.length;
-             sym->ts.u.cl->length = gfc_int_expr (clen);
-           }
-         else if (init->ts.u.cl && init->ts.u.cl->length)
-           sym->ts.u.cl->length = gfc_copy_expr (sym->value->ts.u.cl->length);
-       }
-
-  sym->value = init;
-  return MATCH_YES;
+  t = add_init_expr_to_sym (sym->name, &init, &gfc_current_locus);
+  return (t == SUCCESS) ? MATCH_YES : MATCH_ERROR;
 
 cleanup:
   gfc_free_expr (init);
@@ -6309,8 +6964,8 @@ gfc_match_save (void)
       switch (m)
        {
        case MATCH_YES:
-         if (gfc_add_save (&sym->attr, sym->name, &gfc_current_locus)
-             == FAILURE)
+         if (gfc_add_save (&sym->attr, SAVE_EXPLICIT, sym->name,
+                           &gfc_current_locus) == FAILURE)
            return MATCH_ERROR;
          goto next_item;
 
@@ -6353,6 +7008,13 @@ gfc_match_value (void)
   gfc_symbol *sym;
   match m;
 
+  /* This is not allowed within a BLOCK construct!  */
+  if (gfc_current_state () == COMP_BLOCK)
+    {
+      gfc_error ("VALUE is not allowed inside of BLOCK at %C");
+      return MATCH_ERROR;
+    }
+
   if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: VALUE statement at %C")
       == FAILURE)
     return MATCH_ERROR;
@@ -6419,11 +7081,19 @@ gfc_match_volatile (void)
   for(;;)
     {
       /* VOLATILE is special because it can be added to host-associated 
-        symbols locally.  */
+        symbols locally. Except for coarrays. */
       m = gfc_match_symbol (&sym, 1);
       switch (m)
        {
        case MATCH_YES:
+         /* F2008, C560+C561. VOLATILE for host-/use-associated variable or
+            for variable in a BLOCK which is defined outside of the BLOCK.  */
+         if (sym->ns != gfc_current_ns && sym->attr.codimension)
+           {
+             gfc_error ("Specifying VOLATILE for coarray variable '%s' at "
+                        "%C, which is use-/host-associated", sym->name);
+             return MATCH_ERROR;
+           }
          if (gfc_add_volatile (&sym->attr, sym->name, &gfc_current_locus)
              == FAILURE)
            return MATCH_ERROR;
@@ -6451,6 +7121,59 @@ syntax:
 }
 
 
+match
+gfc_match_asynchronous (void)
+{
+  gfc_symbol *sym;
+  match m;
+
+  if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASYNCHRONOUS statement at %C")
+      == FAILURE)
+    return MATCH_ERROR;
+
+  if (gfc_match (" ::") == MATCH_NO && gfc_match_space () == MATCH_NO)
+    {
+      return MATCH_ERROR;
+    }
+
+  if (gfc_match_eos () == MATCH_YES)
+    goto syntax;
+
+  for(;;)
+    {
+      /* ASYNCHRONOUS is special because it can be added to host-associated 
+        symbols locally.  */
+      m = gfc_match_symbol (&sym, 1);
+      switch (m)
+       {
+       case MATCH_YES:
+         if (gfc_add_asynchronous (&sym->attr, sym->name, &gfc_current_locus)
+             == FAILURE)
+           return MATCH_ERROR;
+         goto next_item;
+
+       case MATCH_NO:
+         break;
+
+       case MATCH_ERROR:
+         return MATCH_ERROR;
+       }
+
+    next_item:
+      if (gfc_match_eos () == MATCH_YES)
+       break;
+      if (gfc_match_char (',') != MATCH_YES)
+       goto syntax;
+    }
+
+  return MATCH_YES;
+
+syntax:
+  gfc_error ("Syntax error in ASYNCHRONOUS statement at %C");
+  return MATCH_ERROR;
+}
+
+
 /* Match a module procedure statement.  Note that we have to modify
    symbols in the parent's namespace because the current one was there
    to receive symbols that are in an interface's formal argument list.  */
@@ -6461,6 +7184,7 @@ gfc_match_modproc (void)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   gfc_symbol *sym;
   match m;
+  locus old_locus;
   gfc_namespace *module_ns;
   gfc_interface *old_interface_head, *interface;
 
@@ -6476,7 +7200,10 @@ gfc_match_modproc (void)
 
   module_ns = gfc_current_ns->parent;
   for (; module_ns; module_ns = module_ns->parent)
-    if (module_ns->proc_name->attr.flavor == FL_MODULE)
+    if (module_ns->proc_name->attr.flavor == FL_MODULE
+       || module_ns->proc_name->attr.flavor == FL_PROGRAM
+       || (module_ns->proc_name->attr.flavor == FL_PROCEDURE
+           && !module_ns->proc_name->attr.contained))
       break;
 
   if (module_ns == NULL)
@@ -6486,9 +7213,23 @@ gfc_match_modproc (void)
      end up with a syntax error and need to recover.  */
   old_interface_head = gfc_current_interface_head ();
 
+  /* Check if the F2008 optional double colon appears.  */
+  gfc_gobble_whitespace ();
+  old_locus = gfc_current_locus;
+  if (gfc_match ("::") == MATCH_YES)
+    {
+      if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: double colon in "
+                        "MODULE PROCEDURE statement at %L", &old_locus)
+         == FAILURE)
+       return MATCH_ERROR;
+    }
+  else
+    gfc_current_locus = old_locus;
+      
   for (;;)
     {
       bool last = false;
+      old_locus = gfc_current_locus;
 
       m = gfc_match_name (name);
       if (m == MATCH_NO)
@@ -6500,6 +7241,7 @@ gfc_match_modproc (void)
         current namespace.  */
       if (gfc_match_eos () == MATCH_YES)
        last = true;
+
       if (!last && gfc_match_char (',') != MATCH_YES)
        goto syntax;
 
@@ -6508,6 +7250,13 @@ gfc_match_modproc (void)
       if (gfc_get_symbol (name, module_ns, &sym))
        return MATCH_ERROR;
 
+      if (sym->attr.intrinsic)
+       {
+         gfc_error ("Intrinsic procedure at %L cannot be a MODULE "
+                    "PROCEDURE", &old_locus);
+         return MATCH_ERROR;
+       }
+
       if (sym->attr.proc != PROC_MODULE
          && gfc_add_procedure (&sym->attr, PROC_MODULE,
                                sym->name, NULL) == FAILURE)
@@ -6517,6 +7266,7 @@ gfc_match_modproc (void)
        return MATCH_ERROR;
 
       sym->attr.mod_proc = 1;
+      sym->declared_at = old_locus;
 
       if (last)
        break;
@@ -6533,7 +7283,7 @@ syntax:
   while (interface != old_interface_head)
   {
     gfc_interface *i = interface->next;
-    gfc_free (interface);
+    free (interface);
     interface = i;
   }
 
@@ -6561,6 +7311,8 @@ check_extended_derived_type (char *name)
       return NULL;
     }
 
+  extended = gfc_find_dt_in_generic (extended);
+
   if (extended->attr.flavor != FL_DERIVED)
     {
       gfc_error ("'%s' in EXTENDS expression at %C is not a "
@@ -6663,11 +7415,12 @@ gfc_match_derived_decl (void)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   char parent[GFC_MAX_SYMBOL_LEN + 1];
   symbol_attribute attr;
-  gfc_symbol *sym;
+  gfc_symbol *sym, *gensym;
   gfc_symbol *extended;
   match m;
   match is_type_attr_spec = MATCH_NO;
   bool seen_attr = false;
+  gfc_interface *intr = NULL, *head;
 
   if (gfc_current_state () == COMP_DERIVED)
     return MATCH_NO;
@@ -6713,16 +7466,50 @@ gfc_match_derived_decl (void)
       return MATCH_ERROR;
     }
 
-  if (gfc_get_symbol (name, NULL, &sym))
+  if (gfc_get_symbol (name, NULL, &gensym))
     return MATCH_ERROR;
 
-  if (sym->ts.type != BT_UNKNOWN)
+  if (!gensym->attr.generic && gensym->ts.type != BT_UNKNOWN)
     {
       gfc_error ("Derived type name '%s' at %C already has a basic type "
-                "of %s", sym->name, gfc_typename (&sym->ts));
+                "of %s", gensym->name, gfc_typename (&gensym->ts));
       return MATCH_ERROR;
     }
 
+  if (!gensym->attr.generic
+      && gfc_add_generic (&gensym->attr, gensym->name, NULL) == FAILURE)
+    return MATCH_ERROR;
+
+  if (!gensym->attr.function
+      && gfc_add_function (&gensym->attr, gensym->name, NULL) == FAILURE)
+    return MATCH_ERROR;
+
+  sym = gfc_find_dt_in_generic (gensym);
+
+  if (sym && (sym->components != NULL || sym->attr.zero_comp))
+    {
+      gfc_error ("Derived type definition of '%s' at %C has already been "
+                 "defined", sym->name);
+      return MATCH_ERROR;
+    }
+
+  if (!sym)
+    {
+      /* Use upper case to save the actual derived-type symbol.  */
+      gfc_get_symbol (gfc_get_string ("%c%s",
+                       (char) TOUPPER ((unsigned char) gensym->name[0]),
+                       &gensym->name[1]), NULL, &sym);
+      sym->name = gfc_get_string (gensym->name);
+      head = gensym->generic;
+      intr = gfc_get_interface ();
+      intr->sym = sym;
+      intr->where = gfc_current_locus;
+      intr->sym->declared_at = gfc_current_locus;
+      intr->next = head;
+      gensym->generic = intr;
+      gensym->attr.if_source = IFSRC_DECL;
+    }
+
   /* The symbol may already have the derived attribute without the
      components.  The ways this can happen is via a function
      definition, an INTRINSIC statement or a subtype in another
@@ -6732,16 +7519,18 @@ gfc_match_derived_decl (void)
       && gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE)
     return MATCH_ERROR;
 
-  if (sym->components != NULL || sym->attr.zero_comp)
-    {
-      gfc_error ("Derived type definition of '%s' at %C has already been "
-                "defined", sym->name);
-      return MATCH_ERROR;
-    }
-
   if (attr.access != ACCESS_UNKNOWN
       && gfc_add_access (&sym->attr, attr.access, sym->name, NULL) == FAILURE)
     return MATCH_ERROR;
+  else if (sym->attr.access == ACCESS_UNKNOWN
+          && gensym->attr.access != ACCESS_UNKNOWN
+          && gfc_add_access (&sym->attr, gensym->attr.access, sym->name, NULL)
+             == FAILURE)
+    return MATCH_ERROR;
+
+  if (sym->attr.access != ACCESS_UNKNOWN
+      && gensym->attr.access == ACCESS_UNKNOWN)
+    gensym->attr.access = sym->attr.access;
 
   /* See if the derived type was labeled as bind(c).  */
   if (attr.is_bind_c != 0)
@@ -6758,13 +7547,23 @@ gfc_match_derived_decl (void)
 
       /* Add the extended derived type as the first component.  */
       gfc_add_component (sym, parent, &p);
-      sym->attr.extension = attr.extension;
       extended->refs++;
       gfc_set_sym_referenced (extended);
 
       p->ts.type = BT_DERIVED;
       p->ts.u.derived = extended;
       p->initializer = gfc_default_initializer (&p->ts);
+      
+      /* Set extension level.  */
+      if (extended->attr.extension == 255)
+       {
+         /* Since the extension field is 8 bit wide, we can only have
+            up to 255 extension levels.  */
+         gfc_error ("Maximum extension level reached with type '%s' at %L",
+                    extended->name, &extended->declared_at);
+         return MATCH_ERROR;
+       }
+      sym->attr.extension = extended->attr.extension + 1;
 
       /* Provide the links between the extended type and its extension.  */
       if (!extended->f2k_derived)
@@ -6773,6 +7572,10 @@ gfc_match_derived_decl (void)
       st->n.sym = sym;
     }
 
+  if (!sym->hash_value)
+    /* Set the hash for the compound name for this type.  */
+    sym->hash_value = gfc_hash_value (sym);
+
   /* Take over the ABSTRACT attribute.  */
   sym->attr.abstract = attr.abstract;
 
@@ -6783,22 +7586,14 @@ gfc_match_derived_decl (void)
 
 
 /* Cray Pointees can be declared as: 
-      pointer (ipt, a (n,m,...,*)) 
-   By default, this is treated as an AS_ASSUMED_SIZE array.  We'll
-   cheat and set a constant bound of 1 for the last dimension, if this
-   is the case. Since there is no bounds-checking for Cray Pointees,
-   this will be okay.  */
+      pointer (ipt, a (n,m,...,*))  */
 
 match
 gfc_mod_pointee_as (gfc_array_spec *as)
 {
   as->cray_pointee = true; /* This will be useful to know later.  */
   if (as->type == AS_ASSUMED_SIZE)
-    {
-      as->type = AS_EXPLICIT;
-      as->upper[as->rank - 1] = gfc_int_expr (1);
-      as->cp_was_assumed = true;
-    }
+    as->cp_was_assumed = true;
   else if (as->type == AS_ASSUMED_SHAPE)
     {
       gfc_error ("Cray Pointee at %C cannot be assumed shape array");
@@ -6842,12 +7637,7 @@ static gfc_expr *
 enum_initializer (gfc_expr *last_initializer, locus where)
 {
   gfc_expr *result;
-
-  result = gfc_get_expr ();
-  result->expr_type = EXPR_CONSTANT;
-  result->ts.type = BT_INTEGER;
-  result->ts.kind = gfc_c_int_kind;
-  result->where = where;
+  result = gfc_get_constant_expr (BT_INTEGER, gfc_c_int_kind, &where);
 
   mpz_init (result->value.integer);
 
@@ -6906,7 +7696,7 @@ enumerator_decl (void)
   /* OK, we've successfully matched the declaration.  Now put the
      symbol in the current namespace. If we fail to create the symbol,
      bail out.  */
-  if (build_sym (name, NULL, &as, &var_locus) == FAILURE)
+  if (build_sym (name, NULL, false, &as, &var_locus) == FAILURE)
     {
       m = MATCH_ERROR;
       goto cleanup;
@@ -6938,10 +7728,9 @@ enumerator_decl (void)
 
   if (initializer == NULL || initializer->ts.type != BT_INTEGER)
     {
-      gfc_error("ENUMERATOR %L not initialized with integer expression",
-               &var_locus);
+      gfc_error ("ENUMERATOR %L not initialized with integer expression",
+                &var_locus);
       m = MATCH_ERROR;
-      gfc_free_enum_history ();
       goto cleanup;
     }
 
@@ -7007,7 +7796,10 @@ gfc_match_enumerator_def (void)
     {
       m = enumerator_decl ();
       if (m == MATCH_ERROR)
-       goto cleanup;
+       {
+         gfc_free_enum_history ();
+         goto cleanup;
+       }
       if (m == MATCH_NO)
        break;
 
@@ -7237,14 +8029,15 @@ match_procedure_in_type (void)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
   char target_buf[GFC_MAX_SYMBOL_LEN + 1];
-  char* target = NULL;
-  gfc_typebound_proc* tb;
+  char* target = NULL, *ifc = NULL;
+  gfc_typebound_proc tb;
   bool seen_colons;
   bool seen_attrs;
   match m;
   gfc_symtree* stree;
   gfc_namespace* ns;
   gfc_symbol* block;
+  int num;
 
   /* Check current state.  */
   gcc_assert (gfc_state_stack->state == COMP_DERIVED_CONTAINS);
@@ -7269,28 +8062,26 @@ match_procedure_in_type (void)
          return MATCH_ERROR;
        }
 
-      target = target_buf;
+      ifc = target_buf;
     }
 
   /* Construct the data structure.  */
-  tb = gfc_get_typebound_proc ();
-  tb->where = gfc_current_locus;
-  tb->is_generic = 0;
+  memset (&tb, 0, sizeof (tb));
+  tb.where = gfc_current_locus;
 
   /* Match binding attributes.  */
-  m = match_binding_attributes (tb, false, false);
+  m = match_binding_attributes (&tb, false, false);
   if (m == MATCH_ERROR)
     return m;
   seen_attrs = (m == MATCH_YES);
 
-  /* Check that attribute DEFERRED is given iff an interface is specified, which
-     means target != NULL.  */
-  if (tb->deferred && !target)
+  /* Check that attribute DEFERRED is given if an interface is specified.  */
+  if (tb.deferred && !ifc)
     {
       gfc_error ("Interface must be specified for DEFERRED binding at %C");
       return MATCH_ERROR;
     }
-  if (target && !tb->deferred)
+  if (ifc && !tb.deferred)
     {
       gfc_error ("PROCEDURE(interface) at %C should be declared DEFERRED");
       return MATCH_ERROR;
@@ -7307,97 +8098,103 @@ match_procedure_in_type (void)
       return MATCH_ERROR;
     }
 
-  /* Match the binding name.  */ 
-  m = gfc_match_name (name);
-  if (m == MATCH_ERROR)
-    return m;
-  if (m == MATCH_NO)
-    {
-      gfc_error ("Expected binding name at %C");
-      return MATCH_ERROR;
-    }
-
-  /* Try to match the '=> target', if it's there.  */
-  m = gfc_match (" =>");
-  if (m == MATCH_ERROR)
-    return m;
-  if (m == MATCH_YES)
+  /* Match the binding names.  */ 
+  for(num=1;;num++)
     {
-      if (tb->deferred)
+      m = gfc_match_name (name);
+      if (m == MATCH_ERROR)
+       return m;
+      if (m == MATCH_NO)
        {
-         gfc_error ("'=> target' is invalid for DEFERRED binding at %C");
+         gfc_error ("Expected binding name at %C");
          return MATCH_ERROR;
        }
 
-      if (!seen_colons)
-       {
-         gfc_error ("'::' needed in PROCEDURE binding with explicit target"
-                    " at %C");
-         return MATCH_ERROR;
-       }
+      if (num>1 && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: PROCEDURE list"
+                                  " at %C") == FAILURE)
+       return MATCH_ERROR;
 
-      m = gfc_match_name (target_buf);
+      /* Try to match the '=> target', if it's there.  */
+      target = ifc;
+      m = gfc_match (" =>");
       if (m == MATCH_ERROR)
        return m;
-      if (m == MATCH_NO)
+      if (m == MATCH_YES)
        {
-         gfc_error ("Expected binding target after '=>' at %C");
-         return MATCH_ERROR;
+         if (tb.deferred)
+           {
+             gfc_error ("'=> target' is invalid for DEFERRED binding at %C");
+             return MATCH_ERROR;
+           }
+
+         if (!seen_colons)
+           {
+             gfc_error ("'::' needed in PROCEDURE binding with explicit target"
+                        " at %C");
+             return MATCH_ERROR;
+           }
+
+         m = gfc_match_name (target_buf);
+         if (m == MATCH_ERROR)
+           return m;
+         if (m == MATCH_NO)
+           {
+             gfc_error ("Expected binding target after '=>' at %C");
+             return MATCH_ERROR;
+           }
+         target = target_buf;
        }
-      target = target_buf;
-    }
 
-  /* Now we should have the end.  */
-  m = gfc_match_eos ();
-  if (m == MATCH_ERROR)
-    return m;
-  if (m == MATCH_NO)
-    {
-      gfc_error ("Junk after PROCEDURE declaration at %C");
-      return MATCH_ERROR;
-    }
+      /* If no target was found, it has the same name as the binding.  */
+      if (!target)
+       target = name;
 
-  /* If no target was found, it has the same name as the binding.  */
-  if (!target)
-    target = name;
+      /* Get the namespace to insert the symbols into.  */
+      ns = block->f2k_derived;
+      gcc_assert (ns);
 
-  /* Get the namespace to insert the symbols into.  */
-  ns = block->f2k_derived;
-  gcc_assert (ns);
+      /* If the binding is DEFERRED, check that the containing type is ABSTRACT.  */
+      if (tb.deferred && !block->attr.abstract)
+       {
+         gfc_error ("Type '%s' containing DEFERRED binding at %C "
+                    "is not ABSTRACT", block->name);
+         return MATCH_ERROR;
+       }
 
-  /* If the binding is DEFERRED, check that the containing type is ABSTRACT.  */
-  if (tb->deferred && !block->attr.abstract)
-    {
-      gfc_error ("Type '%s' containing DEFERRED binding at %C is not ABSTRACT",
-                block->name);
-      return MATCH_ERROR;
-    }
+      /* See if we already have a binding with this name in the symtree which
+        would be an error.  If a GENERIC already targetted this binding, it may
+        be already there but then typebound is still NULL.  */
+      stree = gfc_find_symtree (ns->tb_sym_root, name);
+      if (stree && stree->n.tb)
+       {
+         gfc_error ("There is already a procedure with binding name '%s' for "
+                    "the derived type '%s' at %C", name, block->name);
+         return MATCH_ERROR;
+       }
 
-  /* See if we already have a binding with this name in the symtree which would
-     be an error.  If a GENERIC already targetted this binding, it may be
-     already there but then typebound is still NULL.  */
-  stree = gfc_find_symtree (ns->tb_sym_root, name);
-  if (stree && stree->n.tb)
-    {
-      gfc_error ("There's already a procedure with binding name '%s' for the"
-                " derived type '%s' at %C", name, block->name);
-      return MATCH_ERROR;
-    }
+      /* Insert it and set attributes.  */
 
-  /* Insert it and set attributes.  */
+      if (!stree)
+       {
+         stree = gfc_new_symtree (&ns->tb_sym_root, name);
+         gcc_assert (stree);
+       }
+      stree->n.tb = gfc_get_typebound_proc (&tb);
 
-  if (!stree)
-    {
-      stree = gfc_new_symtree (&ns->tb_sym_root, name);
-      gcc_assert (stree);
+      if (gfc_get_sym_tree (target, gfc_current_ns, &stree->n.tb->u.specific,
+                           false))
+       return MATCH_ERROR;
+      gfc_set_sym_referenced (stree->n.tb->u.specific->n.sym);
+  
+      if (gfc_match_eos () == MATCH_YES)
+       return MATCH_YES;
+      if (gfc_match_char (',') != MATCH_YES)
+       goto syntax;
     }
-  stree->n.tb = tb;
-
-  if (gfc_get_sym_tree (target, gfc_current_ns, &tb->u.specific, false))
-    return MATCH_ERROR;
-  gfc_set_sym_referenced (tb->u.specific->n.sym);
 
-  return MATCH_YES;
+syntax:
+  gfc_error ("Syntax error in PROCEDURE statement at %C");
+  return MATCH_ERROR;
 }
 
 
@@ -7428,6 +8225,9 @@ gfc_match_generic (void)
   ns = block->f2k_derived;
   gcc_assert (block && ns);
 
+  memset (&tbattr, 0, sizeof (tbattr));
+  tbattr.where = gfc_current_locus;
+
   /* See if we get an access-specifier.  */
   m = match_binding_attributes (&tbattr, true, false);
   if (m == MATCH_ERROR)
@@ -7531,7 +8331,7 @@ gfc_match_generic (void)
     }
   else
     {
-      tb = gfc_get_typebound_proc ();
+      tb = gfc_get_typebound_proc (NULL);
       tb->where = gfc_current_locus;
       tb->access = tbattr.access;
       tb->is_generic = 1;
@@ -7592,6 +8392,8 @@ gfc_match_generic (void)
       target->specific_st = target_st;
       target->specific = NULL;
       target->next = tb->u.generic;
+      target->is_operator = ((op_type == INTERFACE_USER_OP)
+                            || (op_type == INTERFACE_INTRINSIC_OP));
       tb->u.generic = target;
     }
   while (gfc_match (" ,") == MATCH_YES);
@@ -7622,8 +8424,18 @@ gfc_match_final_decl (void)
   bool first, last;
   gfc_symbol* block;
 
+  if (gfc_current_form == FORM_FREE)
+    {
+      char c = gfc_peek_ascii_char ();
+      if (!gfc_is_whitespace (c) && c != ':')
+       return MATCH_NO;
+    }
+  
   if (gfc_state_stack->state != COMP_DERIVED_CONTAINS)
     {
+      if (gfc_current_form == FORM_FIXED)
+       return MATCH_NO;
+
       gfc_error ("FINAL declaration at %C must be inside a derived type "
                 "CONTAINS section");
       return MATCH_ERROR;