aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2005-11-17 21:03:50 +0000
committerEric Botcazou <ebotcazou@adacore.com>2005-11-17 21:03:50 +0000
commit242e2f46d06ad0346410b955e3b16885ed5159ca (patch)
tree95f067923cc5dea4fd2ea68e19043c449187374c /gcc/ada
parent6d2596f3dfefd71c8d5b31e8982c8beace6d8713 (diff)
PR ada/22333
* trans.c (gnat_gimplify_expr, case ADDR_EXPR): Always make a temporary if taking the address of something that is neither reference, declaration, or constant, since the gimplifier can't handle that case. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@107134 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog8
-rw-r--r--gcc/ada/trans.c38
2 files changed, 40 insertions, 6 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 75651bc7bc4..78aaba7a9a6 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,11 @@
+2005-11-17 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ PR ada/22333
+ * trans.c (gnat_gimplify_expr, case ADDR_EXPR): Always make
+ a temporary if taking the address of something that is neither
+ reference, declaration, or constant, since the gimplifier
+ can't handle that case.
+
2005-11-17 Laurent GUERBY <laurent@guerby.net>
PR ada/24857
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index 918f374b5da..c7126720003 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -4570,6 +4570,7 @@ int
gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
{
tree expr = *expr_p;
+ tree op;
if (IS_ADA_STMT (expr))
return gnat_gimplify_stmt (expr_p);
@@ -4600,25 +4601,50 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
return GS_OK;
case ADDR_EXPR:
+ op = TREE_OPERAND (expr, 0);
+
/* If we're taking the address of a constant CONSTRUCTOR, force it to
be put into static memory. We know it's going to be readonly given
the semantics we have and it's required to be static memory in
- the case when the reference is in an elaboration procedure. */
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == CONSTRUCTOR
- && TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+ the case when the reference is in an elaboration procedure. */
+ if (TREE_CODE (op) == CONSTRUCTOR && TREE_CONSTANT (op))
{
- tree new_var
- = create_tmp_var (TREE_TYPE (TREE_OPERAND (expr, 0)), "C");
+ tree new_var = create_tmp_var (TREE_TYPE (op), "C");
TREE_READONLY (new_var) = 1;
TREE_STATIC (new_var) = 1;
TREE_ADDRESSABLE (new_var) = 1;
- DECL_INITIAL (new_var) = TREE_OPERAND (expr, 0);
+ DECL_INITIAL (new_var) = op;
+
+ TREE_OPERAND (expr, 0) = new_var;
+ recompute_tree_invarant_for_addr_expr (expr);
+ return GS_ALL_DONE;
+ }
+
+ /* Otherwise, if we are taking the address of something that is neither
+ reference, declaration, or constant, make a variable for the operand
+ here and then take its address. If we don't do it this way, we may
+ confuse the gimplifier because it needs to know the variable is
+ addressable at this point. This duplicates code in
+ internal_get_tmp_var, which is unfortunate. */
+ else if (TREE_CODE_CLASS (TREE_CODE (op)) != tcc_reference
+ && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_declaration
+ && TREE_CODE_CLASS (TREE_CODE (op)) != tcc_constant)
+ {
+ tree new_var = create_tmp_var (TREE_TYPE (op), "A");
+ tree mod = build (MODIFY_EXPR, TREE_TYPE (op), new_var, op);
+
+ TREE_ADDRESSABLE (new_var) = 1;
+
+ if (EXPR_HAS_LOCATION (op))
+ SET_EXPR_LOCUS (mod, EXPR_LOCUS (op));
+ gimplify_and_add (mod, pre_p);
TREE_OPERAND (expr, 0) = new_var;
recompute_tree_invarant_for_addr_expr (expr);
return GS_ALL_DONE;
}
+
return GS_UNHANDLED;
case COMPONENT_REF: