From ef4e0c35546ba2c897613925c1d2485603ca3ab1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 2 Jun 2020 16:23:02 -0400 Subject: [PATCH] c++: Fix VLA in template [PR95232] In a non-template, grokdeclarator notices when we build a pointer to a variably-modified type, and inserts a TYPE_DECL to make sure that type gets gimplified. But in a template we can't always recognize a variably-modified type, so we need to deal with it at instantiation time. gcc/cp/ChangeLog: PR c++/95232 * cp-tree.h (predeclare_vla): Declare. * cp-gimplify.c (predeclare_vla): Handle getting a decl. * pt.c (tsubst_expr) [DECL_EXPR]: Use it. gcc/testsuite/ChangeLog: PR c++/95232 * g++.dg/ubsan/vla-2.C: New test. --- gcc/cp/cp-gimplify.c | 19 +++++++++++++++---- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 5 +++++ gcc/testsuite/g++.dg/ubsan/vla-2.C | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ubsan/vla-2.C diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 6c29be9d836..e8fbc300fda 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1185,14 +1185,17 @@ static tree genericize_spaceship (tree expr) /* If EXPR involves an anonymous VLA type, prepend a DECL_EXPR for that type to trigger gimplify_type_sizes; otherwise a cast to pointer-to-VLA confuses - the middle-end (c++/88256). */ + the middle-end (c++/88256). If EXPR is a DECL, use add_stmt and return + NULL_TREE; otherwise return a COMPOUND_STMT of the DECL_EXPR and EXPR. */ -static tree +tree predeclare_vla (tree expr) { tree type = TREE_TYPE (expr); if (type == error_mark_node) return expr; + if (is_typedef_decl (expr)) + type = DECL_ORIGINAL_TYPE (expr); /* We need to strip pointers for gimplify_type_sizes. */ tree vla = type; @@ -1209,8 +1212,16 @@ predeclare_vla (tree expr) DECL_ARTIFICIAL (decl) = 1; TYPE_NAME (vla) = decl; tree dexp = build_stmt (input_location, DECL_EXPR, decl); - expr = build2 (COMPOUND_EXPR, type, dexp, expr); - return expr; + if (DECL_P (expr)) + { + add_stmt (dexp); + return NULL_TREE; + } + else + { + expr = build2 (COMPOUND_EXPR, type, dexp, expr); + return expr; + } } /* Perform any pre-gimplification lowering of C++ front end trees to diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1775b0a4327..447d1349117 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7794,6 +7794,7 @@ extern tree cp_fold_maybe_rvalue (tree, bool); extern tree cp_fold_rvalue (tree); extern tree cp_fully_fold (tree); extern tree cp_fully_fold_init (tree); +extern tree predeclare_vla (tree); extern void clear_fold_cache (void); extern tree lookup_hotness_attribute (tree); extern tree process_stmt_hotness_attribute (tree, location_t); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9c03c5a5bbd..38a771b8e6f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17990,6 +17990,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, if (ndecl != error_mark_node) cp_maybe_mangle_decomp (ndecl, first, cnt); + /* In a non-template function, VLA type declarations are + handled in grokdeclarator; for templates, handle them + now. */ + predeclare_vla (decl); + cp_finish_decl (decl, init, const_init, NULL_TREE, constinit_p ? LOOKUP_CONSTINIT : 0); diff --git a/gcc/testsuite/g++.dg/ubsan/vla-2.C b/gcc/testsuite/g++.dg/ubsan/vla-2.C new file mode 100644 index 00000000000..342d30bfeac --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/vla-2.C @@ -0,0 +1,14 @@ +// PR c++/95232 +// { dg-additional-options "-Wno-vla -ftrapv -fnon-call-exceptions -O -fsanitize=undefined" } + +template +int tmain(T argc) { + typedef double (*chunk_t)[argc[0][0]]; + chunk_t var; + (void)var[0][0]; + return 0; +} + +int main (int argc, char **argv) { + return tmain(argv); +} -- 2.30.2