OSDN Git Service

PR fortran/50409
[pf3gnuchains/gcc-fork.git] / gcc / fortran / matchexp.c
index 539a91a..cd70dc0 100644 (file)
@@ -1,12 +1,13 @@
 /* Expression parser.
-   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,18 +16,16 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
-
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
-#include <string.h>
+#include "system.h"
 #include "gfortran.h"
 #include "arith.h"
 #include "match.h"
 
-static char expression_syntax[] = "Syntax error in expression at %C";
+static char expression_syntax[] = N_("Syntax error in expression at %C");
 
 
 /* Match a user-defined operator name.  This is a normal name with a
@@ -46,7 +45,7 @@ gfc_match_defined_op_name (char *result, int error_flag)
   match m;
   int i;
 
-  old_loc = *gfc_current_locus ();
+  old_loc = gfc_current_locus;
 
   m = gfc_match (" . %n .", name);
   if (m != MATCH_YES)
@@ -59,7 +58,7 @@ gfc_match_defined_op_name (char *result, int error_flag)
     {
       if (error_flag)
        goto error;
-      gfc_set_locus (&old_loc);
+      gfc_current_locus = old_loc;
       return MATCH_NO;
     }
 
@@ -81,7 +80,7 @@ error:
   gfc_error ("The name '%s' cannot be used as a defined operator at %C",
             name);
 
-  gfc_set_locus (&old_loc);
+  gfc_current_locus = old_loc;
   return MATCH_ERROR;
 }
 
@@ -90,7 +89,7 @@ error:
    operator already.  */
 
 static match
-match_defined_operator (gfc_user_op ** result)
+match_defined_operator (gfc_user_op **result)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
   match m;
@@ -113,21 +112,39 @@ next_operator (gfc_intrinsic_op t)
   gfc_intrinsic_op u;
   locus old_loc;
 
-  old_loc = *gfc_current_locus ();
+  old_loc = gfc_current_locus;
   if (gfc_match_intrinsic_op (&u) == MATCH_YES && t == u)
     return 1;
 
-  gfc_set_locus (&old_loc);
+  gfc_current_locus = old_loc;
   return 0;
 }
 
 
+/* Call the INTRINSIC_PARENTHESES function.  This is both
+   used explicitly, as below, or by resolve.c to generate
+   temporaries.  */
+
+gfc_expr *
+gfc_get_parentheses (gfc_expr *e)
+{
+  gfc_expr *e2;
+
+  e2 = gfc_get_operator_expr (&e->where, INTRINSIC_PARENTHESES, e, NULL);
+  e2->ts = e->ts;
+  e2->rank = e->rank;
+
+  return e2;
+}
+
+
 /* Match a primary expression.  */
 
 static match
