From 788113556899304501fd119f9c7ba93a74835c33 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 1 Feb 2021 23:59:06 -0300 Subject: [PATCH] restore current_function_decl after re-gimplifying nested ADDR_EXPRs Ada makes extensive use of nested functions, which turn all automatic variables of the enclosing function that are used in nested ones into members of an artificial FRAME record type. The address of a local variable is usually passed to asan marking functions without using a temporary. asan_expand_mark_ifn will reject an ADDR_EXPRs if it's split out from the call into an SSA_NAMEs. Taking the address of a member of FRAME within a nested function was not regarded as a gimple val: while introducing FRAME variables, current_function_decl pointed to the outermost function, even while processing a nested function, so decl_address_invariant_p, checking that the context of the variable is current_function_decl, returned false for such ADDR_EXPRs. decl_address_invariant_p, called when determining whether an expression is a legitimate gimple value, compares the context of automatic variables with current_function_decl. Some of the tree-nested function processing doesn't set current_function_decl, but ADDR_EXPR-processing bits temporarily override it. However, they restore it before re-gimplifying, which causes even ADDR_EXPRs referencing automatic variables in the FRAME struct of a nested function to not be regarded as address-invariant. This patch moves the restores of current_function_decl in the ADDR_EXPR-handling bits after the re-gimplification, so that the correct current_function_decl is used when testing for address invariance. for gcc/ChangeLog * tree-nested.c (convert_nonlocal_reference_op): Move current_function_decl restore after re-gimplification. (convert_local_reference_op): Likewise. for gcc/testsuite/ChangeLog * gcc.dg/asan/nested-1.c: New. --- gcc/testsuite/gcc.dg/asan/nested-1.c | 24 ++++++++++++++++++++++++ gcc/tree-nested.c | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/asan/nested-1.c diff --git a/gcc/testsuite/gcc.dg/asan/nested-1.c b/gcc/testsuite/gcc.dg/asan/nested-1.c new file mode 100644 index 00000000000..87e84209807 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/nested-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address" } */ + +int f(int i) { + auto int h() { + int r; + int *p; + + { + int x[3]; + + auto int g() { + return x[i]; + } + + p = &r; + *p = g(); + } + + return *p; + } + + return h(); +} diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 1b52669b622..addd6eef9ab 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1214,7 +1214,6 @@ convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data) save_context = current_function_decl; current_function_decl = info->context; recompute_tree_invariant_for_addr_expr (t); - current_function_decl = save_context; /* If the callback converted the address argument in a context where we only accept variables (and min_invariant, presumably), @@ -1222,6 +1221,7 @@ convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data) if (save_val_only) *tp = gsi_gimplify_val ((struct nesting_info *) wi->info, t, &wi->gsi); + current_function_decl = save_context; } } break; @@ -1969,13 +1969,13 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data) save_context = current_function_decl; current_function_decl = info->context; recompute_tree_invariant_for_addr_expr (t); - current_function_decl = save_context; /* If we are in a context where we only accept values, then compute the address into a temporary. */ if (save_val_only) *tp = gsi_gimplify_val ((struct nesting_info *) wi->info, t, &wi->gsi); + current_function_decl = save_context; } break; -- 2.30.2