diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-28 16:13:11 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-28 16:13:11 +0100 |
commit | 6bb207b468da36d9d99c63409dc4098514759c90 (patch) | |
tree | 79e00d8728b885a5a24f3c40c9697a3108810234 /gcc | |
parent | 8a8e515c2bf1a48117f463a949174c666932711b (diff) | |
download | gcc-6bb207b468da36d9d99c63409dc4098514759c90.zip gcc-6bb207b468da36d9d99c63409dc4098514759c90.tar.gz gcc-6bb207b468da36d9d99c63409dc4098514759c90.tar.bz2 |
c++: Fix up handling of register ... asm ("...") vars in templates [PR33661, PR98847]
As the testcase shows, for vars appearing in templates, we don't attach
the asm spec string to the pattern decls, nor pass it back to cp_finish_decl
during instantiation.
The following patch does that.
2021-01-28 Jakub Jelinek <jakub@redhat.com>
PR c++/33661
PR c++/98847
* decl.c (cp_finish_decl): For register vars with asmspec in templates
call set_user_assembler_name and set DECL_HARD_REGISTER.
* pt.c (tsubst_expr): When instantiating DECL_HARD_REGISTER vars,
pass asmspec_tree to cp_finish_decl.
* g++.target/i386/pr98847.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/decl.c | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.target/i386/pr98847.C | 20 |
3 files changed, 39 insertions, 1 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1a114a2..3b9875e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7840,6 +7840,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, retrofit_lang_decl (decl); SET_DECL_DEPENDENT_INIT_P (decl, true); } + + if (VAR_P (decl) && DECL_REGISTER (decl) && asmspec) + { + set_user_assembler_name (decl, asmspec); + DECL_HARD_REGISTER (decl) = 1; + } return; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8f05ce2..9089afb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18238,6 +18238,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, bool const_init = false; unsigned int cnt = 0; tree first = NULL_TREE, ndecl = error_mark_node; + tree asmspec_tree = NULL_TREE; maybe_push_decl (decl); if (VAR_P (decl) @@ -18261,7 +18262,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, now. */ predeclare_vla (decl); - cp_finish_decl (decl, init, const_init, NULL_TREE, 0); + if (VAR_P (decl) && DECL_HARD_REGISTER (pattern_decl)) + { + tree id = DECL_ASSEMBLER_NAME (pattern_decl); + const char *asmspec = IDENTIFIER_POINTER (id); + gcc_assert (asmspec[0] == '*'); + asmspec_tree + = build_string (IDENTIFIER_LENGTH (id) - 1, + asmspec + 1); + TREE_TYPE (asmspec_tree) = char_array_type_node; + } + + cp_finish_decl (decl, init, const_init, asmspec_tree, 0); if (ndecl != error_mark_node) cp_finish_decomp (ndecl, first, cnt); diff --git a/gcc/testsuite/g++.target/i386/pr98847.C b/gcc/testsuite/g++.target/i386/pr98847.C new file mode 100644 index 0000000..0a72ccc --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr98847.C @@ -0,0 +1,20 @@ +// PR c++/98847 +// { dg-do run } +// { dg-options "-O2 -masm=att" } + +template <int N> +int +foo () +{ + register int edx asm ("edx"); + asm ("movl $1234, %%edx" : "=r" (edx)); + return edx; +} + +int +main () +{ + if (foo<0> () != 1234) + __builtin_abort (); + return 0; +} |