-match_primary (gfc_expr ** result)
+match_primary (gfc_expr **result)
 {
   match m;
+  gfc_expr *e;
 
   m = gfc_match_literal_constant (result, 0);
   if (m != MATCH_NO)
@@ -141,11 +158,11 @@ match_primary (gfc_expr ** result)
   if (m != MATCH_NO)
     return m;
 
-  /* Match an expression in parenthesis.  */
+  /* Match an expression in parentheses.  */
   if (gfc_match_char ('(') != MATCH_YES)
     return MATCH_NO;
 
-  m = gfc_match_expr (result);
+  m = gfc_match_expr (&e);
   if (m == MATCH_NO)
     goto syntax;
   if (m == MATCH_ERROR)
@@ -155,6 +172,11 @@ match_primary (gfc_expr ** result)
   if (m == MATCH_NO)
     gfc_error ("Expected a right parenthesis in expression at %C");
 
+  /* Now we have the expression inside the parentheses, build the
+     expression pointing to it. By 7.1.7.2, any expression in
+     parentheses shall be treated as a data entity.  */
+  *result = gfc_get_parentheses (e);
+
   if (m != MATCH_YES)
     {
       gfc_free_expr (*result);
@@ -169,37 +191,18 @@ syntax:
 }
 
 
-/* Build an operator expression node.  */
-
-static gfc_expr *
-build_node (gfc_intrinsic_op operator, locus * where,
-           gfc_expr * op1, gfc_expr * op2)
-{
-  gfc_expr *new;
-
-  new = gfc_get_expr ();
-  new->expr_type = EXPR_OP;
-  new->operator = operator;
-  new->where = *where;
-
-  new->op1 = op1;
-  new->op2 = op2;
-
-  return new;
-}
-
-
 /* Match a level 1 expression.  */
 
 static match
-match_level_1 (gfc_expr ** result)
+match_level_1 (gfc_expr **result)
 {
   gfc_user_op *uop;
   gfc_expr *e, *f;
   locus where;
   match m;
 
-  where = *gfc_current_locus ();
+  gfc_gobble_whitespace ();
+  where = gfc_current_locus;
   uop = NULL;
   m = match_defined_operator (&uop);
   if (m == MATCH_ERROR)
@@ -213,8 +216,8 @@ match_level_1 (gfc_expr ** result)
     *result = e;
   else
     {
-      f = build_node (INTRINSIC_USER, &where, e, NULL);
-      f->uop = uop;
+      f = gfc_get_operator_expr (&where, INTRINSIC_USER, e, NULL);
+      f->value.op.uop = uop;
       *result = f;
     }
 
@@ -225,7 +228,7 @@ match_level_1 (gfc_expr ** result)
 /* As a GNU extension we support an expanded level-2 expression syntax.
    Via this extension we support (arbitrary) nesting of unary plus and
    minus operations following unary and binary operators, such as **.
-   The grammar of section 7.1.1.3 is effectively rewitten as:
+   The grammar of section 7.1.1.3 is effectively rewritten as:
 
        R704  mult-operand     is level-1-expr [ power-op ext-mult-operand ]
        R704' ext-mult-operand is add-op ext-mult-operand
@@ -238,14 +241,12 @@ match_level_1 (gfc_expr ** result)
                               or add-operand
  */
 
-static match match_ext_mult_operand (gfc_expr ** result);
-static match match_ext_add_operand (gfc_expr ** result);
-
+static match match_ext_mult_operand (gfc_expr **result);
+static match match_ext_add_operand (gfc_expr **result);
 
 static int
 match_add_op (void)
 {
-
   if (next_operator (INTRINSIC_MINUS))
     return -1;
   if (next_operator (INTRINSIC_PLUS))
@@ -255,7 +256,7 @@ match_add_op (void)
 
 
 static match
-match_mult_operand (gfc_expr ** result)
+match_mult_operand (gfc_expr **result)
 {
   gfc_expr *e, *exp, *r;
   locus where;
@@ -271,7 +272,7 @@ match_mult_operand (gfc_expr ** result)
       return MATCH_YES;
     }
 
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
 
   m = match_ext_mult_operand (&exp);
   if (m == MATCH_NO)
@@ -298,23 +299,28 @@ match_mult_operand (gfc_expr ** result)
 
 
 static match
-match_ext_mult_operand (gfc_expr ** result)
+match_ext_mult_operand (gfc_expr **result)
 {
   gfc_expr *all, *e;
   locus where;
   match m;
   int i;
 
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
   i = match_add_op ();
 
   if (i == 0)
     return match_mult_operand (result);
 
-  if (gfc_notify_std (GFC_STD_GNU, "Extension: Unary operator following"
-                     " arithmetic operator (use parentheses) at %C")
-      == FAILURE)
-    return MATCH_ERROR;
+  if (gfc_notification_std (GFC_STD_GNU) == ERROR)
+    {
+      gfc_error ("Extension: Unary operator following "
+                "arithmetic operator (use parentheses) at %C");
+      return MATCH_ERROR;
+    }
+  else
+    gfc_warning ("Extension: Unary operator following "
+                "arithmetic operator (use parentheses) at %C");
 
   m = match_ext_mult_operand (&e);
   if (m != MATCH_YES)
@@ -338,7 +344,7 @@ match_ext_mult_operand (gfc_expr ** result)
 
 
 static match
-match_add_operand (gfc_expr ** result)
+match_add_operand (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where, old_loc;
@@ -353,7 +359,7 @@ match_add_operand (gfc_expr ** result)
     {
       /* Build up a string of products or quotients.  */
 
-      old_loc = *gfc_current_locus ();
+      old_loc = gfc_current_locus;
 
       if (next_operator (INTRINSIC_TIMES))
        i = INTRINSIC_TIMES;
@@ -365,12 +371,12 @@ match_add_operand (gfc_expr ** result)
            break;
        }
 
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_ext_mult_operand (&e);
       if (m == MATCH_NO)
        {
-         gfc_set_locus (&old_loc);
+         gfc_current_locus = old_loc;
          break;
        }
 
@@ -402,23 +408,28 @@ match_add_operand (gfc_expr ** result)
 
 
 static match
-match_ext_add_operand (gfc_expr ** result)
+match_ext_add_operand (gfc_expr **result)
 {
   gfc_expr *all, *e;
   locus where;
   match m;
   int i;
 
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
   i = match_add_op ();
 
   if (i == 0)
     return match_add_operand (result);
 
-  if (gfc_notify_std (GFC_STD_GNU, "Extension: Unary operator following"
-                     " arithmetic operator (use parentheses) at %C")
-      == FAILURE)
-    return MATCH_ERROR;
+  if (gfc_notification_std (GFC_STD_GNU) == ERROR)
+    {
+      gfc_error ("Extension: Unary operator following "
+                "arithmetic operator (use parentheses) at %C");
+      return MATCH_ERROR;
+    }
+  else
+    gfc_warning ("Extension: Unary operator following "
+               "arithmetic operator (use parentheses) at %C");
 
   m = match_ext_add_operand (&e);
   if (m != MATCH_YES)
@@ -444,14 +455,14 @@ match_ext_add_operand (gfc_expr ** result)
 /* Match a level 2 expression.  */
 
 static match
-match_level_2 (gfc_expr ** result)
+match_level_2 (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where;
   match m;
   int i;
 
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
   i = match_add_op ();
 
   if (i != 0)
@@ -487,11 +498,11 @@ match_level_2 (gfc_expr ** result)
 
   all->where = where;
 
-/* Append add-operands to the sum */
+  /* Append add-operands to the sum.  */
 
   for (;;)
     {
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
       i = match_add_op ();
       if (i == 0)
        break;
@@ -529,7 +540,7 @@ match_level_2 (gfc_expr ** result)
 /* Match a level three expression.  */
 
 static match
-match_level_3 (gfc_expr ** result)
+match_level_3 (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where;
@@ -544,7 +555,7 @@ match_level_3 (gfc_expr ** result)
       if (!next_operator (INTRINSIC_CONCAT))
        break;
 
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_level_2 (&e);
       if (m == MATCH_NO)
@@ -575,7 +586,7 @@ match_level_3 (gfc_expr ** result)
 /* Match a level 4 expression.  */
 
 static match
-match_level_4 (gfc_expr ** result)
+match_level_4 (gfc_expr **result)
 {
   gfc_expr *left, *right, *r;
   gfc_intrinsic_op i;
@@ -587,7 +598,7 @@ match_level_4 (gfc_expr ** result)
   if (m != MATCH_YES)
     return m;
 
-  old_loc = *gfc_current_locus ();
+  old_loc = gfc_current_locus;
 
   if (gfc_match_intrinsic_op (&i) != MATCH_YES)
     {
@@ -596,14 +607,16 @@ match_level_4 (gfc_expr ** result)
     }
 
   if (i != INTRINSIC_EQ && i != INTRINSIC_NE && i != INTRINSIC_GE
-      && i != INTRINSIC_LE && i != INTRINSIC_LT && i != INTRINSIC_GT)
+      && i != INTRINSIC_LE && i != INTRINSIC_LT && i != INTRINSIC_GT
+      && i != INTRINSIC_EQ_OS && i != INTRINSIC_NE_OS && i != INTRINSIC_GE_OS
+      && i != INTRINSIC_LE_OS && i != INTRINSIC_LT_OS && i != INTRINSIC_GT_OS)
     {
-      gfc_set_locus (&old_loc);
+      gfc_current_locus = old_loc;
       *result = left;
       return MATCH_YES;
     }
 
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
 
   m = match_level_3 (&right);
   if (m == MATCH_NO)
@@ -617,27 +630,33 @@ match_level_4 (gfc_expr ** result)
   switch (i)
     {
     case INTRINSIC_EQ:
-      r = gfc_eq (left, right);
+    case INTRINSIC_EQ_OS:
+      r = gfc_eq (left, right, i);
       break;
 
     case INTRINSIC_NE:
-      r = gfc_ne (left, right);
+    case INTRINSIC_NE_OS:
+      r = gfc_ne (left, right, i);
       break;
 
     case INTRINSIC_LT:
-      r = gfc_lt (left, right);
+    case INTRINSIC_LT_OS:
+      r = gfc_lt (left, right, i);
       break;
 
     case INTRINSIC_LE:
-      r = gfc_le (left, right);
+    case INTRINSIC_LE_OS:
+      r = gfc_le (left, right, i);
       break;
 
     case INTRINSIC_GT:
-      r = gfc_gt (left, right);
+    case INTRINSIC_GT_OS:
+      r = gfc_gt (left, right, i);
       break;
 
     case INTRINSIC_GE:
-      r = gfc_ge (left, right);
+    case INTRINSIC_GE_OS:
+      r = gfc_ge (left, right, i);
       break;
 
     default:
@@ -659,7 +678,7 @@ match_level_4 (gfc_expr ** result)
 
 
 static match
-match_and_operand (gfc_expr ** result)
+match_and_operand (gfc_expr **result)
 {
   gfc_expr *e, *r;
   locus where;
@@ -667,7 +686,7 @@ match_and_operand (gfc_expr ** result)
   int i;
 
   i = next_operator (INTRINSIC_NOT);
-  where = *gfc_current_locus ();
+  where = gfc_current_locus;
 
   m = match_level_4 (&e);
   if (m != MATCH_YES)
@@ -692,7 +711,7 @@ match_and_operand (gfc_expr ** result)
 
 
 static match
-match_or_operand (gfc_expr ** result)
+match_or_operand (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where;
@@ -706,7 +725,7 @@ match_or_operand (gfc_expr ** result)
     {
       if (!next_operator (INTRINSIC_AND))
        break;
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_and_operand (&e);
       if (m == MATCH_NO)
@@ -735,7 +754,7 @@ match_or_operand (gfc_expr ** result)
 
 
 static match
-match_equiv_operand (gfc_expr ** result)
+match_equiv_operand (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where;
@@ -749,7 +768,7 @@ match_equiv_operand (gfc_expr ** result)
     {
       if (!next_operator (INTRINSIC_OR))
        break;
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_or_operand (&e);
       if (m == MATCH_NO)
@@ -780,7 +799,7 @@ match_equiv_operand (gfc_expr ** result)
 /* Match a level 5 expression.  */
 
 static match
-match_level_5 (gfc_expr ** result)
+match_level_5 (gfc_expr **result)
 {
   gfc_expr *all, *e, *total;
   locus where;
@@ -803,7 +822,7 @@ match_level_5 (gfc_expr ** result)
            break;
        }
 
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_equiv_operand (&e);
       if (m == MATCH_NO)
@@ -839,7 +858,7 @@ match_level_5 (gfc_expr ** result)
    level 5 expressions separated by binary operators.  */
 
 match
-gfc_match_expr (gfc_expr ** result)
+gfc_match_expr (gfc_expr **result)
 {
   gfc_expr *all, *e;
   gfc_user_op *uop;
@@ -852,6 +871,7 @@ gfc_match_expr (gfc_expr ** result)
 
   for (;;)
     {
+      uop = NULL;
       m = match_defined_operator (&uop);
       if (m == MATCH_NO)
        break;
@@ -861,7 +881,7 @@ gfc_match_expr (gfc_expr ** result)
          return MATCH_ERROR;
        }
 
-      where = *gfc_current_locus ();
+      where = gfc_current_locus;
 
       m = match_level_5 (&e);
       if (m == MATCH_NO)
@@ -872,8 +892,8 @@ gfc_match_expr (gfc_expr ** result)
          return MATCH_ERROR;
        }
 
-      all = build_node (INTRINSIC_USER, &where, all, e);
-      all->uop = uop;
+      all = gfc_get_operator_expr (&where, INTRINSIC_USER, all, e);
+      all->value.op.uop = uop;
     }
 
   *result = all;