Hi.

After the discussion with Richi and Nathan, I made a place in tree_function_decl
and I rebased the original Dominik's patch on top of that.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin
>From cdf41c7e6d00680b6c7fc31234025aef0091bd9c Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Tue, 2 Jul 2019 08:30:09 +0200
Subject: [PATCH 1/2] Come up with function_decl_type and use it in
 tree_function_decl.

gcc/ChangeLog:

2019-07-02  Martin Liska  <mli...@suse.cz>

	* calls.c (maybe_warn_alloc_args_overflow): Use new macros
	(e.g. DECL_SET_LAMBDA_FUNCTION and DECL_LAMBDA_FUNCTION_P).
	* coverage.c (coverage_begin_function): Likewise.
	* fold-const.c (tree_expr_nonzero_warnv_p): Likewise.
	* gimple.c (gimple_call_nonnull_result_p): Likewise.
	* ipa-icf.c (sem_item::compare_referenced_symbol_properties): Likewise.
	(sem_item::hash_referenced_symbol_properties): Likewise.
	* lto-streamer-out.c (hash_tree): Likewise.
	* predict.c (expr_expected_value_1): Likewise.
	* tree-inline.c (expand_call_inline): Likewise.
	* tree-streamer-in.c (unpack_ts_function_decl_value_fields): Likewise.
	* tree-streamer-out.c (pack_ts_function_decl_value_fields): Likewise.
	* tree-core.h (enum function_decl_type): New enum.
	(struct tree_function_decl): Remove operator_new_flag and lambda_function.
	* tree.h (FUNCTION_DECL_DECL_TYPE): New.
	(set_function_decl_type): Likewise.
	(DECL_IS_OPERATOR_NEW_P): New.
	(DECL_SET_IS_OPERATOR_NEW): Likewise.
	(DECL_LAMBDA_FUNCTION): Likewise.
	(DECL_LAMBDA_FUNCTION_P): Likewise.
	(DECL_IS_OPERATOR_NEW): Remove.
	(DECL_SET_LAMBDA_FUNCTION): Likewise.

gcc/c/ChangeLog:

2019-07-02  Martin Liska  <mli...@suse.cz>

	* c-decl.c (merge_decls): Use new macros
	(e.g. DECL_SET_LAMBDA_FUNCTION and DECL_LAMBDA_FUNCTION_P).

gcc/cp/ChangeLog:

2019-07-02  Martin Liska  <mli...@suse.cz>

	* decl.c (duplicate_decls): Use new macros
	(e.g. DECL_SET_LAMBDA_FUNCTION and DECL_LAMBDA_FUNCTION_P).
	(cxx_init_decl_processing): Likewise.
	(grok_op_properties): Likewise.
	* parser.c (cp_parser_lambda_declarator_opt): Likewise.

gcc/lto/ChangeLog:

2019-07-02  Martin Liska  <mli...@suse.cz>

	* lto-common.c (compare_tree_sccs_1): Use new macros
	(e.g. DECL_SET_LAMBDA_FUNCTION and DECL_LAMBDA_FUNCTION_P).
---
 gcc/c/c-decl.c          |  3 ++-
 gcc/calls.c             |  2 +-
 gcc/coverage.c          |  2 +-
 gcc/cp/decl.c           | 13 +++++++------
 gcc/cp/parser.c         |  2 +-
 gcc/fold-const.c        |  2 +-
 gcc/gimple.c            |  2 +-
 gcc/ipa-icf.c           |  6 +++---
 gcc/lto-streamer-out.c  |  2 +-
 gcc/lto/lto-common.c    |  2 +-
 gcc/predict.c           |  2 +-
 gcc/tree-core.h         | 20 +++++++++++++++++---
 gcc/tree-inline.c       |  2 +-
 gcc/tree-streamer-in.c  |  2 +-
 gcc/tree-streamer-out.c |  2 +-
 gcc/tree.h              | 34 ++++++++++++++++++++++++++++++----
 16 files changed, 70 insertions(+), 28 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index cb2f49fa5a2..b0a7e34745f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2638,7 +2638,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 	    |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
 	  TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
 	  DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
-	  DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+	  if (DECL_IS_OPERATOR_NEW_P (olddecl))
+	    DECL_SET_IS_OPERATOR_NEW (newdecl, true);
 	  TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
 	  DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
 	  DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
