Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(revision 201977)
+++ gcc/fortran/trans-decl.c	(working copy)
@@ -2068,6 +2068,11 @@ create_function_arglist (gfc_symbol * sym)
 	      type = build_reference_type (type);
 	    }
 	}
+      else if (sym->attr.allocatable && !sym->attr.dimension)
+	{
+	  type = build_reference_type (type);
+	  type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
+	}
 
       parm = build_decl (input_location,
 			 PARM_DECL, get_identifier ("__result"), type);
@@ -3654,9 +3659,6 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gf
 	  else if (TREE_CODE (proc_sym->ts.u.cl->backend_decl) == VAR_DECL)
 	    gfc_trans_dummy_character (proc_sym, proc_sym->ts.u.cl, block);
 	}
-      else
-	gcc_assert (gfc_option.flag_f2c
-		    && proc_sym->ts.type == BT_COMPLEX);
     }
 
   /* Initialize the INTENT(OUT) derived type dummy arguments.  This
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 201977)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -1855,29 +1855,28 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
 	  /* Dereference non-character scalar dummy arguments.  */
 	  if (sym->attr.dummy && !sym->attr.dimension
 	      && !(sym->attr.codimension && sym->attr.allocatable))
-	    se->expr = build_fold_indirect_ref_loc (input_location,
-						se->expr);
+	    se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
 
           /* Dereference scalar hidden result.  */
 	  if (gfc_option.flag_f2c && sym->ts.type == BT_COMPLEX
 	      && (sym->attr.function || sym->attr.result)
 	      && !sym->attr.dimension && !sym->attr.pointer
 	      && !sym->attr.always_explicit)
-	    se->expr = build_fold_indirect_ref_loc (input_location,
-						se->expr);
+	    se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
 
+	  if (sym->attr.allocatable && !sym->attr.dimension
+	      && (sym->attr.function || sym->attr.result))
+	    se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
+
 	  /* Dereference non-character pointer variables.
 	     These must be dummies, results, or scalars.  */
 	  if ((sym->attr.pointer || sym->attr.allocatable
 	       || gfc_is_associate_pointer (sym)
 	       || (sym->as && sym->as->type == AS_ASSUMED_RANK))
-	      && (sym->attr.dummy
-		  || sym->attr.function
-		  || sym->attr.result
+	      && (sym->attr.dummy || sym->attr.function || sym->attr.result
 		  || (!sym->attr.dimension
 		      && (!sym->attr.codimension || !sym->attr.allocatable))))
-	    se->expr = build_fold_indirect_ref_loc (input_location,
-						se->expr);
+	    se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
 	}
 
       ref = expr->ref;
@@ -4887,8 +4886,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
       len = cl.backend_decl;
     }
 
-  byref = (comp && (comp->attr.dimension || comp->ts.type == BT_CHARACTER))
-	  || (!comp && gfc_return_by_reference (sym));
+  byref = (comp && (comp->attr.dimension || comp->attr.allocatable
+		    || comp->ts.type == BT_CHARACTER))
+	   || (!comp && gfc_return_by_reference (sym));
   if (byref)
     {
       if (se->direct_byref)
@@ -5000,6 +5000,24 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
 	  tmp = gfc_build_addr_expr (NULL_TREE, result);
 	  vec_safe_push (retargs, tmp);
 	}
+      else if (!comp && sym->result->attr.allocatable)
+	{
+	  /* Allocatable scalar result variable: Temporary passed as argument.  */
+	  type = gfc_typenode_for_spec (&sym->result->ts);
+	  type = build_pointer_type (type);
+	  var = gfc_create_var (type, "asr");
+	  var = gfc_build_addr_expr (NULL_TREE, var);
+	  vec_safe_push (retargs, var);
+	}
+      else if (comp && comp->attr.allocatable)
+	{
+	  /* Allocatable scalar result variable: Temporary passed as argument.  */
+	  type = gfc_typenode_for_spec (&comp->ts);
+	  type = build_pointer_type (type);
+	  var = gfc_create_var (type, "asr");
+	  var = gfc_build_addr_expr (NULL_TREE, var);
+	  vec_safe_push (retargs, var);
+	}
       else if (ts.type == BT_CHARACTER)
 	{
 	  /* Pass the string length.  */
@@ -5129,6 +5147,18 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
 
   if (byref)
     {
+      if ((!comp && !sym->result->attr.dimension && sym->result->attr.allocatable)
+	  || (comp && !comp->attr.dimension && comp->attr.allocatable))
+	{
+	  /* Nullify allocatable-scalar-result temporary.  */
+	  var = build_fold_indirect_ref_loc (input_location, var);
+	  tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+				 TREE_TYPE (var), var,
+				 fold_convert (TREE_TYPE (var),
+					       null_pointer_node));
+	  gfc_add_expr_to_block (&se->pre, tmp);
+	}
+
       /* Add the function call to the pre chain.  There is no expression.  */
       gfc_add_expr_to_block (&se->pre, se->expr);
       se->expr = NULL_TREE;
@@ -5164,10 +5194,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
 	      se->string_length = len;
 	    }
 	  else
-	    {
-	      gcc_assert (ts.type == BT_COMPLEX && gfc_option.flag_f2c);
-	      se->expr = build_fold_indirect_ref_loc (input_location, var);
-	    }
+	    se->expr = build_fold_indirect_ref_loc (input_location, var);
 	}
     }
 
@@ -5204,6 +5231,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
 					    NULL, false);
 	  gfc_add_expr_to_block (&se->pre, tmp);
 	}
+
+      if (!comp
+	  && !sym->result->attr.dimension && sym->result->attr.allocatable)
+	{
+	  /* Deallocate allocatable-scalar-result temporary.  */
+	  tmp = gfc_deallocate_scalar_with_status (var, NULL_TREE, true,
+						   NULL, sym->result->ts);
+	  gfc_add_expr_to_block (&se->post, tmp);
+	}
     }
   else
     gfc_add_block_to_block (&se->post, &post);
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c	(revision 201977)
+++ gcc/fortran/trans-types.c	(working copy)
@@ -2586,7 +2586,7 @@ gfc_return_by_reference (gfc_symbol * sym)
   if (!sym->attr.function)
     return 0;
 
-  if (sym->attr.dimension)
+  if (sym->attr.dimension || sym->attr.allocatable)
     return 1;
 
   if (sym->ts.type == BT_CHARACTER
