OSDN Git Service

PR fortran/30723
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-decl.c
index dce4095..8c564cb 100644 (file)
@@ -1,5 +1,6 @@
 /* Backend function setup
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software
+   Foundation, Inc.
    Contributed by Paul Brook
 
 This file is part of GCC.
@@ -30,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "ggc.h"
 #include "toplev.h"
 #include "tm.h"
+#include "rtl.h"
 #include "target.h"
 #include "function.h"
 #include "flags.h"
@@ -48,14 +50,15 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 /* Holds the result of the function if no result variable specified.  */
 
 static GTY(()) tree current_fake_result_decl;
+static GTY(()) tree parent_fake_result_decl;
 
 static GTY(()) tree current_function_return_label;
 
 
 /* Holds the variable DECLs for the current function.  */
 
-static GTY(()) tree saved_function_decls = NULL_TREE;
-static GTY(()) tree saved_parent_function_decls = NULL_TREE;
+static GTY(()) tree saved_function_decls;
+static GTY(()) tree saved_parent_function_decls;
 
 
 /* The namespace of the module we're currently generating.  Only used while
@@ -71,13 +74,12 @@ tree gfc_static_ctors;
 
 /* Function declarations for builtin library functions.  */
 
-tree gfor_fndecl_internal_malloc;
-tree gfor_fndecl_internal_malloc64;
 tree gfor_fndecl_internal_realloc;
 tree gfor_fndecl_internal_realloc64;
-tree gfor_fndecl_internal_free;
 tree gfor_fndecl_allocate;
 tree gfor_fndecl_allocate64;
+tree gfor_fndecl_allocate_array;
+tree gfor_fndecl_allocate64_array;
 tree gfor_fndecl_deallocate;
 tree gfor_fndecl_pause_numeric;
 tree gfor_fndecl_pause_string;
@@ -85,8 +87,17 @@ tree gfor_fndecl_stop_numeric;
 tree gfor_fndecl_stop_string;
 tree gfor_fndecl_select_string;
 tree gfor_fndecl_runtime_error;
+tree gfor_fndecl_runtime_error_at;
+tree gfor_fndecl_os_error;
+tree gfor_fndecl_generate_error;
 tree gfor_fndecl_set_fpe;
 tree gfor_fndecl_set_std;
+tree gfor_fndecl_set_convert;
+tree gfor_fndecl_set_record_marker;
+tree gfor_fndecl_set_max_subrecord_length;
+tree gfor_fndecl_ctime;
+tree gfor_fndecl_fdate;
+tree gfor_fndecl_ttynam;
 tree gfor_fndecl_in_pack;
 tree gfor_fndecl_in_unpack;
 tree gfor_fndecl_associated;
@@ -111,7 +122,6 @@ tree gfor_fndecl_math_exponent16;
 
 /* String functions.  */
 
-tree gfor_fndecl_copy_string;
 tree gfor_fndecl_compare_string;
 tree gfor_fndecl_concat_string;
 tree gfor_fndecl_string_len_trim;
@@ -119,7 +129,6 @@ tree gfor_fndecl_string_index;
 tree gfor_fndecl_string_scan;
 tree gfor_fndecl_string_verify;
 tree gfor_fndecl_string_trim;
-tree gfor_fndecl_string_repeat;
 tree gfor_fndecl_adjustl;
 tree gfor_fndecl_adjustr;
 
@@ -134,6 +143,12 @@ tree gfor_fndecl_iargc;
 tree gfor_fndecl_si_kind;
 tree gfor_fndecl_sr_kind;
 
+/* BLAS gemm functions.  */
+tree gfor_fndecl_sgemm;
+tree gfor_fndecl_dgemm;
+tree gfor_fndecl_cgemm;
+tree gfor_fndecl_zgemm;
+
 
 static void
 gfc_add_decl_to_parent_function (tree decl)
@@ -284,7 +299,7 @@ gfc_sym_mangled_identifier (gfc_symbol * sym)
     return gfc_sym_identifier (sym);
   else
     {
-      snprintf (name, sizeof name, "__%s__%s", sym->module, sym->name);
+      snprintf (name, sizeof name, "__%s_MOD_%s", sym->module, sym->name);
       return get_identifier (name);
     }
 }
@@ -299,7 +314,8 @@ gfc_sym_mangled_function_id (gfc_symbol * sym)
   char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1];
 
   if (sym->module == NULL || sym->attr.proc == PROC_EXTERNAL
-      || (sym->module != NULL && sym->attr.if_source == IFSRC_IFBODY))
+      || (sym->module != NULL && (sym->attr.external
+           || sym->attr.if_source == IFSRC_IFBODY)))
     {
       if (strcmp (sym->name, "MAIN__") == 0
          || sym->attr.proc == PROC_INTRINSIC)
@@ -319,7 +335,7 @@ gfc_sym_mangled_function_id (gfc_symbol * sym)
     }
   else
     {
-      snprintf (name, sizeof name, "__%s__%s", sym->module, sym->name);
+      snprintf (name, sizeof name, "__%s_MOD_%s", sym->module, sym->name);
       return get_identifier (name);
     }
 }
@@ -365,13 +381,13 @@ gfc_finish_cray_pointee (tree decl, gfc_symbol *sym)
 
   /* Parameters need to be dereferenced.  */
   if (sym->cp_pointer->attr.dummy) 
-    ptr_decl = gfc_build_indirect_ref (ptr_decl);
+    ptr_decl = build_fold_indirect_ref (ptr_decl);
 
   /* Check to see if we're dealing with a variable-sized array.  */
   if (sym->attr.dimension
       && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE) 
     {  
-      /* These decls will be derefenced later, so we don't dereference
+      /* These decls will be dereferenced later, so we don't dereference
         them here.  */
       value = convert (TREE_TYPE (decl), ptr_decl);
     }
@@ -379,69 +395,49 @@ gfc_finish_cray_pointee (tree decl, gfc_symbol *sym)
     {
       ptr_decl = convert (build_pointer_type (TREE_TYPE (decl)),
                          ptr_decl);
-      value = gfc_build_indirect_ref (ptr_decl);
+      value = build_fold_indirect_ref (ptr_decl);
     }
 
   SET_DECL_VALUE_EXPR (decl, value);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
+  GFC_DECL_CRAY_POINTEE (decl) = 1;
   /* This is a fake variable just for debugging purposes.  */
   TREE_ASM_WRITTEN (decl) = 1;
 }
 
 
-/* Finish processing of a declaration and install its initial value.  */
+/* Finish processing of a declaration without an initial value.  */
 
 static void
-gfc_finish_decl (tree decl, tree init)
+gfc_finish_decl (tree decl)
 {
-  if (TREE_CODE (decl) == PARM_DECL)
-    gcc_assert (init == NULL_TREE);
-  /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se
-     -- it overlaps DECL_ARG_TYPE.  */
-  else if (init == NULL_TREE)
-    gcc_assert (DECL_INITIAL (decl) == NULL_TREE);
-  else
-    gcc_assert (DECL_INITIAL (decl) == error_mark_node);
+  gcc_assert (TREE_CODE (decl) == PARM_DECL
+             || DECL_INITIAL (decl) == NULL_TREE);
 
-  if (init != NULL_TREE)
-    {
-      if (TREE_CODE (decl) != TYPE_DECL)
-       DECL_INITIAL (decl) = init;
-      else
-       {
-         /* typedef foo = bar; store the type of bar as the type of foo.  */
-         TREE_TYPE (decl) = TREE_TYPE (init);
-         DECL_INITIAL (decl) = init = 0;
-       }
-    }
-
-  if (TREE_CODE (decl) == VAR_DECL)
-    {
-      if (DECL_SIZE (decl) == NULL_TREE
-         && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
-       layout_decl (decl, 0);
-
-      /* A static variable with an incomplete type is an error if it is
-         initialized. Also if it is not file scope. Otherwise, let it
-         through, but if it is not `extern' then it may cause an error
-         message later.  */
-      /* An automatic variable with an incomplete type is an error.  */
-      if (DECL_SIZE (decl) == NULL_TREE
-          && (TREE_STATIC (decl) ? (DECL_INITIAL (decl) != 0
-                                   || DECL_CONTEXT (decl) != 0)
-                                 : !DECL_EXTERNAL (decl)))
-       {
-         gfc_fatal_error ("storage size not known");
-       }
-
-      if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
-         && (DECL_SIZE (decl) != 0)
-         && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
-       {
-         gfc_fatal_error ("storage size not constant");
-       }
-    }
+  if (TREE_CODE (decl) != VAR_DECL)
+    return;
 
+  if (DECL_SIZE (decl) == NULL_TREE
+      && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
+    layout_decl (decl, 0);
+
+  /* A few consistency checks.  */
+  /* A static variable with an incomplete type is an error if it is
+     initialized. Also if it is not file scope. Otherwise, let it
+     through, but if it is not `extern' then it may cause an error
+     message later.  */
+  /* An automatic variable with an incomplete type is an error.  */
+
+  /* We should know the storage size.  */
+  gcc_assert (DECL_SIZE (decl) != NULL_TREE
+             || (TREE_STATIC (decl) 
+                 ? (!DECL_INITIAL (decl) || !DECL_CONTEXT (decl))
+                 : DECL_EXTERNAL (decl)));
+
+  /* The storage size should be constant.  */
+  gcc_assert ((!DECL_EXTERNAL (decl) && !TREE_STATIC (decl))
+             || !DECL_SIZE (decl)
+             || TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST);
 }
 
 
@@ -450,6 +446,7 @@ gfc_finish_decl (tree decl, tree init)
 static void
 gfc_finish_var_decl (tree decl, gfc_symbol * sym)
 {
+  tree new;
   /* TREE_ADDRESSABLE means the address of this variable is actually needed.
      This is the equivalent of the TARGET variables.
      We also need to set this if the variable is passed by reference in a
@@ -497,12 +494,31 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
   if ((sym->attr.save || sym->attr.data || sym->value)
       && !sym->attr.use_assoc)
     TREE_STATIC (decl) = 1;
-  
+
+  if (sym->attr.volatile_)
+    {
+      TREE_THIS_VOLATILE (decl) = 1;
+      new = build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_VOLATILE);
+      TREE_TYPE (decl) = new;
+    } 
+
   /* Keep variables larger than max-stack-var-size off stack.  */
   if (!sym->ns->proc_name->attr.recursive
       && INTEGER_CST_P (DECL_SIZE_UNIT (decl))
-      && !gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl)))
+      && !gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl))
+        /* Put variable length auto array pointers always into stack.  */
+      && (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
+         || sym->attr.dimension == 0
+         || sym->as->type != AS_EXPLICIT
+         || sym->attr.pointer
+         || sym->attr.allocatable)
+      && !DECL_ARTIFICIAL (decl))
     TREE_STATIC (decl) = 1;