diff --git a/gcc/calls.c b/gcc/calls.c
index 6ab138e7bb0..7507b698e27 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1395,7 +1395,7 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		  && fn
 		  && !args[1]
 		  && lang_GNU_CXX ()
-		  && DECL_IS_OPERATOR_NEW (fn)
+		  && DECL_IS_OPERATOR_NEW_P (fn)
 		  && integer_all_onesp (args[i]))
 		continue;
 
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 1ffefd5f482..a63cb94e9f3 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -643,7 +643,7 @@ coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
 		     (DECL_ASSEMBLER_NAME (current_function_decl)));
   gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
 		       && !DECL_FUNCTION_VERSIONED (current_function_decl)
-		       && !DECL_LAMBDA_FUNCTION (current_function_decl));
+		       && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
   gcov_write_filename (xloc.file);
   gcov_write_unsigned (xloc.line);
   gcov_write_unsigned (xloc.column);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bb9d19a8172..0e9b1b55141 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2292,7 +2292,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 	  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
 	    |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
 	  DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
-	  DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+	  if (DECL_IS_OPERATOR_NEW_P (olddecl))
+	    DECL_SET_IS_OPERATOR_NEW (newdecl, true);
 	  DECL_LOOPING_CONST_OR_PURE_P (newdecl)
 	    |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
 
@@ -4357,10 +4358,10 @@ cxx_init_decl_processing (void)
     deltype = build_exception_variant (deltype, empty_except_spec);
     tree opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
     DECL_IS_MALLOC (opnew) = 1;
-    DECL_IS_OPERATOR_NEW (opnew) = 1;
+    DECL_SET_IS_OPERATOR_NEW (opnew, true);
     opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
     DECL_IS_MALLOC (opnew) = 1;
-    DECL_IS_OPERATOR_NEW (opnew) = 1;
+    DECL_SET_IS_OPERATOR_NEW (opnew, true);
     push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
     push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
     if (flag_sized_deallocation)
@@ -4393,10 +4394,10 @@ cxx_init_decl_processing (void)
 	newtype = build_exception_variant (newtype, new_eh_spec);
 	opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
 	DECL_IS_MALLOC (opnew) = 1;
-	DECL_IS_OPERATOR_NEW (opnew) = 1;
+	DECL_SET_IS_OPERATOR_NEW (opnew, true);
 	opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
 	DECL_IS_MALLOC (opnew) = 1;
-	DECL_IS_OPERATOR_NEW (opnew) = 1;
+	DECL_SET_IS_OPERATOR_NEW (opnew, true);
 
 	/* operator delete (void *, align_val_t); */
 	deltype = build_function_type_list (void_type_node, ptr_type_node,
@@ -13637,7 +13638,7 @@ grok_op_properties (tree decl, bool complain)
 	coerce_delete_type (decl, loc);
       else
 	{
-	  DECL_IS_OPERATOR_NEW (decl) = 1;
+	  DECL_SET_IS_OPERATOR_NEW (decl, true);
 	  TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl), loc);
 	}
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 12814102465..7cded50dcfc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10977,7 +10977,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
 	DECL_ARTIFICIAL (fco) = 1;
 	/* Give the object parameter a different name.  */
 	DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier;
