diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2005-11-17 21:03:50 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2005-11-17 21:03:50 +0000 |
commit | 242e2f46d06ad0346410b955e3b16885ed5159ca (patch) | |
tree | 95f067923cc5dea4fd2ea68e19043c449187374c /gcc/ada | |
parent | 6d2596f3dfefd71c8d5b31e8982c8beace6d8713 (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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ada/trans.c | 38 |
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: |