+
+  /* Handle threadprivate variables.  */
+  if (sym->attr.threadprivate
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+    DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
 }
 
 
@@ -610,6 +626,30 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       else
        gfc_add_decl_to_function (GFC_TYPE_ARRAY_OFFSET (type));
     }
+
+  if (GFC_TYPE_ARRAY_SIZE (type) == NULL_TREE
+      && sym->as->type != AS_ASSUMED_SIZE)
+    GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest);
+
+  if (POINTER_TYPE_P (type))
+    {
+      gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (type)));
+      gcc_assert (TYPE_LANG_SPECIFIC (type)
+                 == TYPE_LANG_SPECIFIC (TREE_TYPE (type)));
+      type = TREE_TYPE (type);
+    }
+
+  if (! COMPLETE_TYPE_P (type) && GFC_TYPE_ARRAY_SIZE (type))
+    {
+      tree size, range;
+
+      size = build2 (MINUS_EXPR, gfc_array_index_type,
+                    GFC_TYPE_ARRAY_SIZE (type), gfc_index_one_node);
+      range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
+                               size);
+      TYPE_DOMAIN (type) = range;
+      layout_type (type);
+    }
 }
 
 
@@ -624,7 +664,7 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
   tree type;
   gfc_array_spec *as;
   char *name;
-  int packed;
+  gfc_packed packed;
   int n;
   bool known_size;
 
@@ -655,30 +695,30 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
   type = TREE_TYPE (type);
   if (GFC_DESCRIPTOR_TYPE_P (type))
     {
-      /* Create a decriptorless array pointer.  */
+      /* Create a descriptorless array pointer.  */
       as = sym->as;
-      packed = 0;
+      packed = PACKED_NO;
       if (!gfc_option.flag_repack_arrays)
        {
          if (as->type == AS_ASSUMED_SIZE)
-           packed = 2;
+           packed = PACKED_FULL;
        }
       else
        {
          if (as->type == AS_EXPLICIT)
            {
-             packed = 2;
+             packed = PACKED_FULL;
              for (n = 0; n < as->rank; n++)
                {
                  if (!(as->upper[n]
                        && as->lower[n]
                        && as->upper[n]->expr_type == EXPR_CONSTANT
                        && as->lower[n]->expr_type == EXPR_CONSTANT))
-                   packed = 1;
+                   packed = PACKED_PARTIAL;
                }
            }
          else
-           packed = 1;
+           packed = PACKED_PARTIAL;
        }
 
       type = gfc_typenode_for_spec (&sym->ts);
@@ -689,9 +729,10 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
       /* We now have an expression for the element size, so create a fully
         qualified type.  Reset sym->backend decl or this will just return the
         old type.  */
+      DECL_ARTIFICIAL (sym->backend_decl) = 1;
       sym->backend_decl = NULL_TREE;
       type = gfc_sym_type (sym);
-      packed = 2;
+      packed = PACKED_FULL;
     }
 
   ASM_FORMAT_PRIVATE_NAME (name, IDENTIFIER_POINTER (DECL_NAME (dummy)), 0);
@@ -706,16 +747,10 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
      frontend bugs.  */
   gcc_assert (sym->as->type != AS_DEFERRED);
 
-  switch (packed)
-    {
-    case 1:
-      GFC_DECL_PARTIAL_PACKED_ARRAY (decl) = 1;
-      break;
-
-    case 2:
-      GFC_DECL_PACKED_ARRAY (decl) = 1;
-      break;
-    }
+  if (packed == PACKED_PARTIAL)
+    GFC_DECL_PARTIAL_PACKED_ARRAY (decl) = 1;
+  else if (packed == PACKED_FULL)
+    GFC_DECL_PACKED_ARRAY (decl) = 1;
 
   gfc_build_qualified_array (decl, sym);
 
@@ -758,7 +793,8 @@ gfc_create_string_length (gfc_symbol * sym)
                           gfc_charlen_type_node);
       DECL_ARTIFICIAL (length) = 1;
       TREE_USED (length) = 1;
-      gfc_defer_symbol_init (sym);
+      if (sym->ns->proc_name->tlink != NULL)
+       gfc_defer_symbol_init (sym);
       sym->ts.cl->backend_decl = length;
     }
 
@@ -809,7 +845,9 @@ gfc_get_symbol_decl (gfc_symbol * sym)
   tree length = NULL_TREE;
   int byref;
 
-  gcc_assert (sym->attr.referenced);
+  gcc_assert (sym->attr.referenced
+               || sym->attr.use_assoc
+               || sym->ns->proc_name->attr.if_source == IFSRC_IFBODY);
 
   if (sym->ns && sym->ns->proc_name->attr.function)
     byref = gfc_return_by_reference (sym->ns->proc_name);
@@ -837,21 +875,33 @@ gfc_get_symbol_decl (gfc_symbol * sym)
       if (sym->ts.type == BT_CHARACTER)
        {
          if (sym->ts.cl->backend_decl == NULL_TREE)
+           length = gfc_create_string_length (sym);
+         else
+           length = sym->ts.cl->backend_decl;
+         if (TREE_CODE (length) == VAR_DECL
+             && DECL_CONTEXT (length) == NULL_TREE)
            {
-             length = gfc_create_string_length (sym);
-             if (TREE_CODE (length) != INTEGER_CST)
-               {
-                 gfc_finish_var_decl (length, sym);
-                 gfc_defer_symbol_init (sym);
-               }
+             /* Add the string length to the same context as the symbol.  */
+             if (DECL_CONTEXT (sym->backend_decl) == current_function_decl)
+               gfc_add_decl_to_function (length);
+             else
+               gfc_add_decl_to_parent_function (length);
+
+             gcc_assert (DECL_CONTEXT (sym->backend_decl) ==
+                           DECL_CONTEXT (length));
+
+             gfc_defer_symbol_init (sym);
            }
        }
 
       /* Use a copy of the descriptor for dummy arrays.  */
       if (sym->attr.dimension && !TREE_USED (sym->backend_decl))
         {
-          sym->backend_decl =
-            gfc_build_dummy_array_decl (sym, sym->backend_decl);
+         decl = gfc_build_dummy_array_decl (sym, sym->backend_decl);
+         /* Prevent the dummy from being detected as unused if it is copied.  */
+         if (sym->backend_decl != NULL && decl != sym->backend_decl)
+           DECL_ARTIFICIAL (sym->backend_decl) = 1;
+         sym->backend_decl = decl;
        }
 
       TREE_USED (sym->backend_decl) = 1;
@@ -903,6 +953,9 @@ gfc_get_symbol_decl (gfc_symbol * sym)
        GFC_DECL_PACKED_ARRAY (decl) = 1;
     }
 
+  if (sym->ts.type == BT_DERIVED && sym->ts.derived->attr.alloc_comp)
+    gfc_defer_symbol_init (sym);
+
   gfc_finish_var_decl (decl, sym);
 
   if (sym->ts.type == BT_CHARACTER)
@@ -930,9 +983,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
   sym->backend_decl = decl;
 
   if (sym->attr.assign)
