xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/c-family/c-semantics.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* This file contains subroutine used by the C front-end to construct GENERIC.
2*8feb0f0bSmrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Written by Benjamin Chelf (chelf@codesourcery.com).
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg #include "config.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "c-common.h"
251debfc3dSmrg #include "tree-iterator.h"
261debfc3dSmrg 
271debfc3dSmrg /* Create an empty statement tree rooted at T.  */
281debfc3dSmrg 
291debfc3dSmrg tree
push_stmt_list(void)301debfc3dSmrg push_stmt_list (void)
311debfc3dSmrg {
321debfc3dSmrg   tree t;
331debfc3dSmrg   t = alloc_stmt_list ();
341debfc3dSmrg   vec_safe_push (stmt_list_stack, t);
351debfc3dSmrg   return t;
361debfc3dSmrg }
371debfc3dSmrg 
38a2dc1f3fSmrg /* Return TRUE if, after I, there are any nondebug stmts.  */
39a2dc1f3fSmrg 
40a2dc1f3fSmrg static inline bool
only_debug_stmts_after_p(tree_stmt_iterator i)41a2dc1f3fSmrg only_debug_stmts_after_p (tree_stmt_iterator i)
42a2dc1f3fSmrg {
43a2dc1f3fSmrg   for (tsi_next (&i); !tsi_end_p (i); tsi_next (&i))
44a2dc1f3fSmrg     if (TREE_CODE (tsi_stmt (i)) != DEBUG_BEGIN_STMT)
45a2dc1f3fSmrg       return false;
46a2dc1f3fSmrg   return true;
47a2dc1f3fSmrg }
48a2dc1f3fSmrg 
491debfc3dSmrg /* Finish the statement tree rooted at T.  */
501debfc3dSmrg 
511debfc3dSmrg tree
pop_stmt_list(tree t)521debfc3dSmrg pop_stmt_list (tree t)
531debfc3dSmrg {
541debfc3dSmrg   tree u = NULL_TREE;
551debfc3dSmrg 
561debfc3dSmrg   /* Pop statement lists until we reach the target level.  The extra
571debfc3dSmrg      nestings will be due to outstanding cleanups.  */
581debfc3dSmrg   while (1)
591debfc3dSmrg     {
601debfc3dSmrg       u = stmt_list_stack->pop ();
611debfc3dSmrg       if (!stmt_list_stack->is_empty ())
621debfc3dSmrg 	{
631debfc3dSmrg 	  tree x = stmt_list_stack->last ();
641debfc3dSmrg 	  STATEMENT_LIST_HAS_LABEL (x) |= STATEMENT_LIST_HAS_LABEL (u);
651debfc3dSmrg 	}
661debfc3dSmrg       if (t == u)
671debfc3dSmrg 	break;
681debfc3dSmrg     }
691debfc3dSmrg 
701debfc3dSmrg   gcc_assert (u != NULL_TREE);
711debfc3dSmrg 
721debfc3dSmrg   /* If the statement list is completely empty, just return it.  This is
731debfc3dSmrg      just as good small as build_empty_stmt, with the advantage that
741debfc3dSmrg      statement lists are merged when they appended to one another.  So
751debfc3dSmrg      using the STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P
761debfc3dSmrg      statements.  */
771debfc3dSmrg   if (TREE_SIDE_EFFECTS (t))
781debfc3dSmrg     {
791debfc3dSmrg       tree_stmt_iterator i = tsi_start (t);
801debfc3dSmrg 
811debfc3dSmrg       /* If the statement list contained exactly one statement, then
821debfc3dSmrg 	 extract it immediately.  */
831debfc3dSmrg       if (tsi_one_before_end_p (i))
841debfc3dSmrg 	{
851debfc3dSmrg 	  u = tsi_stmt (i);
861debfc3dSmrg 	  tsi_delink (&i);
871debfc3dSmrg 	  free_stmt_list (t);
881debfc3dSmrg 	  t = u;
891debfc3dSmrg 	}
90a2dc1f3fSmrg       /* If the statement list contained a debug begin stmt and a
91a2dc1f3fSmrg 	 statement list, move the debug begin stmt into the statement
92a2dc1f3fSmrg 	 list and return it.  */
93a2dc1f3fSmrg       else if (!tsi_end_p (i)
94a2dc1f3fSmrg 	       && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
95a2dc1f3fSmrg 	{
96a2dc1f3fSmrg 	  u = tsi_stmt (i);
97a2dc1f3fSmrg 	  tsi_next (&i);
98a2dc1f3fSmrg 	  if (tsi_one_before_end_p (i)
99a2dc1f3fSmrg 	      && TREE_CODE (tsi_stmt (i)) == STATEMENT_LIST)
100a2dc1f3fSmrg 	    {
101a2dc1f3fSmrg 	      tree l = tsi_stmt (i);
102a2dc1f3fSmrg 	      tsi_prev (&i);
103a2dc1f3fSmrg 	      tsi_delink (&i);
104a2dc1f3fSmrg 	      tsi_delink (&i);
105a2dc1f3fSmrg 	      i = tsi_start (l);
106a2dc1f3fSmrg 	      free_stmt_list (t);
107a2dc1f3fSmrg 	      t = l;
108a2dc1f3fSmrg 	      tsi_link_before (&i, u, TSI_SAME_STMT);
109a2dc1f3fSmrg 	    }
110a2dc1f3fSmrg 	  while (!tsi_end_p (i)
111a2dc1f3fSmrg 		 && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
112a2dc1f3fSmrg 	    tsi_next (&i);
113a2dc1f3fSmrg 	  /* If there are only debug stmts in the list, without them
114a2dc1f3fSmrg 	     we'd have an empty stmt without side effects.  If there's
115a2dc1f3fSmrg 	     only one nondebug stmt, we'd have extracted the stmt and
116a2dc1f3fSmrg 	     dropped the list, and we'd take TREE_SIDE_EFFECTS from
117a2dc1f3fSmrg 	     that statement.  In either case, keep the list's
118a2dc1f3fSmrg 	     TREE_SIDE_EFFECTS in sync.  */
119a2dc1f3fSmrg 	  if (tsi_end_p (i))
120a2dc1f3fSmrg 	    TREE_SIDE_EFFECTS (t) = 0;
121a2dc1f3fSmrg 	  else if (only_debug_stmts_after_p (i))
122a2dc1f3fSmrg 	    TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (tsi_stmt (i));
123a2dc1f3fSmrg 	}
1241debfc3dSmrg     }
1251debfc3dSmrg 
1261debfc3dSmrg   return t;
1271debfc3dSmrg }
1281debfc3dSmrg 
1291debfc3dSmrg /* Build a generic statement based on the given type of node and
1301debfc3dSmrg    arguments. Similar to `build_nt', except that we set
1311debfc3dSmrg    EXPR_LOCATION to LOC. */
1321debfc3dSmrg /* ??? This should be obsolete with the lineno_stmt productions
1331debfc3dSmrg    in the grammar.  */
1341debfc3dSmrg 
1351debfc3dSmrg tree
build_stmt(location_t loc,enum tree_code code,...)1361debfc3dSmrg build_stmt (location_t loc, enum tree_code code, ...)
1371debfc3dSmrg {
1381debfc3dSmrg   tree ret;
1391debfc3dSmrg   int length, i;
1401debfc3dSmrg   va_list p;
1411debfc3dSmrg   bool side_effects;
1421debfc3dSmrg 
1431debfc3dSmrg   /* This function cannot be used to construct variably-sized nodes.  */
1441debfc3dSmrg   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
1451debfc3dSmrg 
1461debfc3dSmrg   va_start (p, code);
1471debfc3dSmrg 
1481debfc3dSmrg   ret = make_node (code);
1491debfc3dSmrg   TREE_TYPE (ret) = void_type_node;
1501debfc3dSmrg   length = TREE_CODE_LENGTH (code);
1511debfc3dSmrg   SET_EXPR_LOCATION (ret, loc);
1521debfc3dSmrg 
1531debfc3dSmrg   /* TREE_SIDE_EFFECTS will already be set for statements with
1541debfc3dSmrg      implicit side effects.  Here we make sure it is set for other
1551debfc3dSmrg      expressions by checking whether the parameters have side
1561debfc3dSmrg      effects.  */
1571debfc3dSmrg 
1581debfc3dSmrg   side_effects = false;
1591debfc3dSmrg   for (i = 0; i < length; i++)
1601debfc3dSmrg     {
1611debfc3dSmrg       tree t = va_arg (p, tree);
1621debfc3dSmrg       if (t && !TYPE_P (t))
1631debfc3dSmrg 	side_effects |= TREE_SIDE_EFFECTS (t);
1641debfc3dSmrg       TREE_OPERAND (ret, i) = t;
1651debfc3dSmrg     }
1661debfc3dSmrg 
1671debfc3dSmrg   TREE_SIDE_EFFECTS (ret) |= side_effects;
1681debfc3dSmrg 
1691debfc3dSmrg   va_end (p);
1701debfc3dSmrg   return ret;
1711debfc3dSmrg }
1721debfc3dSmrg 
1731debfc3dSmrg /* Build a REALPART_EXPR or IMAGPART_EXPR, according to CODE, from ARG.  */
1741debfc3dSmrg 
1751debfc3dSmrg tree
build_real_imag_expr(location_t location,enum tree_code code,tree arg)1761debfc3dSmrg build_real_imag_expr (location_t location, enum tree_code code, tree arg)
1771debfc3dSmrg {
1781debfc3dSmrg   tree ret;
1791debfc3dSmrg   tree arg_type = TREE_TYPE (arg);
1801debfc3dSmrg 
1811debfc3dSmrg   gcc_assert (code == REALPART_EXPR || code == IMAGPART_EXPR);
1821debfc3dSmrg 
1831debfc3dSmrg   if (TREE_CODE (arg_type) == COMPLEX_TYPE)
1841debfc3dSmrg     {
1851debfc3dSmrg       ret = build1 (code, TREE_TYPE (TREE_TYPE (arg)), arg);
1861debfc3dSmrg       SET_EXPR_LOCATION (ret, location);
1871debfc3dSmrg     }
1881debfc3dSmrg   else if (INTEGRAL_TYPE_P (arg_type) || SCALAR_FLOAT_TYPE_P (arg_type))
1891debfc3dSmrg     {
1901debfc3dSmrg       ret = (code == REALPART_EXPR
1911debfc3dSmrg 	     ? arg
1921debfc3dSmrg 	     : omit_one_operand_loc (location, arg_type,
1931debfc3dSmrg 				     integer_zero_node, arg));
1941debfc3dSmrg     }
1951debfc3dSmrg   else
1961debfc3dSmrg     {
1971debfc3dSmrg       error_at (location, "wrong type argument to %s",
1981debfc3dSmrg 		code == REALPART_EXPR ? "__real" : "__imag");
1991debfc3dSmrg       ret = error_mark_node;
2001debfc3dSmrg     }
2011debfc3dSmrg 
2021debfc3dSmrg   return ret;
2031debfc3dSmrg }
204