diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c12809706777e448c7877ad8a7142644462001f4..77ec5111a4d4ee96ced8d3bf071881f183bb7a77 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2007-07-04  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+	PR fortran/31198
+	* trans-intrinsic.c (trans-intrinsic.c): Handle optional
+	arguments correctly for MIN and MAX intrinsics.
+
 2007-07-03  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR fortran/32545
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 874b1081de668d91aafed493e7f326dac7b85b4b..8856f1965af8f4e9bab170bf92344e0cf1e167bb 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -1381,12 +1381,51 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op)
   tree val;
   tree thencase;
   tree elsecase;
-  tree arg;
+  tree arg, arg1, arg2;
   tree type;
+  gfc_actual_arglist *argexpr;
+  unsigned int i;
 
   arg = gfc_conv_intrinsic_function_args (se, expr);
+  arg1 = TREE_VALUE (arg);
+  arg2 = TREE_VALUE (TREE_CHAIN (arg));
   type = gfc_typenode_for_spec (&expr->ts);
 
+  /* The first and second arguments should be present, if they are
+     optional dummy arguments.  */
+  argexpr = expr->value.function.actual;
+  if (argexpr->expr->expr_type == EXPR_VARIABLE
+      && argexpr->expr->symtree->n.sym->attr.optional
+      && TREE_CODE (arg1) == INDIRECT_REF)
+    {
+      /* Check the first argument.  */
+      tree cond;
+      char *msg;
+
+      asprintf (&msg, "First argument of '%s' intrinsic should be present",
+		expr->symtree->n.sym->name);
+      cond = build2 (EQ_EXPR, boolean_type_node, TREE_OPERAND (arg1, 0),
+		     build_int_cst (TREE_TYPE (TREE_OPERAND (arg1, 0)), 0));
+      gfc_trans_runtime_check (cond, msg, &se->pre, &expr->where);
+      gfc_free (msg);
+    }
+
+  if (argexpr->next->expr->expr_type == EXPR_VARIABLE
+      && argexpr->next->expr->symtree->n.sym->attr.optional
+      && TREE_CODE (arg2) == INDIRECT_REF)
+    {
+      /* Check the second argument.  */
+      tree cond;
+      char *msg;
+
+      asprintf (&msg, "Second argument of '%s' intrinsic should be present",
+		expr->symtree->n.sym->name);
+      cond = build2 (EQ_EXPR, boolean_type_node, TREE_OPERAND (arg2, 0),
+		     build_int_cst (TREE_TYPE (TREE_OPERAND (arg2, 0)), 0));
+      gfc_trans_runtime_check (cond, msg, &se->pre, &expr->where);
+      gfc_free (msg);
+    }
+
   limit = TREE_VALUE (arg);
   if (TREE_TYPE (limit) != type)
     limit = convert (type, limit);
@@ -1396,23 +1435,40 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op)
 
   mvar = gfc_create_var (type, "M");
   elsecase = build2_v (MODIFY_EXPR, mvar, limit);
-  for (arg = TREE_CHAIN (arg); arg != NULL_TREE; arg = TREE_CHAIN (arg))
+  for (arg = TREE_CHAIN (arg), i = 0, argexpr = argexpr->next;
+       arg != NULL_TREE; arg = TREE_CHAIN (arg), i++)
     {
+      tree cond;
+
       val = TREE_VALUE (arg);
-      if (TREE_TYPE (val) != type)
-	val = convert (type, val);
 
-      /* Only evaluate the argument once.  */
-      if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
-        val = gfc_evaluate_now (val, &se->pre);
+      /* Handle absent optional arguments by ignoring the comparison.  */
+      if (i > 0 && argexpr->expr->expr_type == EXPR_VARIABLE
+	  && argexpr->expr->symtree->n.sym->attr.optional
+	  && TREE_CODE (val) == INDIRECT_REF)
+	cond = build2 (NE_EXPR, boolean_type_node, TREE_OPERAND (val, 0),
+		       build_int_cst (TREE_TYPE (TREE_OPERAND (val, 0)), 0));
+      else
+      {
+	cond = NULL_TREE;
+
+	/* Only evaluate the argument once.  */
+	if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))
+	  val = gfc_evaluate_now (val, &se->pre);
+      }
 
       thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));
 