-    {
-      gfc_add_assign_aux_vars (sym);
-    }
+    gfc_add_assign_aux_vars (sym);
 
   if (TREE_STATIC (decl) && !sym->attr.use_assoc)
     {
@@ -982,7 +1033,7 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
   gfc_expr e;
   gfc_intrinsic_sym *isym;
   gfc_expr argexpr;
-  char s[GFC_MAX_SYMBOL_LEN + 13]; /* "f2c_specific" and '\0'.  */
+  char s[GFC_MAX_SYMBOL_LEN + 23]; /* "_gfortran_f2c_specific" and '\0'.  */
   tree name;
   tree mangled_name;
 
@@ -1014,9 +1065,14 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
        isym->resolve.f1 (&e, &argexpr);
       else
        {
-         /* All specific intrinsics take one or two arguments.  */
-         gcc_assert (isym->formal->next->next == NULL);
-         isym->resolve.f2 (&e, &argexpr, NULL);
+         if (isym->formal->next->next == NULL)
+           isym->resolve.f2 (&e, &argexpr, NULL);
+         else
+           {
+             /* All specific intrinsics take less than 4 arguments.  */
+             gcc_assert (isym->formal->next->next->next == NULL);
+             isym->resolve.f3 (&e, &argexpr, NULL, NULL);
+           }
        }
 
       if (gfc_option.flag_f2c
@@ -1025,10 +1081,10 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
        {
          /* Specific which needs a different implementation if f2c
             calling conventions are used.  */
-         sprintf (s, "f2c_specific%s", e.value.function.name);
+         sprintf (s, "_gfortran_f2c_specific%s", e.value.function.name);
        }
       else
-       sprintf (s, "specific%s", e.value.function.name);
+       sprintf (s, "_gfortran_specific%s", e.value.function.name);
 
       name = get_identifier (s);
       mangled_name = name;
@@ -1073,7 +1129,7 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
      sense.  */
   if (sym->attr.pure || sym->attr.elemental)
     {
-      if (sym->attr.function)
+      if (sym->attr.function && !gfc_return_by_reference (sym))
        DECL_IS_PURE (fndecl) = 1;
       /* TODO: check if pure SUBROUTINEs don't have INTENT(OUT)
         parameters and don't use alternate returns (is this
@@ -1200,7 +1256,7 @@ build_function_decl (gfc_symbol * sym)
       /* TODO: check if a pure SUBROUTINE has no INTENT(OUT) arguments
         including a alternate return. In that case it can also be
         marked as PURE. See also in gfc_get_extern_function_decl().  */
-      if (attr.function)
+      if (attr.function && !gfc_return_by_reference (sym))
        DECL_IS_PURE (fndecl) = 1;
       TREE_SIDE_EFFECTS (fndecl) = 0;
     }
@@ -1220,9 +1276,8 @@ create_function_arglist (gfc_symbol * sym)
 {
   tree fndecl;
   gfc_formal_arglist *f;
-  tree typelist;
-  tree arglist;
-  tree length;
+  tree typelist, hidden_typelist;
+  tree arglist, hidden_arglist;
   tree type;
   tree parm;
 
@@ -1231,6 +1286,7 @@ create_function_arglist (gfc_symbol * sym)
   /* Build formal argument list. Make sure that their TREE_CONTEXT is
      the new FUNCTION_DECL node.  */
   arglist = NULL_TREE;
+  hidden_arglist = NULL_TREE;
   typelist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
 
   if (sym->attr.entry_master)
@@ -1241,7 +1297,8 @@ create_function_arglist (gfc_symbol * sym)
       DECL_CONTEXT (parm) = fndecl;
       DECL_ARG_TYPE (parm) = type;
       TREE_READONLY (parm) = 1;
-      gfc_finish_decl (parm, NULL_TREE);
+      gfc_finish_decl (parm);
+      DECL_ARTIFICIAL (parm) = 1;
 
       arglist = chainon (arglist, parm);
       typelist = TREE_CHAIN (typelist);
@@ -1249,131 +1306,187 @@ create_function_arglist (gfc_symbol * sym)
 
   if (gfc_return_by_reference (sym))
     {
-      type = TREE_VALUE (typelist);
-      parm = build_decl (PARM_DECL, get_identifier ("__result"), type);
-
-      DECL_CONTEXT (parm) = fndecl;
-      DECL_ARG_TYPE (parm) = type;
-      TREE_READONLY (parm) = 1;
-      DECL_ARTIFICIAL (parm) = 1;
-      gfc_finish_decl (parm, NULL_TREE);
-
-      arglist = chainon (arglist, parm);
-      typelist = TREE_CHAIN (typelist);
+      tree type = TREE_VALUE (typelist), length = NULL;
 
       if (sym->ts.type == BT_CHARACTER)
        {
-         gfc_allocate_lang_decl (parm);
-
          /* Length of character result.  */
-         type = TREE_VALUE (typelist);
-         gcc_assert (type == gfc_charlen_type_node);
+         tree len_type = TREE_VALUE (TREE_CHAIN (typelist));
+         gcc_assert (len_type == gfc_charlen_type_node);
 
          length = build_decl (PARM_DECL,
                               get_identifier (".__result"),
-                              type);
+                              len_type);
          if (!sym->ts.cl->length)
            {
              sym->ts.cl->backend_decl = length;
              TREE_USED (length) = 1;
            }
          gcc_assert (TREE_CODE (length) == PARM_DECL);
-         arglist = chainon (arglist, length);
-         typelist = TREE_CHAIN (typelist);
          DECL_CONTEXT (length) = fndecl;
-         DECL_ARG_TYPE (length) = type;
+         DECL_ARG_TYPE (length) = len_type;
          TREE_READONLY (length) = 1;
          DECL_ARTIFICIAL (length) = 1;
-         gfc_finish_decl (length, NULL_TREE);
-       }
-    }
-
-  for (f = sym->formal; f; f = f->next)
-    {
-      if (f->sym != NULL)      /* ignore alternate returns.  */
-       {
-         length = NULL_TREE;
+         gfc_finish_decl (length);
+         if (sym->ts.cl->backend_decl == NULL
+             || sym->ts.cl->backend_decl == length)
+           {
+             gfc_symbol *arg;
+             tree backend_decl;
 
-         type = TREE_VALUE (typelist);
+             if (sym->ts.cl->backend_decl == NULL)
+               {
+                 tree len = build_decl (VAR_DECL,
+                                        get_identifier ("..__result"),
+                                        gfc_charlen_type_node);
+                 DECL_ARTIFICIAL (len) = 1;
+                 TREE_USED (len) = 1;
+                 sym->ts.cl->backend_decl = len;
+               }
 
-         /* Build a the argument declaration.  */
-         parm = build_decl (PARM_DECL,
-                            gfc_sym_identifier (f->sym), type);
+             /* Make sure PARM_DECL type doesn't point to incomplete type.  */
+             arg = sym->result ? sym->result : sym;
+             backend_decl = arg->backend_decl;
+             /* Temporary clear it, so that gfc_sym_type creates complete
+                type.  */
+             arg->backend_decl = NULL;
+             type = gfc_sym_type (arg);
+             arg->backend_decl = backend_decl;
+             type = build_reference_type (type);
+           }
+       }
 
-         /* Fill in arg stuff.  */
-         DECL_CONTEXT (parm) = fndecl;
-         DECL_ARG_TYPE (parm) = type;
-         /* All implementation args are read-only.  */
-         TREE_READONLY (parm) = 1;
+      parm = build_decl (PARM_DECL, get_identifier ("__result"), type);
 
-         gfc_finish_decl (parm, NULL_TREE);
+      DECL_CONTEXT (parm) = fndecl;
+      DECL_ARG_TYPE (parm) = TREE_VALUE (typelist);
+      TREE_READONLY (parm) = 1;
+      DECL_ARTIFICIAL (parm) = 1;
+      gfc_finish_decl (parm);
 
-         f->sym->backend_decl = parm;
+      arglist = chainon (arglist, parm);
+      typelist = TREE_CHAIN (typelist);
 
-         arglist = chainon (arglist, parm);
+      if (sym->ts.type == BT_CHARACTER)
+       {
+         gfc_allocate_lang_decl (parm);
+         arglist = chainon (arglist, length);
          typelist = TREE_CHAIN (typelist);
        }
     }
 
-  /* Add the hidden string length parameters.  */
-  parm = arglist;
+  hidden_typelist = typelist;
+  for (f = sym->formal; f; f = f->next)
+    if (f->sym != NULL)        /* Ignore alternate returns.  */
+      hidden_typelist = TREE_CHAIN (hidden_typelist);
+
   for (f = sym->formal; f; f = f->next)
     {
       char name[GFC_MAX_SYMBOL_LEN + 2];
+
       /* Ignore alternate returns.  */
       if (f->sym == NULL)
        continue;
 
-      if (f->sym->ts.type != BT_CHARACTER)
-       continue;
-
-      parm = f->sym->backend_decl;
       type = TREE_VALUE (typelist);
-      gcc_assert (type == gfc_charlen_type_node);
 
-      strcpy (&name[1], f->sym->name);
-      name[0] = '_';
-      length = build_decl (PARM_DECL, get_identifier (name), type);
+      if (f->sym->ts.type == BT_CHARACTER)
+       {
+         tree len_type = TREE_VALUE (hidden_typelist);
+         tree length = NULL_TREE;
+         gcc_assert (len_type == gfc_charlen_type_node);
 
-      arglist = chainon (arglist, length);
-      DECL_CONTEXT (length) = fndecl;
-      DECL_ARTIFICIAL (length) = 1;
-      DECL_ARG_TYPE (length) = type;
-      TREE_READONLY (length) = 1;
-      gfc_finish_decl (length, NULL_TREE);
+         strcpy (&name[1], f->sym->name);
+         name[0] = '_';
+         length = build_decl (PARM_DECL, get_identifier (name), len_type);
+
+         hidden_arglist = chainon (hidden_arglist, length);
+         DECL_CONTEXT (length) = fndecl;
+         DECL_ARTIFICIAL (length) = 1;
+         DECL_ARG_TYPE (length) = len_type;
+         TREE_READONLY (length) = 1;
+         gfc_finish_decl (length);
 
-      /* TODO: Check string lengths when -fbounds-check.  */
+         /* TODO: Check string lengths when -fbounds-check.  */
 
-      /* Use the passed value for assumed length variables.  */
-      if (!f->sym->ts.cl->length)
-       {
-         TREE_USED (length) = 1;
-         if (!f->sym->ts.cl->backend_decl)
-           f->sym->ts.cl->backend_decl = length;
-         else
+         /* Use the passed value for assumed length variables.  */
+         if (!f->sym->ts.cl->length)
            {
-             /* there is already another variable using this
-                gfc_charlen node, build a new one for this variable
-                and chain it into the list of gfc_charlens.
-                This happens for e.g. in the case
-                CHARACTER(*)::c1,c2
-                since CHARACTER declarations on the same line share
-                the same gfc_charlen node.  */
-             gfc_charlen *cl;
+             TREE_USED (length) = 1;
+             if (!f->sym->ts.cl->backend_decl)
+               f->sym->ts.cl->backend_decl = length;
+             else
+               {
+                 /* there is already another variable using this
+                    gfc_charlen node, build a new one for this variable
+                    and chain it into the list of gfc_charlens.
+                    This happens for e.g. in the case
+                    CHARACTER(*)::c1,c2
+                    since CHARACTER declarations on the same line share
+                    the same gfc_charlen node.  */
+                 gfc_charlen *cl;
              
-             cl = gfc_get_charlen ();
-             cl->backend_decl = length;
-             cl->next = f->sym->ts.cl->next;
-             f->sym->ts.cl->next = cl;
-             f->sym->ts.cl = cl;
+                 cl = gfc_get_charlen ();
+                 cl->backend_decl = length;
+                 cl->next = f->sym->ts.cl->next;
+                 f->sym->ts.cl->next = cl;
+                 f->sym->ts.cl = cl;
+               }
+           }
+
+         hidden_typelist = TREE_CHAIN (hidden_typelist);
+
+         if (f->sym->ts.cl->backend_decl == NULL
+             || f->sym->ts.cl->backend_decl == length)
+           {
+             if (f->sym->ts.cl->backend_decl == NULL)
+               gfc_create_string_length (f->sym);
+
+             /* Make sure PARM_DECL type doesn't point to incomplete type.  */
+             if (f->sym->attr.flavor == FL_PROCEDURE)
+               type = build_pointer_type (gfc_get_function_type (f->sym));
+             else
+               type = gfc_sym_type (f->sym);
            }
        }
 
-      parm = TREE_CHAIN (parm);
+      /* For non-constant length array arguments, make sure they use
+        a different type node from TYPE_ARG_TYPES type.  */
+      if (f->sym->attr.dimension
+         && type == TREE_VALUE (typelist)
+         && TREE_CODE (type) == POINTER_TYPE
+         && GFC_ARRAY_TYPE_P (type)
+         && f->sym->as->type != AS_ASSUMED_SIZE
+         && ! COMPLETE_TYPE_P (TREE_TYPE (type)))
+       {
+         if (f->sym->attr.flavor == FL_PROCEDURE)
+           type = build_pointer_type (gfc_get_function_type (f->sym));
+         else
+           type = gfc_sym_type (f->sym);
+       }
+
+      /* Build a the argument declaration.  */
+      parm = build_decl (PARM_DECL, gfc_sym_identifier (f->sym), type);
+
+      /* Fill in arg stuff.  */
+      DECL_CONTEXT (parm) = fndecl;
+      DECL_ARG_TYPE (parm) = TREE_VALUE (typelist);
+      /* All implementation args are read-only.  */
+      TREE_READONLY (parm) = 1;
+
+      gfc_finish_decl (parm);
+
+      f->sym->backend_decl = parm;
+
+      arglist = chainon (arglist, parm);
       typelist = TREE_CHAIN (typelist);
     }
 
-  gcc_assert (TREE_VALUE (typelist) == void_type_node);
+  /* Add the hidden string length parameters.  */
+  arglist = chainon (arglist, hidden_arglist);
+
+  gcc_assert (hidden_typelist == NULL_TREE
+              || TREE_VALUE (hidden_typelist) == void_type_node);
   DECL_ARGUMENTS (fndecl) = arglist;
 }
 
@@ -1387,6 +1500,11 @@ gfc_gimplify_function (tree fndecl)
   gimplify_function_tree (fndecl);
   dump_function (TDI_generic, fndecl);
 
+  /* Generate errors for structured block violations.  */
+  /* ??? Could be done as part of resolve_labels.  */
+  if (flag_openmp)
+    diagnose_omp_structured_block_errors (fndecl);
+
   /* Convert all nested functions to GIMPLE now.  We do things in this order
      so that items like VLA sizes are expanded properly in the context of the
      correct function.  */
@@ -1501,6 +1619,7 @@ build_entry_thunks (gfc_namespace * ns)
          if (thunk_formal)
            {
              /* Pass the argument.  */
+             DECL_ARTIFICIAL (thunk_formal->sym->backend_decl) = 1;
              args = tree_cons (NULL_TREE, thunk_formal->sym->backend_decl,
                                args);
              if (formal->sym->ts.type == BT_CHARACTER)
@@ -1515,7 +1634,7 @@ build_entry_thunks (gfc_namespace * ns)
              args = tree_cons (NULL_TREE, null_pointer_node, args);
              if (formal->sym->ts.type == BT_CHARACTER)
                {
-                 tmp = convert (gfc_charlen_type_node, integer_zero_node);
+                 tmp = build_int_cst (gfc_charlen_type_node, 0);
                  string_args = tree_cons (NULL_TREE, tmp, string_args);
                }
            }
@@ -1525,7 +1644,7 @@ build_entry_thunks (gfc_namespace * ns)
       args = nreverse (args);
       args = chainon (args, nreverse (string_args));
       tmp = ns->proc_name->backend_decl;
-      tmp = gfc_build_function_call (tmp, args);
+      tmp = build_function_call_expr (tmp, args);
       if (ns->proc_name->attr.mixed_entry_master)
        {
          tree union_decl, field;
@@ -1632,23 +1751,50 @@ gfc_create_function_decl (gfc_namespace * ns)
   create_function_arglist (ns->proc_name);
 }
 
-/* Return the decl used to hold the function return value.  */
+/* Return the decl used to hold the function return value.  If
+   parent_flag is set, the context is the parent_scope.  */
 
 tree
-gfc_get_fake_result_decl (gfc_symbol * sym)
+gfc_get_fake_result_decl (gfc_symbol * sym, int parent_flag)
 {
   tree decl;
   tree length;
+  tree this_fake_result_decl;
+  tree this_function_decl;
 
   char name[GFC_MAX_SYMBOL_LEN + 10];
 
+  if (parent_flag)
+    {
+      this_fake_result_decl = parent_fake_result_decl;
+      this_function_decl = DECL_CONTEXT (current_function_decl);
+    }
+  else
+    {
+      this_fake_result_decl = current_fake_result_decl;
+      this_function_decl = current_function_decl;
+    }
+
   if (sym
-      && sym->ns->proc_name->backend_decl == current_function_decl
-      && sym->ns->proc_name->attr.mixed_entry_master
+      && sym->ns->proc_name->backend_decl == this_function_decl
+      && sym->ns->proc_name->attr.entry_master
       && sym != sym->ns->proc_name)
     {
-      decl = gfc_get_fake_result_decl (sym->ns->proc_name);
-      if (decl)
+      tree t = NULL, var;
+      if (this_fake_result_decl != NULL)
+       for (t = TREE_CHAIN (this_fake_result_decl); t; t = TREE_CHAIN (t))
+         if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t)), sym->name) == 0)
+           break;
+      if (t)
+       return TREE_VALUE (t);
+      decl = gfc_get_fake_result_decl (sym->ns->proc_name, parent_flag);
+
+      if (parent_flag)
+       this_fake_result_decl = parent_fake_result_decl;
+      else
+       this_fake_result_decl = current_fake_result_decl;
+
+      if (decl && sym->ns->proc_name->attr.mixed_entry_master)
        {
          tree field;
 
@@ -1662,29 +1808,47 @@ gfc_get_fake_result_decl (gfc_symbol * sym)
          decl = build3 (COMPONENT_REF, TREE_TYPE (field), decl, field,
                         NULL_TREE);
        }