-	DECL_LAMBDA_FUNCTION (fco) = 1;
+	DECL_SET_LAMBDA_FUNCTION (fco, true);
       }
     if (template_param_list)
       {
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0ca472d422f..a8ae5652682 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9250,7 +9250,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 	tree fndecl = get_callee_fndecl (t);
 	if (!fndecl) return false;
 	if (flag_delete_null_pointer_checks && !flag_check_new
-	    && DECL_IS_OPERATOR_NEW (fndecl)
+	    && DECL_IS_OPERATOR_NEW_P (fndecl)
 	    && !TREE_NOTHROW (fndecl))
 	  return true;
 	if (flag_delete_null_pointer_checks
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 63c8d5e85ae..513bde209e2 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1583,7 +1583,7 @@ gimple_call_nonnull_result_p (gcall *call)
   if (!fndecl)
     return false;
   if (flag_delete_null_pointer_checks && !flag_check_new
-      && DECL_IS_OPERATOR_NEW (fndecl)
+      && DECL_IS_OPERATOR_NEW_P (fndecl)
       && !TREE_NOTHROW (fndecl))
     return true;
 
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 7c486eda758..ce544d45e88 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -344,8 +344,8 @@ sem_item::compare_referenced_symbol_properties (symtab_node *used_by,
 	    return return_false_with_msg ("inline attributes are different");
 	}
 
-      if (DECL_IS_OPERATOR_NEW (n1->decl)
-	  != DECL_IS_OPERATOR_NEW (n2->decl))
+      if (DECL_IS_OPERATOR_NEW_P (n1->decl)
+	  != DECL_IS_OPERATOR_NEW_P (n2->decl))
 	return return_false_with_msg ("operator new flags are different");
     }
 
@@ -409,7 +409,7 @@ sem_item::hash_referenced_symbol_properties (symtab_node *ref,
 	  hstate.add_flag (DECL_DISREGARD_INLINE_LIMITS (ref->decl));
 	  hstate.add_flag (DECL_DECLARED_INLINE_P (ref->decl));
 	}
-      hstate.add_flag (DECL_IS_OPERATOR_NEW (ref->decl));
+      hstate.add_flag (DECL_IS_OPERATOR_NEW_P (ref->decl));
     }
   else if (is_a <varpool_node *> (ref))
     {
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index dc68429303c..574f51dbb66 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1121,12 +1121,12 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       hstate.add_int (DECL_BUILT_IN_CLASS (t));
       hstate.add_flag (DECL_STATIC_CONSTRUCTOR (t));
       hstate.add_flag (DECL_STATIC_DESTRUCTOR (t));
+      hstate.add_flag (FUNCTION_DECL_DECL_TYPE (t));
       hstate.add_flag (DECL_UNINLINABLE (t));
       hstate.add_flag (DECL_POSSIBLY_INLINED (t));
       hstate.add_flag (DECL_IS_NOVOPS (t));
       hstate.add_flag (DECL_IS_RETURNS_TWICE (t));
       hstate.add_flag (DECL_IS_MALLOC (t));
-      hstate.add_flag (DECL_IS_OPERATOR_NEW (t));
       hstate.add_flag (DECL_DECLARED_INLINE_P (t));
       hstate.add_flag (DECL_STATIC_CHAIN (t));
       hstate.add_flag (DECL_NO_INLINE_WARNING_P (t));
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 1275b673506..acb7d5d8bec 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1213,7 +1213,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
       compare_values (DECL_IS_NOVOPS);
       compare_values (DECL_IS_RETURNS_TWICE);
       compare_values (DECL_IS_MALLOC);
-      compare_values (DECL_IS_OPERATOR_NEW);
+      compare_values (DECL_IS_OPERATOR_NEW_P);
       compare_values (DECL_DECLARED_INLINE_P);
       compare_values (DECL_STATIC_CHAIN);
       compare_values (DECL_NO_INLINE_WARNING_P);
diff --git a/gcc/predict.c b/gcc/predict.c
index ad19d1295e0..debf27bf5f8 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -2450,7 +2450,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
 	      return NULL;
 	    }
 
