selfpatch-slr/gcc_component_ref.patch

245 lines
8.8 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 4c2d49dcf5e9a1090313cd9d922b63e280fc4d54 Mon Sep 17 00:00:00 2001
From: York Jasper Niebuhr <yjnworkstation@gmail.com>
Date: Fri, 17 Oct 2025 21:17:30 +0200
Subject: [PATCH] unformatted component ref callback
---
gcc/c-family/c-common.cc | 48 +++++++++++++++++++++++++++++++---------
gcc/c-family/c-common.h | 3 ++-
gcc/c/c-parser.cc | 2 +-
gcc/c/c-typeck.cc | 9 ++++++++
gcc/doc/plugins.texi | 6 +++++
gcc/plugin.cc | 2 ++
gcc/plugin.def | 6 +++++
7 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 587d76461e9..f23093f5a66 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -7076,43 +7076,48 @@ c_common_to_target_charset (HOST_WIDE_INT c)
the whole expression. Return the folded result. */
tree
-fold_offsetof (tree expr, tree type, enum tree_code ctx)
+fold_offsetof (tree expr, tree type, enum tree_code ctx, bool may_fail)
{
tree base, off, t;
tree_code code = TREE_CODE (expr);
+
switch (code)
{
case ERROR_MARK:
return expr;
case VAR_DECL:
- error ("cannot apply %<offsetof%> to static data member %qD", expr);
+ if (!may_fail)
+ error ("cannot apply %<offsetof%> to static data member %qD", expr);
return error_mark_node;
case CALL_EXPR:
case TARGET_EXPR:
- error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+ if (!may_fail)
+ error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
return error_mark_node;
case NOP_EXPR:
case INDIRECT_REF:
if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
{
- error ("cannot apply %<offsetof%> to a non constant address");
+ if (!may_fail)
+ error ("cannot apply %<offsetof%> to a non constant address");
return error_mark_node;
}
return convert (type, TREE_OPERAND (expr, 0));
case COMPONENT_REF:
- base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code, may_fail);
if (base == error_mark_node)
return base;
t = TREE_OPERAND (expr, 1);
if (DECL_C_BIT_FIELD (t))
{
- error ("attempt to take address of bit-field structure "
- "member %qD", t);
+ if (!may_fail)
+ error ("attempt to take address of bit-field structure "
+ "member %qD", t);
return error_mark_node;
}
off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
@@ -7121,7 +7126,7 @@ fold_offsetof (tree expr, tree type, enum tree_code ctx)
break;
case ARRAY_REF:
- base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code, may_fail);
if (base == error_mark_node)
return base;
@@ -7178,17 +7183,38 @@ fold_offsetof (tree expr, tree type, enum tree_code ctx)
case COMPOUND_EXPR:
/* Handle static members of volatile structs. */
t = TREE_OPERAND (expr, 1);
- gcc_checking_assert (VAR_P (get_base_address (t)));
- return fold_offsetof (t, type);
+ if (!VAR_P (get_base_address (t)))
+ return error_mark_node;
+ return fold_offsetof (t, type, ERROR_MARK, may_fail);
default:
- gcc_unreachable ();
+ return error_mark_node;
}
if (!POINTER_TYPE_P (type))
return size_binop (PLUS_EXPR, base, convert (type, off));
return fold_build_pointer_plus (base, off);
}
+
+/* Tries folding expr using fold_offsetof. On success, the folded offsetof
+ is returned. On failure, the original expr is wrapped in an ADDR_EXPR
+ and converted to the desired expression type. The resulting expression
+ may or may not be constant! */
+
+tree
+fold_offsetof_maybe (tree expr, tree type)
+{
+ /* expr might not have the correct structure, thus folding may fail */
+ tree maybe_folded = fold_offsetof(expr, type, ERROR_MARK, true);
+ if (maybe_folded != error_mark_node)
+ return maybe_folded;
+
+ tree ptr_type = build_pointer_type (TREE_TYPE (expr));
+ tree ptr = build1 (ADDR_EXPR, ptr_type, expr);
+
+ return fold_convert (type, ptr);
+}
+
/* *PTYPE is an incomplete array. Complete it with a domain based on
INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index ea6c2975056..70fcfeb6661 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1174,7 +1174,8 @@ extern bool c_dump_tree (void *, tree);
extern void verify_sequence_points (tree);
extern tree fold_offsetof (tree, tree = size_type_node,
- tree_code ctx = ERROR_MARK);
+ tree_code ctx = ERROR_MARK, bool may_fail = false);
+extern tree fold_offsetof_maybe (tree, tree = size_type_node);
extern int complete_array_type (tree *, tree, bool);
extern void complete_flexible_array_elts (tree);
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 22ec0f849b7..6a8a5d58e6d 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -11823,7 +11823,7 @@ c_parser_postfix_expression (c_parser *parser)
location_t end_loc = c_parser_peek_token (parser)->get_finish ();
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
- expr.value = fold_offsetof (offsetof_ref);
+ expr.value = fold_offsetof_maybe (offsetof_ref);
set_c_expr_source_range (&expr, loc, end_loc);
}
break;
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 55d896e02df..e76002151bd 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "realmpfr.h"
#include "tree-pretty-print-markup.h"
#include "gcc-urlifier.h"
+#include "plugin.h"
/* Possible cases of implicit conversions. Used to select diagnostic messages
and control folding initializers in convert_for_assignment. */
@@ -133,6 +134,7 @@ static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
static bool comptypes_internal (const_tree, const_tree,
struct comptypes_data *data);
+
/* Return true if EXP is a null pointer constant, false otherwise. */
@@ -3174,6 +3176,13 @@ build_component_ref (location_t loc, tree datum, tree component,
else if (TREE_DEPRECATED (subdatum))
warn_deprecated_use (subdatum, NULL_TREE);
+ tree pre_cb_type = TREE_TYPE (ref);
+ if (invoke_plugin_callbacks (PLUGIN_BUILD_COMPONENT_REF, &ref) == PLUGEVT_SUCCESS &&
+ !comptypes (TREE_TYPE (ref), pre_cb_type))
+ {
+ error_at (EXPR_LOCATION (ref), "PLUGIN_BUILD_COMPONENT_REF callback returned expression of incompatible type");
+ }
+
datum = ref;
field = TREE_CHAIN (field);
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index c11167a34ef..942e2e41b90 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -222,6 +222,12 @@ enum plugin_event
ana::plugin_analyzer_init_iface *. */
PLUGIN_ANALYZER_INIT,
+ /* Called by the C front end when a COMPONENT_REF node is built.
+ The callback receives a pointer to the COMPONENT_REF tree (of type 'tree *').
+ Plugins may replace the node by assigning through the pointer, but any
+ replacement must be type-compatible with the original node. */
+ PLUGIN_BUILD_COMPONENT_REF,
+
PLUGIN_EVENT_FIRST_DYNAMIC /* Dummy event used for indexing callback
array. */
@};
diff --git a/gcc/plugin.cc b/gcc/plugin.cc
index 0de2cc2dd2c..975e8c4e291 100644
--- a/gcc/plugin.cc
+++ b/gcc/plugin.cc
@@ -500,6 +500,7 @@ register_callback (const char *plugin_name,
case PLUGIN_NEW_PASS:
case PLUGIN_INCLUDE_FILE:
case PLUGIN_ANALYZER_INIT:
+ case PLUGIN_BUILD_COMPONENT_REF:
{
struct callback_info *new_callback;
if (!callback)
@@ -581,6 +582,7 @@ invoke_plugin_callbacks_full (int event, void *gcc_data)
case PLUGIN_NEW_PASS:
case PLUGIN_INCLUDE_FILE:
case PLUGIN_ANALYZER_INIT:
+ case PLUGIN_BUILD_COMPONENT_REF:
{
/* Iterate over every callback registered with this event and
call it. */
diff --git a/gcc/plugin.def b/gcc/plugin.def
index 94e012a1e00..b0335178762 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -103,6 +103,12 @@ DEFEVENT (PLUGIN_INCLUDE_FILE)
ana::plugin_analyzer_init_iface *. */
DEFEVENT (PLUGIN_ANALYZER_INIT)
+/* Called by the C front end when a COMPONENT_REF node is built.
+ The callback receives a pointer to the COMPONENT_REF tree (of type 'tree *').
+ Plugins may replace the node by assigning through the pointer, but any
+ replacement must be type-compatible with the original node. */
+DEFEVENT (PLUGIN_BUILD_COMPONENT_REF)
+
/* When adding a new hard-coded plugin event, don't forget to edit in
file plugin.cc the functions register_callback and
invoke_plugin_callbacks_full accordingly! */
--
2.43.0