-      return decl;
+
+      var = create_tmp_var_raw (TREE_TYPE (decl), sym->name);
+      if (parent_flag)
+       gfc_add_decl_to_parent_function (var);
+      else
+       gfc_add_decl_to_function (var);
+
+      SET_DECL_VALUE_EXPR (var, decl);
+      DECL_HAS_VALUE_EXPR_P (var) = 1;
+      GFC_DECL_RESULT (var) = 1;
+
+      TREE_CHAIN (this_fake_result_decl)
+         = tree_cons (get_identifier (sym->name), var,
+                      TREE_CHAIN (this_fake_result_decl));
+      return var;
     }
 
-  if (current_fake_result_decl != NULL_TREE)
-    return current_fake_result_decl;
+  if (this_fake_result_decl != NULL_TREE)
+    return TREE_VALUE (this_fake_result_decl);
 
   /* Only when gfc_get_fake_result_decl is called by gfc_trans_return,
      sym is NULL.  */
   if (!sym)
     return NULL_TREE;
 
-  if (sym->ts.type == BT_CHARACTER
-      && !sym->ts.cl->backend_decl)
+  if (sym->ts.type == BT_CHARACTER)
     {
-      length = gfc_create_string_length (sym);
-      gfc_finish_var_decl (length, sym);
+      if (sym->ts.cl->backend_decl == NULL_TREE)
+       length = gfc_create_string_length (sym);
+      else
+       length = sym->ts.cl->backend_decl;
+      if (TREE_CODE (length) == VAR_DECL
+         && DECL_CONTEXT (length) == NULL_TREE)
+       gfc_add_decl_to_function (length);
     }
 
   if (gfc_return_by_reference (sym))
     {
-      decl = DECL_ARGUMENTS (current_function_decl);
+      decl = DECL_ARGUMENTS (this_function_decl);
 
-      if (sym->ns->proc_name->backend_decl == current_function_decl
+      if (sym->ns->proc_name->backend_decl == this_function_decl
          && sym->ns->proc_name->attr.entry_master)
        decl = TREE_CHAIN (decl);
 
@@ -1695,22 +1859,33 @@ gfc_get_fake_result_decl (gfc_symbol * sym)
   else
     {
       sprintf (name, "__result_%.20s",
-              IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
-
-      decl = build_decl (VAR_DECL, get_identifier (name),
-                        TREE_TYPE (TREE_TYPE (current_function_decl)));
+              IDENTIFIER_POINTER (DECL_NAME (this_function_decl)));
 
+      if (!sym->attr.mixed_entry_master && sym->attr.function)
+       decl = build_decl (VAR_DECL, get_identifier (name),
+                          gfc_sym_type (sym));
+      else
+       decl = build_decl (VAR_DECL, get_identifier (name),
+                          TREE_TYPE (TREE_TYPE (this_function_decl)));
       DECL_ARTIFICIAL (decl) = 1;
       DECL_EXTERNAL (decl) = 0;
       TREE_PUBLIC (decl) = 0;
       TREE_USED (decl) = 1;
+      GFC_DECL_RESULT (decl) = 1;
+      TREE_ADDRESSABLE (decl) = 1;
 
       layout_decl (decl, 0);
 
-      gfc_add_decl_to_function (decl);
+      if (parent_flag)
+       gfc_add_decl_to_parent_function (decl);
+      else
+       gfc_add_decl_to_function (decl);
     }
 
-  current_fake_result_decl = decl;
+  if (parent_flag)
+    parent_fake_result_decl = build_tree_list (NULL, decl);
+  else
+    current_fake_result_decl = build_tree_list (NULL, decl);
 
   return decl;
 }
@@ -1780,15 +1955,9 @@ gfc_build_intrinsic_function_decls (void)
   tree gfc_complex8_type_node = gfc_get_complex_type (8);
   tree gfc_complex10_type_node = gfc_get_complex_type (10);
   tree gfc_complex16_type_node = gfc_get_complex_type (16);
+  tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
 
   /* String functions.  */
-  gfor_fndecl_copy_string =
-    gfc_build_library_function_decl (get_identifier (PREFIX("copy_string")),
-                                    void_type_node,
-                                    4,
-                                    gfc_charlen_type_node, pchar_type_node,
-                                    gfc_charlen_type_node, pchar_type_node);
-
   gfor_fndecl_compare_string =
     gfc_build_library_function_decl (get_identifier (PREFIX("compare_string")),
                                     gfc_int4_type_node,
@@ -1840,14 +2009,28 @@ gfc_build_intrinsic_function_decls (void)
                                      gfc_charlen_type_node,
                                      pchar_type_node);
 
-  gfor_fndecl_string_repeat =
-    gfc_build_library_function_decl (get_identifier (PREFIX("string_repeat")),
+  gfor_fndecl_ttynam =
+    gfc_build_library_function_decl (get_identifier (PREFIX("ttynam")),
                                      void_type_node,
-                                     4,
+                                     3,
                                      pchar_type_node,
                                      gfc_charlen_type_node,
+                                     gfc_c_int_type_node);
+
+  gfor_fndecl_fdate =
+    gfc_build_library_function_decl (get_identifier (PREFIX("fdate")),
+                                     void_type_node,
+                                     2,
                                      pchar_type_node,
-                                     gfc_int4_type_node);
+                                     gfc_charlen_type_node);
+
+  gfor_fndecl_ctime =
+    gfc_build_library_function_decl (get_identifier (PREFIX("ctime")),
+                                     void_type_node,
+                                     3,
+                                     pchar_type_node,
+                                     gfc_charlen_type_node,
+                                     gfc_int8_type_node);
 
   gfor_fndecl_adjustl =
     gfc_build_library_function_decl (get_identifier (PREFIX("adjustl")),
@@ -1864,13 +2047,15 @@ gfc_build_intrinsic_function_decls (void)
                                     gfc_charlen_type_node, pchar_type_node);
 
   gfor_fndecl_si_kind =
-    gfc_build_library_function_decl (get_identifier ("selected_int_kind"),
+    gfc_build_library_function_decl (get_identifier
+                                       (PREFIX("selected_int_kind")),
                                      gfc_int4_type_node,
                                      1,
                                      pvoid_type_node);
 
   gfor_fndecl_sr_kind =
-    gfc_build_library_function_decl (get_identifier ("selected_real_kind"),
+    gfc_build_library_function_decl (get_identifier 
+                                       (PREFIX("selected_real_kind")),
                                      gfc_int4_type_node,
                                      2, pvoid_type_node,
                                      pvoid_type_node);
@@ -1899,6 +2084,7 @@ gfc_build_intrinsic_function_decls (void)
                gfor_fndecl_math_powi[jkind][ikind].integer =
                  gfc_build_library_function_decl (get_identifier (name),
                    jtype, 2, jtype, itype);
+               TREE_READONLY (gfor_fndecl_math_powi[jkind][ikind].integer) = 1;
              }
          }
 
@@ -1912,6 +2098,7 @@ gfc_build_intrinsic_function_decls (void)
                gfor_fndecl_math_powi[rkind][ikind].real =
                  gfc_build_library_function_decl (get_identifier (name),
                    rtype, 2, rtype, itype);
+               TREE_READONLY (gfor_fndecl_math_powi[rkind][ikind].real) = 1;
              }
 
            ctype = gfc_get_complex_type (rkinds[rkind]);
