diff options
author | Jason Merrill <jason@redhat.com> | 2020-06-02 16:23:02 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-06-03 14:06:17 -0400 |
commit | ef4e0c35546ba2c897613925c1d2485603ca3ab1 (patch) | |
tree | 5d209b6ffdcdb2555a52c17ce15c951e398e332f | |
parent | 8d57c30611b05a89fd265f6c0a74fe829c21cd34 (diff) | |
download | gcc-ef4e0c35546ba2c897613925c1d2485603ca3ab1.zip gcc-ef4e0c35546ba2c897613925c1d2485603ca3ab1.tar.gz gcc-ef4e0c35546ba2c897613925c1d2485603ca3ab1.tar.bz2 |
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.
-rw-r--r-- | gcc/cp/cp-gimplify.c | 19 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/vla-2.C | 14 |
4 files changed, 35 insertions, 4 deletions
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 6c29be9..e8fbc30 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 1775b0a..447d134 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 9c03c5a..38a771b 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 0000000..342d30b --- /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 <typename T> +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); +} |