-      tmp = build2 (op, boolean_type_node, val, limit);
+      tmp = build2 (op, boolean_type_node, convert (type, val), limit);
       tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
+
+      if (cond != NULL_TREE)
+	tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
+
       gfc_add_expr_to_block (&se->pre, tmp);
       elsecase = build_empty_stmt ();
       limit = mvar;
+      argexpr = argexpr->next;
     }
   se->expr = mvar;
 }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 77dc469169e29b93f872faba4791d9ab0d57686f..71c389afc87d8d97c443cd88adce2d506dfff0f4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2007-07-04  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+	PR fortran/31198
+	* gfortran.dg/min_max_optional_1.f90: New test.
+	* gfortran.dg/min_max_optional_2.f90: New test.
+	* gfortran.dg/min_max_optional_3.f90: New test.
+
 2007-07-03  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR fortran/32545
@@ -16,7 +23,7 @@
 2007-07-03  Christopher D. Rickett  <crickett@lanl.gov>
 
 	PR fortran/32579
-        * gfortran.dg/iso_c_binding_only.f03: Updated test case.
+	* gfortran.dg/iso_c_binding_only.f03: Updated test case.
 
 2007-07-03  Tobias Burnus  <burnus@net-b.de>
 
diff --git a/gcc/testsuite/gfortran.dg/min_max_optional_1.f90 b/gcc/testsuite/gfortran.dg/min_max_optional_1.f90
new file mode 100644
index 0000000000000000000000000000000000000000..250010dffb966b15b8d096a38da5e552d45b0ad4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/min_max_optional_1.f90
@@ -0,0 +1,20 @@
+! { dg-do run }
+IF (T1(1.0,1.0) .NE. (1.0,1.0) ) CALL ABORT()
+IF (T1(1.0) .NE. (1.0,0.0)) CALL ABORT()
+IF (M1(1,2,3) .NE. 3) CALL ABORT()
+IF (M1(1,2,A4=4) .NE. 4) CALL ABORT()
+CONTAINS
+
+COMPLEX FUNCTION T1(X,Y)
+  REAL :: X
+  REAL, OPTIONAL :: Y
+  T1=CMPLX(X,Y)
+END FUNCTION T1
+
+INTEGER FUNCTION M1(A1,A2,A3,A4)
+  INTEGER :: A1,A2
+  INTEGER, OPTIONAL :: A3,A4
+  M1=MAX(A1,A2,A3,A4)
+END FUNCTION M1
+
+END
diff --git a/gcc/testsuite/gfortran.dg/min_max_optional_2.f90 b/gcc/testsuite/gfortran.dg/min_max_optional_2.f90
new file mode 100644
index 0000000000000000000000000000000000000000..51e0feee641a8f2f22a20f8f966de96ea42446ec
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/min_max_optional_2.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! { dg-shouldfail "" }
+  program test 
+    if (m1(3,4) /= 4) call abort
+    if (m1(3) /= 3) call abort
+    print *, m1() 
+  contains 
+    integer function m1(a1,a2) 
+      integer, optional :: a1,a2 
+      m1 = max(a2, a1, 1, 2) 
+    end function m1 
+  end 
+! { dg-output "First argument of 'max' intrinsic should be present" }
diff --git a/gcc/testsuite/gfortran.dg/min_max_optional_3.f90 b/gcc/testsuite/gfortran.dg/min_max_optional_3.f90
new file mode 100644
index 0000000000000000000000000000000000000000..e0e6e29d969d6a11db844b26b27d17565c1e9600
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/min_max_optional_3.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! { dg-shouldfail "" }
+  program test 
+    if (m1(1,2,3,4) /= 1) call abort
+    if (m1(1,2,3) /= 1) call abort
+    if (m1(1,2) /= 1) call abort
+    print *, m1(1) 
+    print *, m1() 
+  contains 
+    integer function m1(a1,a2,a3,a4) 
+      integer, optional :: a1,a2,a3,a4 
+      m1 = min(a1,a2,a3,a4) ! { dg-output "Second argument of 'min' intrinsic should be present" }
+    end function m1 
+  end