@@ -1922,6 +2109,7 @@ gfc_build_intrinsic_function_decls (void)
                gfor_fndecl_math_powi[rkind][ikind].cmplx =
                  gfc_build_library_function_decl (get_identifier (name),
                    ctype, 2,ctype, itype);
+               TREE_READONLY (gfor_fndecl_math_powi[rkind][ikind].cmplx) = 1;
              }
          }
       }
@@ -1985,6 +2173,49 @@ gfc_build_intrinsic_function_decls (void)
                                       gfc_int4_type_node, 1,
                                       gfc_real16_type_node);
 
+  /* BLAS functions.  */
+  {
+    tree pint = build_pointer_type (gfc_c_int_type_node);
+    tree ps = build_pointer_type (gfc_get_real_type (gfc_default_real_kind));
+    tree pd = build_pointer_type (gfc_get_real_type (gfc_default_double_kind));
+    tree pc = build_pointer_type (gfc_get_complex_type (gfc_default_real_kind));
+    tree pz = build_pointer_type
+               (gfc_get_complex_type (gfc_default_double_kind));
+
+    gfor_fndecl_sgemm = gfc_build_library_function_decl
+                         (get_identifier
+                            (gfc_option.flag_underscoring ? "sgemm_"
+                                                          : "sgemm"),
+                          void_type_node, 15, pchar_type_node,
+                          pchar_type_node, pint, pint, pint, ps, ps, pint,
+                          ps, pint, ps, ps, pint, gfc_c_int_type_node,
+                          gfc_c_int_type_node);
+    gfor_fndecl_dgemm = gfc_build_library_function_decl
+                         (get_identifier
+                            (gfc_option.flag_underscoring ? "dgemm_"
+                                                          : "dgemm"),
+                          void_type_node, 15, pchar_type_node,
+                          pchar_type_node, pint, pint, pint, pd, pd, pint,
+                          pd, pint, pd, pd, pint, gfc_c_int_type_node,
+                          gfc_c_int_type_node);
+    gfor_fndecl_cgemm = gfc_build_library_function_decl
+                         (get_identifier
+                            (gfc_option.flag_underscoring ? "cgemm_"
+                                                          : "cgemm"),
+                          void_type_node, 15, pchar_type_node,
+                          pchar_type_node, pint, pint, pint, pc, pc, pint,
+                          pc, pint, pc, pc, pint, gfc_c_int_type_node,
+                          gfc_c_int_type_node);
+    gfor_fndecl_zgemm = gfc_build_library_function_decl
+                         (get_identifier
+                            (gfc_option.flag_underscoring ? "zgemm_"
+                                                          : "zgemm"),
+                          void_type_node, 15, pchar_type_node,
+                          pchar_type_node, pint, pint, pint, pz, pz, pint,
+                          pz, pint, pz, pz, pint, gfc_c_int_type_node,
+                          gfc_c_int_type_node);
+  }
+
   /* Other functions.  */
   gfor_fndecl_size0 =
     gfc_build_library_function_decl (get_identifier (PREFIX("size0")),
@@ -2014,18 +2245,6 @@ gfc_build_builtin_function_decls (void)
   tree gfc_logical4_type_node = gfc_get_logical_type (4);
   tree gfc_pint4_type_node = build_pointer_type (gfc_int4_type_node);
 
-  /* Treat these two internal malloc wrappers as malloc.  */
-  gfor_fndecl_internal_malloc =
-    gfc_build_library_function_decl (get_identifier (PREFIX("internal_malloc")),
-                                    pvoid_type_node, 1, gfc_int4_type_node);
-  DECL_IS_MALLOC (gfor_fndecl_internal_malloc) = 1;
-
-  gfor_fndecl_internal_malloc64 =
-    gfc_build_library_function_decl (get_identifier
-                                    (PREFIX("internal_malloc64")),
-                                    pvoid_type_node, 1, gfc_int8_type_node);
-  DECL_IS_MALLOC (gfor_fndecl_internal_malloc64) = 1;
-
   gfor_fndecl_internal_realloc =
     gfc_build_library_function_decl (get_identifier
                                     (PREFIX("internal_realloc")),
@@ -2038,23 +2257,33 @@ gfc_build_builtin_function_decls (void)
                                     pvoid_type_node, 2, pvoid_type_node,
                                     gfc_int8_type_node);
 
-  gfor_fndecl_internal_free =
-    gfc_build_library_function_decl (get_identifier (PREFIX("internal_free")),
-                                    void_type_node, 1, pvoid_type_node);
-
   gfor_fndecl_allocate =
     gfc_build_library_function_decl (get_identifier (PREFIX("allocate")),
-                                    void_type_node, 2, ppvoid_type_node,
-                                    gfc_int4_type_node);
+                                    pvoid_type_node, 2,
+                                    gfc_int4_type_node, gfc_pint4_type_node);
+  DECL_IS_MALLOC (gfor_fndecl_allocate) = 1;
 
   gfor_fndecl_allocate64 =
     gfc_build_library_function_decl (get_identifier (PREFIX("allocate64")),
-                                    void_type_node, 2, ppvoid_type_node,
-                                    gfc_int8_type_node);
+                                    pvoid_type_node, 2,
+                                    gfc_int8_type_node, gfc_pint4_type_node);
+  DECL_IS_MALLOC (gfor_fndecl_allocate64) = 1;
+
+  gfor_fndecl_allocate_array =
+    gfc_build_library_function_decl (get_identifier (PREFIX("allocate_array")),
+                                    pvoid_type_node, 3, pvoid_type_node,
+                                    gfc_int4_type_node, gfc_pint4_type_node);
+  DECL_IS_MALLOC (gfor_fndecl_allocate_array) = 1;
+
+  gfor_fndecl_allocate64_array =
+    gfc_build_library_function_decl (get_identifier (PREFIX("allocate64_array")),
+                                    pvoid_type_node, 3, pvoid_type_node,
+                                    gfc_int8_type_node, gfc_pint4_type_node);
+  DECL_IS_MALLOC (gfor_fndecl_allocate64_array) = 1;
 
   gfor_fndecl_deallocate =
     gfc_build_library_function_decl (get_identifier (PREFIX("deallocate")),
-                                    void_type_node, 2, ppvoid_type_node,
+                                    void_type_node, 2, pvoid_type_node,
                                     gfc_pint4_type_node);
 
   gfor_fndecl_stop_numeric =