-	  if (DECL_IS_MALLOC (decl) || DECL_IS_OPERATOR_NEW (decl))
+	  if (DECL_IS_MALLOC (decl) || DECL_IS_OPERATOR_NEW_P (decl))
 	    {
 	      if (predictor)
 		*predictor = PRED_MALLOC_NONNULL;
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 23f8f01317e..e0643503e80 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1801,6 +1801,17 @@ struct GTY(()) tree_decl_non_common {
   tree result;
 };
 
+/* Classify a special function declaration type.  */
+
+enum function_decl_type
+{
+  NONE,
+  OPERATOR_NEW,
+  LAMBDA_FUNCTION
+
+  /* 0 values left */
+};
+
 /* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
    arguments/result/saved_tree fields by front ends.   It was either inherit
    FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,
@@ -1840,19 +1851,22 @@ struct GTY(()) tree_function_decl {
   unsigned novops_flag : 1;
   unsigned returns_twice_flag : 1;
   unsigned malloc_flag : 1;
-  unsigned operator_new_flag : 1;
   unsigned declared_inline_flag : 1;
   unsigned no_inline_warning_flag : 1;
 
   unsigned no_instrument_function_entry_exit : 1;
+
+  /* Align the bitfield to boundary of a byte.  */
+  ENUM_BITFIELD(function_decl_type) decl_type: 2;
+
   unsigned no_limit_stack : 1;
   unsigned disregard_inline_limits : 1;
   unsigned pure_flag : 1;
   unsigned looping_const_or_pure_flag : 1;
   unsigned has_debug_args_flag : 1;
   unsigned versioned_function : 1;
-  unsigned lambda_function: 1;
-  /* No bits left.  */
+
+  /* 0 bits left.  */
 };
 
 struct GTY(()) tree_translation_unit_decl {
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 450af460dd0..22ac06255a5 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4883,7 +4883,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
      we may get confused if the compiler sees that the inlined new
      function returns a pointer which was just deleted.  See bug
      33407.  */
-  if (DECL_IS_OPERATOR_NEW (fn))
+  if (DECL_IS_OPERATOR_NEW_P (fn))
     {
       return_slot = NULL;
       modify_dest = NULL;
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 35b3e9874d5..7bd21ae7bc5 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -333,7 +333,7 @@ unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
   DECL_IS_NOVOPS (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_IS_RETURNS_TWICE (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_IS_MALLOC (expr) = (unsigned) bp_unpack_value (bp, 1);
-  DECL_IS_OPERATOR_NEW (expr) = (unsigned) bp_unpack_value (bp, 1);
+  DECL_SET_IS_OPERATOR_NEW (expr, (unsigned) bp_unpack_value (bp, 1));
   DECL_DECLARED_INLINE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_STATIC_CHAIN (expr) = (unsigned) bp_unpack_value (bp, 1);
   DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index a83057ec277..7e93e6c23bb 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -295,7 +295,7 @@ pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
   bp_pack_value (bp, DECL_IS_NOVOPS (expr), 1);
   bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1);
   bp_pack_value (bp, DECL_IS_MALLOC (expr), 1);
-  bp_pack_value (bp, DECL_IS_OPERATOR_NEW (expr), 1);
+  bp_pack_value (bp, DECL_IS_OPERATOR_NEW_P (expr), 1);
   bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1);
   bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
   bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);
diff --git a/gcc/tree.h b/gcc/tree.h
index 1a43e6b7ff8..117c2e13335 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2980,11 +2980,34 @@ extern void decl_fini_priority_insert (tree, priority_type);
 #define DECL_IS_MALLOC(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.malloc_flag)
 
+/* Macro for direct set and get of function_decl.decl_type.  */
+#define FUNCTION_DECL_DECL_TYPE(NODE) \
+  (NODE->function_decl.decl_type)
+
+/* Set decl_type of a DECL.  Set it to T when SET is true, or reset
+   it to NONE.  */
+
+static inline void
+set_function_decl_type (tree decl, function_decl_type t, bool set)
+{
+  if (set)
+    {
+      gcc_assert (FUNCTION_DECL_DECL_TYPE (decl) == NONE
+		  || FUNCTION_DECL_DECL_TYPE (decl) == t);
+      decl->function_decl.decl_type = t;
+    }
+  else if (FUNCTION_DECL_DECL_TYPE (decl) == t)
+    FUNCTION_DECL_DECL_TYPE (decl) = NONE;
+}
+
 /* Nonzero in a FUNCTION_DECL means this function should be treated as
    C++ operator new, meaning that it returns a pointer for which we
    should not use type based aliasing.  */
-#define DECL_IS_OPERATOR_NEW(NODE) \
-  (FUNCTION_DECL_CHECK (NODE)->function_decl.operator_new_flag)
+#define DECL_IS_OPERATOR_NEW_P(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_NEW)
+
+#define DECL_SET_IS_OPERATOR_NEW(NODE, VAL) \
+  set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_NEW, VAL)
 
 /* Nonzero in a FUNCTION_DECL means this function may return more
    than once.  */
@@ -3129,8 +3152,11 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
    (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.cxx_destructor)
 
 /* In FUNCTION_DECL, this is set if this function is a lambda function.  */
-#define DECL_LAMBDA_FUNCTION(NODE) \
-  (FUNCTION_DECL_CHECK (NODE)->function_decl.lambda_function)
+#define DECL_LAMBDA_FUNCTION_P(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == LAMBDA_FUNCTION)
+
+#define DECL_SET_LAMBDA_FUNCTION(NODE, VAL) \
+  set_function_decl_type (FUNCTION_DECL_CHECK (NODE), LAMBDA_FUNCTION, VAL)
 
 /* In FUNCTION_DECL that represent an virtual method this is set when
    the method is final.  */
-- 
2.22.0

Reply via email to