@@ -2086,13 +2315,28 @@ gfc_build_builtin_function_decls (void)
 
   gfor_fndecl_runtime_error =
     gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error")),
-                                    void_type_node,
-                                    3,
-                                    pchar_type_node, pchar_type_node,
-                                    gfc_int4_type_node);
+                                    void_type_node, 1, pchar_type_node);
   /* The runtime_error function does not return.  */
   TREE_THIS_VOLATILE (gfor_fndecl_runtime_error) = 1;
 
+  gfor_fndecl_runtime_error_at =
+    gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error_at")),
+                                    void_type_node, 2, pchar_type_node,
+                                    pchar_type_node);
+  /* The runtime_error_at function does not return.  */
+  TREE_THIS_VOLATILE (gfor_fndecl_runtime_error_at) = 1;
+  
+  gfor_fndecl_generate_error =
+    gfc_build_library_function_decl (get_identifier (PREFIX("generate_error")),
+                                    void_type_node, 3, pvoid_type_node,
+                                     gfc_c_int_type_node, pchar_type_node);
+
+  gfor_fndecl_os_error =
+    gfc_build_library_function_decl (get_identifier (PREFIX("os_error")),
+                                    void_type_node, 1, pchar_type_node);
+  /* The runtime_error function does not return.  */
+  TREE_THIS_VOLATILE (gfor_fndecl_os_error) = 1;
+
   gfor_fndecl_set_fpe =
     gfc_build_library_function_decl (get_identifier (PREFIX("set_fpe")),
                                    void_type_node, 1, gfc_c_int_type_node);
@@ -2100,10 +2344,25 @@ gfc_build_builtin_function_decls (void)
   gfor_fndecl_set_std =
     gfc_build_library_function_decl (get_identifier (PREFIX("set_std")),
                                    void_type_node,
-                                   2,
+                                   5,
+                                   gfc_int4_type_node,
+                                   gfc_int4_type_node,
+                                   gfc_int4_type_node,
                                    gfc_int4_type_node,
                                    gfc_int4_type_node);
 
+  gfor_fndecl_set_convert =
+    gfc_build_library_function_decl (get_identifier (PREFIX("set_convert")),
+                                    void_type_node, 1, gfc_c_int_type_node);
+
+  gfor_fndecl_set_record_marker =
+    gfc_build_library_function_decl (get_identifier (PREFIX("set_record_marker")),
+                                    void_type_node, 1, gfc_c_int_type_node);
+
+  gfor_fndecl_set_max_subrecord_length =
+    gfc_build_library_function_decl (get_identifier (PREFIX("set_max_subrecord_length")),
+                                    void_type_node, 1, gfc_c_int_type_node);
+
   gfor_fndecl_in_pack = gfc_build_library_function_decl (
         get_identifier (PREFIX("internal_pack")),
         pvoid_type_node, 1, pvoid_type_node);
@@ -2129,17 +2388,19 @@ gfc_build_builtin_function_decls (void)
 /* Evaluate the length of dummy character variables.  */
 
 static tree
-gfc_trans_dummy_character (gfc_charlen * cl, tree fnbody)
+gfc_trans_dummy_character (gfc_symbol *sym, gfc_charlen *cl, tree fnbody)
 {
   stmtblock_t body;
 
-  gfc_finish_decl (cl->backend_decl, NULL_TREE);
+  gfc_finish_decl (cl->backend_decl);
 
   gfc_start_block (&body);
 
   /* Evaluate the string length expression.  */
   gfc_trans_init_string_length (cl, &body);
-  
+
+  gfc_trans_vla_type_sizes (sym, &body);
+
   gfc_add_expr_to_block (&body, fnbody);
   return gfc_finish_block (&body);
 }
@@ -2162,6 +2423,8 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody)
   /* Evaluate the string length expression.  */
   gfc_trans_init_string_length (sym->ts.cl, &body);
 
+  gfc_trans_vla_type_sizes (sym, &body);
+
   decl = sym->backend_decl;
 
   /* Emit a DECL_EXPR for this variable, which will cause the
@@ -2192,6 +2455,112 @@ gfc_trans_assign_aux_var (gfc_symbol * sym, tree fnbody)
   return gfc_finish_block (&body);
 }
 
+static void
+gfc_trans_vla_one_sizepos (tree *tp, stmtblock_t *body)
+{
+  tree t = *tp, var, val;
+
+  if (t == NULL || t == error_mark_node)
+    return;
+  if (TREE_CONSTANT (t) || DECL_P (t))
+    return;
+
+  if (TREE_CODE (t) == SAVE_EXPR)
+    {
+      if (SAVE_EXPR_RESOLVED_P (t))
+       {
+         *tp = TREE_OPERAND (t, 0);
+         return;
+       }
+      val = TREE_OPERAND (t, 0);
+    }
+  else
+    val = t;
+
+  var = gfc_create_var_np (TREE_TYPE (t), NULL);
+  gfc_add_decl_to_function (var);
+  gfc_add_modify_expr (body, var, val);
+  if (TREE_CODE (t) == SAVE_EXPR)
+    TREE_OPERAND (t, 0) = var;
+  *tp = var;
+}
+
+static void
+gfc_trans_vla_type_sizes_1 (tree type, stmtblock_t *body)
+{
+  tree t;
+
+  if (type == NULL || type == error_mark_node)
+    return;
+
+  type = TYPE_MAIN_VARIANT (type);
+
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    {
+      gfc_trans_vla_one_sizepos (&TYPE_MIN_VALUE (type), body);
+      gfc_trans_vla_one_sizepos (&TYPE_MAX_VALUE (type), body);
+
+      for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
+         TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
+       }
+    }
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      gfc_trans_vla_type_sizes_1 (TREE_TYPE (type), body);
+      gfc_trans_vla_type_sizes_1 (TYPE_DOMAIN (type), body);
+      gfc_trans_vla_one_sizepos (&TYPE_SIZE (type), body);
+      gfc_trans_vla_one_sizepos (&TYPE_SIZE_UNIT (type), body);
+
+      for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         TYPE_SIZE (t) = TYPE_SIZE (type);
+         TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
+       }
+    }
+}
+
+/* Make sure all type sizes and array domains are either constant,
+   or variable or parameter decls.  This is a simplified variant
+   of gimplify_type_sizes, but we can't use it here, as none of the
+   variables in the expressions have been gimplified yet.
+   As type sizes and domains for various variable length arrays
+   contain VAR_DECLs that are only initialized at gfc_trans_deferred_vars
+   time, without this routine gimplify_type_sizes in the middle-end
+   could result in the type sizes being gimplified earlier than where
+   those variables are initialized.  */
+
+void
+gfc_trans_vla_type_sizes (gfc_symbol *sym, stmtblock_t *body)
+{
+  tree type = TREE_TYPE (sym->backend_decl);
+
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      && (sym->attr.function || sym->attr.result || sym->attr.entry))
+    {
+      if (! current_fake_result_decl)
+       return;
+
+      type = TREE_TYPE (TREE_VALUE (current_fake_result_decl));
+    }
+
+  while (POINTER_TYPE_P (type))
+    type = TREE_TYPE (type);
+
+  if (GFC_DESCRIPTOR_TYPE_P (type))
+    {
+      tree etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
+
+      while (POINTER_TYPE_P (etype))
+       etype = TREE_TYPE (etype);
+
+      gfc_trans_vla_type_sizes_1 (etype, body);
+    }
+
+  gfc_trans_vla_type_sizes_1 (type, body);
+}
+
 
 /* Generate function entry and exit code, and add it to the function body.
    This includes:
@@ -2205,6 +2574,9 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
 {
   locus loc;
   gfc_symbol *sym;
+  gfc_formal_arglist *f;
+  stmtblock_t body;
+  bool seen_trans_deferred_array = false;
 
   /* Deal with implicit return variables.  Explicit return variables will
      already have been added.  */
@@ -2224,14 +2596,20 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
        }
       else if (proc_sym->as)
        {
-         fnbody = gfc_trans_dummy_array_bias (proc_sym,
-                                              current_fake_result_decl,
-                                              fnbody);
+         tree result = TREE_VALUE (current_fake_result_decl);
+         fnbody = gfc_trans_dummy_array_bias (proc_sym, result, fnbody);
+
+         /* An automatic character length, pointer array result.  */
+         if (proc_sym->ts.type == BT_CHARACTER
+               && TREE_CODE (proc_sym->ts.cl->backend_decl) == VAR_DECL)
+           fnbody = gfc_trans_dummy_character (proc_sym, proc_sym->ts.cl,
+                                               fnbody);
        }
       else if (proc_sym->ts.type == BT_CHARACTER)
        {
          if (TREE_CODE (proc_sym->ts.cl->backend_decl) == VAR_DECL)
-           fnbody = gfc_trans_dummy_character (proc_sym->ts.cl, fnbody);
+           fnbody = gfc_trans_dummy_character (proc_sym, proc_sym->ts.cl,
+                                               fnbody);
        }
       else
        gcc_assert (gfc_option.flag_f2c
@@ -2240,6 +2618,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
 
   for (sym = proc_sym->tlink; sym != proc_sym; sym = sym->tlink)
     {
+      bool sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
+                                  && sym->ts.derived->attr.alloc_comp;
       if (sym->attr.dimension)
        {
          switch (sym->as->type)
@@ -2253,10 +2633,19 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
                  if (TREE_STATIC (sym->backend_decl))
                    gfc_trans_static_array_pointer (sym);
                  else
-                   fnbody = gfc_trans_deferred_array (sym, fnbody);
+                   {
+                     seen_trans_deferred_array = true;
+                     fnbody = gfc_trans_deferred_array (sym, fnbody);
+                   }
                }
              else
                {
+                 if (sym_has_alloc_comp)
+                   {
+                     seen_trans_deferred_array = true;
+                     fnbody = gfc_trans_deferred_array (sym, fnbody);
+                   }
+
                  gfc_get_backend_locus (&loc);
                  gfc_set_backend_locus (&sym->declared_at);
                  fnbody = gfc_trans_auto_array_allocation (sym->backend_decl,
@@ -2282,19 +2671,24 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
              break;
 
            case AS_DEFERRED:
+             seen_trans_deferred_array = true;
              fnbody = gfc_trans_deferred_array (sym, fnbody);
              break;
 
            default:
              gcc_unreachable ();
            }
+         if (sym_has_alloc_comp && !seen_trans_deferred_array)
+           fnbody = gfc_trans_deferred_array (sym, fnbody);
        }
+      else if (sym_has_alloc_comp)
+       fnbody = gfc_trans_deferred_array (sym, fnbody);
       else if (sym->ts.type == BT_CHARACTER)
        {
          gfc_get_backend_locus (&loc);
          gfc_set_backend_locus (&sym->declared_at);
          if (sym->attr.dummy || sym->attr.result)
-           fnbody = gfc_trans_dummy_character (sym->ts.cl, fnbody);
+           fnbody = gfc_trans_dummy_character (sym, sym->ts.cl, fnbody);
          else
            fnbody = gfc_trans_auto_character_variable (sym, fnbody);
          gfc_set_backend_locus (&loc);
@@ -2310,7 +2704,26 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
        gcc_unreachable ();
     }
 
-  return fnbody;
+  gfc_init_block (&body);
+
+  for (f = proc_sym->formal; f; f = f->next)
+    if (f->sym && f->sym->tlink == NULL && f->sym->ts.type == BT_CHARACTER)
+      {
+       gcc_assert (f->sym->ts.cl->backend_decl != NULL);
+       if (TREE_CODE (f->sym->ts.cl->backend_decl) == PARM_DECL)
+         gfc_trans_vla_type_sizes (f->sym, &body);
+      }
+
+  if (gfc_return_by_reference (proc_sym) && proc_sym->ts.type == BT_CHARACTER
+      && current_fake_result_decl != NULL)
+    {
+      gcc_assert (proc_sym->ts.cl->backend_decl != NULL);
+      if (TREE_CODE (proc_sym->ts.cl->backend_decl) == PARM_DECL)
+       gfc_trans_vla_type_sizes (proc_sym, &body);
+    }
+
+  gfc_add_expr_to_block (&body, fnbody);
+  return gfc_finish_block (&body);
 }
 
 
@@ -2321,12 +2734,10 @@ gfc_create_module_variable (gfc_symbol * sym)
 {
   tree decl;
 
-  /* Only output symbols from this module.  */
-  if (sym->ns != module_namespace)
-    {
-      /* I don't think this should ever happen.  */
-      internal_error ("module symbol %s in wrong namespace", sym->name);
-    }
+  /* Module functions with alternate entries are dealt with later and
+     would get caught by the next condition.  */
+  if (sym->attr.entry)
+    return;
 
   /* Only output variables and array valued parameters.  */
   if (sym->attr.flavor != FL_VARIABLE
@@ -2339,7 +2750,8 @@ gfc_create_module_variable (gfc_symbol * sym)
     return;
 
   /* Equivalenced variables arrive here after creation.  */
-  if (sym->backend_decl && sym->equiv_built)
+  if (sym->backend_decl
+       && (sym->equiv_built || sym->attr.in_equivalence))
       return;
 
   if (sym->backend_decl)
@@ -2413,6 +2825,112 @@ gfc_generate_contained_functions (gfc_namespace * parent)
 }
 
 
+/* Drill down through expressions for the array specification bounds and
+   character length calling generate_local_decl for all those variables
+   that have not already been declared.  */
+
+static void
+generate_local_decl (gfc_symbol *);
+
+static void
+generate_expr_decls (gfc_symbol *sym, gfc_expr *e)
+{
+  gfc_actual_arglist *arg;
+  gfc_ref *ref;
+  int i;
+
+  if (e == NULL)
+    return;
+
+  switch (e->expr_type)
+    {
+    case EXPR_FUNCTION:
+      for (arg = e->value.function.actual; arg; arg = arg->next)
+       generate_expr_decls (sym, arg->expr);
+      break;
+
+    /* If the variable is not the same as the dependent, 'sym', and
+       it is not marked as being declared and it is in the same
+       namespace as 'sym', add it to the local declarations.  */
+    case EXPR_VARIABLE:
+      if (sym == e->symtree->n.sym
+           || e->symtree->n.sym->mark
+           || e->symtree->n.sym->ns != sym->ns)
+       return;
+
+      generate_local_decl (e->symtree->n.sym);
+      break;
+
+    case EXPR_OP:
+      generate_expr_decls (sym, e->value.op.op1);
+      generate_expr_decls (sym, e->value.op.op2);
+      break;
+
+    default:
+      break;
+    }
+
+  if (e->ref)
+    {
+      for (ref = e->ref; ref; ref = ref->next)
+       {
+         switch (ref->type)
+           {
+           case REF_ARRAY:
+             for (i = 0; i < ref->u.ar.dimen; i++)
+               {
+                 generate_expr_decls (sym, ref->u.ar.start[i]);
+                 generate_expr_decls (sym, ref->u.ar.end[i]);
+                 generate_expr_decls (sym, ref->u.ar.stride[i]);
+               }
+             break;
+
+           case REF_SUBSTRING:
+             generate_expr_decls (sym, ref->u.ss.start);
+             generate_expr_decls (sym, ref->u.ss.end);
+             break;
+
+           case REF_COMPONENT:
+             if (ref->u.c.component->ts.type == BT_CHARACTER
+                   && ref->u.c.component->ts.cl->length->expr_type
+                                               != EXPR_CONSTANT)
+               generate_expr_decls (sym, ref->u.c.component->ts.cl->length);
+
+             if (ref->u.c.component->as)
+               for (i = 0; i < ref->u.c.component->as->rank; i++)
+                 {
+                   generate_expr_decls (sym, ref->u.c.component->as->lower[i]);
+                   generate_expr_decls (sym, ref->u.c.component->as->upper[i]);
+                 }
+             break;
+           }
+       }
+    }
+}
+
+
+/* Check for dependencies in the character length and array spec. */
+
+static void
+generate_dependency_declarations (gfc_symbol *sym)
+{
+  int i;
+
+  if (sym->ts.type == BT_CHARACTER
+       && sym->ts.cl->length->expr_type != EXPR_CONSTANT)
+    generate_expr_decls (sym, sym->ts.cl->length);
+
+  if (sym->as && sym->as->rank)
+    {
+      for (i = 0; i < sym->as->rank; i++)
+       {
+          generate_expr_decls (sym, sym->as->lower[i]);
+          generate_expr_decls (sym, sym->as->upper[i]);
+       }
+    }
+}
+
+
 /* Generate decls for all local variables.  We do this to ensure correct
    handling of expressions which only appear in the specification of
    other functions.  */
@@ -2422,15 +2940,38 @@ generate_local_decl (gfc_symbol * sym)
 {
   if (sym->attr.flavor == FL_VARIABLE)
     {
+      /* Check for dependencies in the array specification and string
+       length, adding the necessary declarations to the function.  We
+       mark the symbol now, as well as in traverse_ns, to prevent
+       getting stuck in a circular dependency.  */
+      sym->mark = 1;
+      if (!sym->attr.dummy && !sym->ns->proc_name->attr.entry_master)
+        generate_dependency_declarations (sym);
+
       if (sym->attr.referenced)
         gfc_get_symbol_decl (sym);
       else if (sym->attr.dummy && warn_unused_parameter)
-            warning (0, "unused parameter %qs", sym->name);
+       gfc_warning ("Unused parameter %s declared at %L", sym->name,
+                    &sym->declared_at);
       /* Warn for unused variables, but not if they're inside a common
         block or are use-associated.  */
       else if (warn_unused_variable
               && !(sym->attr.in_common || sym->attr.use_assoc))
-       warning (0, "unused variable %qs", sym->name); 
+       gfc_warning ("Unused variable %s declared at %L", sym->name,
+                    &sym->declared_at);
+      /* For variable length CHARACTER parameters, the PARM_DECL already
+        references the length variable, so force gfc_get_symbol_decl
+        even when not referenced.  If optimize > 0, it will be optimized
+        away anyway.  But do this only after emitting -Wunused-parameter
+        warning if requested.  */
+      if (sym->attr.dummy && ! sym->attr.referenced
+         && sym->ts.type == BT_CHARACTER
+         && sym->ts.cl->backend_decl != NULL
+         && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
+       {
+         sym->attr.referenced = 1;
+         gfc_get_symbol_decl (sym);
+       }
     }
 }
 
@@ -2486,10 +3027,12 @@ gfc_generate_function_code (gfc_namespace * ns)
   tree old_context;
   tree decl;
   tree tmp;
+  tree tmp2;
   stmtblock_t block;
   stmtblock_t body;
   tree result;
   gfc_symbol *sym;
+  int rank;
 
   sym = ns->proc_name;
 
@@ -2513,9 +3056,6 @@ gfc_generate_function_code (gfc_namespace * ns)
 
   trans_function_start (sym);
 
-  /* Will be created as needed.  */
-  current_fake_result_decl = NULL_TREE;
-
   gfc_start_block (&block);
 
   if (ns->entries && ns->proc_name->ts.type == BT_CHARACTER)
@@ -2534,30 +3074,46 @@ gfc_generate_function_code (gfc_namespace * ns)
   /* Translate COMMON blocks.  */
   gfc_trans_common (ns);
 
+  /* Null the parent fake result declaration if this namespace is
+     a module function or an external procedures.  */
+  if ((ns->parent && ns->parent->proc_name->attr.flavor == FL_MODULE)
+       || ns->parent == NULL)
+    parent_fake_result_decl = NULL_TREE;
+
   gfc_generate_contained_functions (ns);
 
   generate_local_vars (ns);
+  
+  /* Keep the parent fake result declaration in module functions
+     or external procedures.  */
+  if ((ns->parent && ns->parent->proc_name->attr.flavor == FL_MODULE)
+       || ns->parent == NULL)
+    current_fake_result_decl = parent_fake_result_decl;
+  else
+    current_fake_result_decl = NULL_TREE;
 
   current_function_return_label = NULL;
 
   /* Now generate the code for the body of this function.  */
   gfc_init_block (&body);
 
-  /* If this is the main program and we compile with -pedantic, add a call
-     to set_std to set up the runtime library Fortran language standard
-     parameters.  */
-  if (sym->attr.is_main_program && pedantic)
-    {
-      tree arglist, gfc_int4_type_node;
-
-      gfc_int4_type_node = gfc_get_int_type (4);
-      arglist = gfc_chainon_list (NULL_TREE,
-                                 build_int_cst (gfc_int4_type_node,
-                                                gfc_option.warn_std));
-      arglist = gfc_chainon_list (arglist,
-                                 build_int_cst (gfc_int4_type_node,
-                                                gfc_option.allow_std));
-      tmp = gfc_build_function_call (gfor_fndecl_set_std, arglist);
+  /* If this is the main program, add a call to set_std to set up the
+     runtime library Fortran language standard parameters.  */
+
+  if (sym->attr.is_main_program)
+    {
+      tree gfc_int4_type_node = gfc_get_int_type (4);
+      tmp = build_call_expr (gfor_fndecl_set_std, 5,
+                            build_int_cst (gfc_int4_type_node,
+                                           gfc_option.warn_std),
+                            build_int_cst (gfc_int4_type_node,
+                                           gfc_option.allow_std),
+                            build_int_cst (gfc_int4_type_node,
+                                           pedantic),
+                            build_int_cst (gfc_int4_type_node,
+                                           gfc_option.flag_dump_core),
+                            build_int_cst (gfc_int4_type_node,
+                                           gfc_option.flag_backtrace));
       gfc_add_expr_to_block (&body, tmp);
     }
 
@@ -2566,13 +3122,46 @@ gfc_generate_function_code (gfc_namespace * ns)
      needed.  */
   if (sym->attr.is_main_program && gfc_option.fpe != 0)
     {
-      tree arglist, gfc_c_int_type_node;
+      tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
+      tmp = build_call_expr (gfor_fndecl_set_fpe, 1,
+                            build_int_cst (gfc_c_int_type_node,
+                                           gfc_option.fpe));
+      gfc_add_expr_to_block (&body, tmp);
+    }
+
+  /* If this is the main program and an -fconvert option was provided,
+     add a call to set_convert.  */
+
+  if (sym->attr.is_main_program && gfc_option.convert != CONVERT_NATIVE)
+    {
+      tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
+      tmp = build_call_expr (gfor_fndecl_set_convert, 1,
+                            build_int_cst (gfc_c_int_type_node,
+                                           gfc_option.convert));
+      gfc_add_expr_to_block (&body, tmp);
+    }
+
+  /* If this is the main program and an -frecord-marker option was provided,
+     add a call to set_record_marker.  */
+
+  if (sym->attr.is_main_program && gfc_option.record_marker != 0)
+    {
+      tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
+      tmp = build_call_expr (gfor_fndecl_set_record_marker, 1,
+                            build_int_cst (gfc_c_int_type_node,
+                                           gfc_option.record_marker));
+      gfc_add_expr_to_block (&body, tmp);
+    }
+
+  if (sym->attr.is_main_program && gfc_option.max_subrecord_length != 0)
+    {
+      tree gfc_c_int_type_node;
 
       gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind);
-      arglist = gfc_chainon_list (NULL_TREE,
-                                 build_int_cst (gfc_c_int_type_node,
-                                                gfc_option.fpe));
-      tmp = gfc_build_function_call (gfor_fndecl_set_fpe, arglist);
+      tmp = build_call_expr (gfor_fndecl_set_max_subrecord_length,
+                            1,
+                            build_int_cst (gfc_c_int_type_node,
+                                           gfc_option.max_subrecord_length));
       gfc_add_expr_to_block (&body, tmp);
     }
 
@@ -2580,7 +3169,7 @@ gfc_generate_function_code (gfc_namespace * ns)
       && sym->attr.subroutine)
     {
       tree alternate_return;
-      alternate_return = gfc_get_fake_result_decl (sym);
+      alternate_return = gfc_get_fake_result_decl (sym, 0);
       gfc_add_modify_expr (&body, alternate_return, integer_zero_node);
     }
 
@@ -2604,29 +3193,49 @@ gfc_generate_function_code (gfc_namespace * ns)
   tmp = gfc_finish_block (&body);
   /* Add code to create and cleanup arrays.  */
   tmp = gfc_trans_deferred_vars (sym, tmp);
-  gfc_add_expr_to_block (&block, tmp);
 
   if (TREE_TYPE (DECL_RESULT (fndecl)) != void_type_node)
     {
       if (sym->attr.subroutine || sym == sym->result)
        {
-         result = current_fake_result_decl;
+         if (current_fake_result_decl != NULL)
+           result = TREE_VALUE (current_fake_result_decl);
+         else
+           result = NULL_TREE;
          current_fake_result_decl = NULL_TREE;
        }
       else
        result = sym->result->backend_decl;
 
-      if (result == NULL_TREE)
+      if (result != NULL_TREE && sym->attr.function
+           && sym->ts.type == BT_DERIVED
+           && sym->ts.derived->attr.alloc_comp
+           && !sym->attr.pointer)
+       {
+         rank = sym->as ? sym->as->rank : 0;
+         tmp2 = gfc_nullify_alloc_comp (sym->ts.derived, result, rank);
+         gfc_add_expr_to_block (&block, tmp2);
+       }
+
+     gfc_add_expr_to_block (&block, tmp);
+
+     if (result == NULL_TREE)
        warning (0, "Function return value not set");
       else
        {
-         /* Set the return value to the dummy result variable.  */
-         tmp = build2 (MODIFY_EXPR, TREE_TYPE (result),
-                       DECL_RESULT (fndecl), result);
+         /* Set the return value to the dummy result variable.  The
+            types may be different for scalar default REAL functions
+            with -ff2c, therefore we have to convert.  */
+         tmp = convert (TREE_TYPE (DECL_RESULT (fndecl)), result);
+         tmp = build2 (MODIFY_EXPR, TREE_TYPE (tmp),
+                       DECL_RESULT (fndecl), tmp);
          tmp = build1_v (RETURN_EXPR, tmp);
          gfc_add_expr_to_block (&block, tmp);
        }
     }
+  else
+    gfc_add_expr_to_block (&block, tmp);
+
 
   /* Add all the decls we created during processing.  */
   decl = saved_function_decls;
@@ -2691,7 +3300,7 @@ gfc_generate_constructors (void)
   if (gfc_static_ctors == NULL_TREE)
     return;
 
-  fnname = get_file_function_name ('I');
+  fnname = get_file_function_name ("I");
   type = build_function_type (void_type_node,
                              gfc_chainon_list (NULL_TREE, void_type_node));
 
@@ -2718,8 +3327,7 @@ gfc_generate_constructors (void)
 
   for (; gfc_static_ctors; gfc_static_ctors = TREE_CHAIN (gfc_static_ctors))
     {
-      tmp =
-       gfc_build_function_call (TREE_VALUE (gfc_static_ctors), NULL_TREE);
+      tmp = build_call_expr (TREE_VALUE (gfc_static_ctors), 0);
       DECL_SAVED_TREE (fndecl) = build_stmt (EXPR_STMT, tmp);
     }