aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h17
-rw-r--r--gcc/cp/lambda.cc96
-rw-r--r--gcc/cp/mangle.cc2
-rw-r--r--gcc/cp/module.cc4
-rw-r--r--gcc/cp/parser.cc5
-rw-r--r--gcc/cp/pt.cc50
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-sig1-17.C26
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-sig1.h42
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h (renamed from gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C)3
11 files changed, 198 insertions, 97 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6d84514..4c0bacb 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1500,9 +1500,10 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
-/* If EXTRA_SCOPE, this is the number of the lambda within that scope. */
-#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \
- (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator)
+/* Lambdas in the same extra scope might need a discriminating count.
+ This is a single per-scope count. */
+#define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \
+ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope)
/* During parsing of the lambda, a vector of capture proxies which need
to be pushed once we're done processing a nested lambda. */
@@ -1530,8 +1531,8 @@ struct GTY (()) tree_lambda_expr
tree regen_info;
vec<tree, va_gc> *pending_proxies;
location_t locus;
- enum cp_lambda_default_capture_mode_type default_capture_mode : 8;
- short int discriminator;
+ enum cp_lambda_default_capture_mode_type default_capture_mode : 2;
+ unsigned discriminator_scope : 15; // Per-scope discriminator
};
/* Non-zero if this template specialization has access violations that
@@ -7778,10 +7779,10 @@ extern tree cp_build_vec_convert (tree, location_t, tree,
tsubst_flags_t);
extern tree cp_build_bit_cast (location_t, tree, tree,
tsubst_flags_t);
-extern void start_lambda_scope (tree);
-extern void record_lambda_scope (tree);
-extern void record_null_lambda_scope (tree);
+extern void start_lambda_scope (tree decl);
extern void finish_lambda_scope (void);
+extern void record_lambda_scope (tree lambda);
+extern void record_lambda_scope_discriminator (tree lambda);
extern tree start_lambda_function (tree fn, tree lambda_expr);
extern void finish_lambda_function (tree body);
extern bool regenerated_lambda_fn_p (tree);
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index e9d5d4d..d2673e2 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1444,79 +1444,77 @@ is_lambda_ignored_entity (tree val)
return false;
}
-/* Lambdas that appear in variable initializer or default argument scope
- get that in their mangling, so we need to record it. We might as well
- use the count for function and namespace scopes as well. */
-static GTY(()) tree lambda_scope;
-static GTY(()) int lambda_count;
-struct GTY(()) tree_int
+/* Lambdas that appear in variable initializer or default argument
+ scope get that in their mangling, so we need to record it. Also,
+ multiple lambdas in the same scope may need a mangling
+ discriminator. Record in the same data structure. */
+struct GTY(()) lambda_discriminator
{
- tree t;
- int i;
+ tree scope;
+ unsigned nesting; // Inside a function, VAR_DECLs get the function
+ // as scope. This counts that nesting.
+ unsigned count; // The per-scope counter.
};
-static GTY(()) vec<tree_int, va_gc> *lambda_scope_stack;
+// The current scope.
+static GTY(()) lambda_discriminator lambda_scope;
+// Stack of previous scopes.
+static GTY(()) vec<lambda_discriminator, va_gc> *lambda_scope_stack;
+
+// Push DECL as lambda extra scope, also new discriminator counters.
void
start_lambda_scope (tree decl)
{
- tree_int ti;
- gcc_assert (decl);
- /* Once we're inside a function, we ignore variable scope and just push
- the function again so that popping works properly. */
+ gcc_checking_assert (decl);
if (current_function_decl && TREE_CODE (decl) == VAR_DECL)
- decl = current_function_decl;
- ti.t = lambda_scope;
- ti.i = lambda_count;
- vec_safe_push (lambda_scope_stack, ti);
- if (lambda_scope != decl)
+ // If we're inside a function, we ignore variable scope. Don't push.
+ lambda_scope.nesting++;
+ else
{
- /* Don't reset the count if we're still in the same function. */
- lambda_scope = decl;
- lambda_count = 0;
+ vec_safe_push (lambda_scope_stack, lambda_scope);
+ lambda_scope.scope = decl;
+ lambda_scope.nesting = 0;
+ lambda_scope.count = 0;
}
}
+// Pop from the current lambda extra scope.
+
void
-record_lambda_scope (tree lambda)
+finish_lambda_scope (void)
{
- LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;
- LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
- if (lambda_scope)
+ if (!lambda_scope.nesting--)
{
- tree closure = LAMBDA_EXPR_CLOSURE (lambda);
- gcc_checking_assert (closure);
- maybe_key_decl (lambda_scope, TYPE_NAME (closure));
+ lambda_scope = lambda_scope_stack->last ();
+ lambda_scope_stack->pop ();
}
}
-/* This lambda is an instantiation of a lambda in a template default argument
- that got no LAMBDA_EXPR_EXTRA_SCOPE, so this shouldn't either. But we do
- need to use and increment the global count to avoid collisions. */
+// Record the current lambda scope into LAMBDA
void
-record_null_lambda_scope (tree lambda)
+record_lambda_scope (tree lambda)
{
- if (vec_safe_is_empty (lambda_scope_stack))
- record_lambda_scope (lambda);
- else
+ LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope.scope;
+ if (lambda_scope.scope)
{
- tree_int *p = lambda_scope_stack->begin();
- LAMBDA_EXPR_EXTRA_SCOPE (lambda) = p->t;
- LAMBDA_EXPR_DISCRIMINATOR (lambda) = p->i++;
+ tree closure = LAMBDA_EXPR_CLOSURE (lambda);
+ gcc_checking_assert (closure);
+ maybe_key_decl (lambda_scope.scope, TYPE_NAME (closure));
}
- gcc_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == NULL_TREE);
}
+// Record the per-scope discriminator of LAMBDA. If the extra scope
+// is empty, we must use the empty scope counter, which might not be
+// the live one.
+
void
-finish_lambda_scope (void)
+record_lambda_scope_discriminator (tree lambda)
{
- tree_int *p = &lambda_scope_stack->last ();
- if (lambda_scope != p->t)
- {
- lambda_scope = p->t;
- lambda_count = p->i;
- }
- lambda_scope_stack->pop ();
+ auto *slot = (vec_safe_is_empty (lambda_scope_stack)
+ || LAMBDA_EXPR_EXTRA_SCOPE (lambda)
+ ? &lambda_scope : lambda_scope_stack->begin ());
+ LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++;
}
tree
@@ -1648,6 +1646,10 @@ prune_lambda_captures (tree body)
}
}
+// Record the per-scope per-signature discriminator of LAMBDA. If the
+// extra scope is empty, we must use the empty scope counter, which
+// might not be the live one.
+
void
finish_lambda_function (tree body)
{
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index e396218..a62c975 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1810,7 +1810,7 @@ write_closure_type_name (const tree type)
write_method_parms (parms, /*method_p=*/1, fn);
write_char ('E');
- write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
+ write_compact_number (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda));
}
/* Convert NUMBER to ascii using base BASE and generating at least
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9957df5..df05b52 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -6327,7 +6327,7 @@ trees_out::core_vals (tree t)
if (streaming_p ())
{
WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode);
- WU (((lang_tree_node *)t)->lambda_expression.discriminator);
+ WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
}
break;
@@ -6819,7 +6819,7 @@ trees_in::core_vals (tree t)
= state->read_location (*this);
RUC (cp_lambda_default_capture_mode_type,
((lang_tree_node *)t)->lambda_expression.default_capture_mode);
- RU (((lang_tree_node *)t)->lambda_expression.discriminator);
+ RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
break;
case OVERLOAD:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 6da3280..e0e3cf3 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -11035,6 +11035,7 @@ cp_parser_lambda_expression (cp_parser* parser)
return error_mark_node;
record_lambda_scope (lambda_expr);
+ record_lambda_scope_discriminator (lambda_expr);
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
@@ -11085,9 +11086,7 @@ cp_parser_lambda_expression (cp_parser* parser)
ok = false;
if (ok)
- {
- cp_parser_lambda_body (parser, lambda_expr);
- }
+ cp_parser_lambda_body (parser, lambda_expr);
else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
{
if (cp_parser_skip_to_closing_brace (parser))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 51bfbbc..fc6279c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19866,21 +19866,13 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == error_mark_node)
return error_mark_node;
- if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
- {
- /* A lambda in a default argument outside a class gets no
- LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
- tsubst_default_argument calls start_lambda_scope, so we need to
- specifically ignore it here, and use the global scope. */
- record_null_lambda_scope (r);
-
- /* If we're pushed into another scope (PR105652), fix it. */
- if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
- TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
- = TYPE_CONTEXT (TREE_TYPE (t));
- }
- else
+ if (LAMBDA_EXPR_EXTRA_SCOPE (t))
record_lambda_scope (r);
+ else if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
+ /* If we're pushed into another scope (PR105652), fix it. */
+ TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
+ = TYPE_CONTEXT (TREE_TYPE (t));
+ record_lambda_scope_discriminator (r);
/* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
determine_visibility (TYPE_NAME (type));
@@ -19911,29 +19903,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
fntype = build_memfn_type (fntype, type,
type_memfn_quals (fntype),
type_memfn_rqual (fntype));
- tree fn, tmpl;
- if (oldtmpl)
+ tree inst = (oldtmpl
+ ? tsubst_template_decl (oldtmpl, args, complain, fntype)
+ : tsubst_function_decl (oldfn, args, complain, fntype));
+ if (inst == error_mark_node)
{
- tmpl = tsubst_template_decl (oldtmpl, args, complain, fntype);
- if (tmpl == error_mark_node)
- {
- r = error_mark_node;
- goto out;
- }
- fn = DECL_TEMPLATE_RESULT (tmpl);
- finish_member_declaration (tmpl);
- }
- else
- {
- tmpl = NULL_TREE;
- fn = tsubst_function_decl (oldfn, args, complain, fntype);
- if (fn == error_mark_node)
- {
- r = error_mark_node;
- goto out;
- }
- finish_member_declaration (fn);
+ r = error_mark_node;
+ goto out;
}
+ finish_member_declaration (inst);
+
+ tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst;
/* Let finish_function set this. */
DECL_DECLARED_CONSTEXPR_P (fn) = false;
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
new file mode 100644
index 0000000..cb71209
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++20 } }
+// { dg-options -fabi-version=17 }
+
+#include "lambda-sig1.h"
+
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE3_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE3_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE6_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E7_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E5_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE0_clEi:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE3_clEi:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E1_clIiEEDaiS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E4_clIiEEDaiS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1.h b/gcc/testsuite/g++.dg/abi/lambda-sig1.h
new file mode 100644
index 0000000..a8b77ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-sig1.h
@@ -0,0 +1,42 @@
+template<typename T, unsigned I> struct X
+{
+ void Fn ()
+ {
+ {
+ auto v1 = []<typename U> (U) {};
+ auto v2 = [] (T) {};
+ auto v3 = []<typename U> (T, U) {};
+
+ v1 (1);
+ v2 (1);
+ v3 (1, 2);
+ }
+ if constexpr (I)
+ {
+ auto v1 = []<typename U> (U) {};
+ auto v2 = [] (T) {};
+ auto v3 = []<typename U> (T, U) {};
+
+ v1 (1);
+ v2 (1);
+ v3 (1, 2);
+ }
+ {
+ auto v1 = []<typename U> (U) {};
+ auto v2 = [] (T) {};
+ auto v3 = []<typename U> (T, U) {};
+
+ v1 (1);
+ v2 (1);
+ v3 (1, 2);
+ }
+
+ };
+};
+
+void f (X<int, 0> &x, X<float, 0> &y, X<float, 1> &z)
+{
+ x.Fn ();
+ y.Fn ();
+ z.Fn ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
new file mode 100644
index 0000000..9847587
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fabi-version=11 }
+
+// PRs 78621
+
+#include "lambda-mangle-1.h"
+
+// We erroneously mangled lambda auto parms as-if template parameters (T<n>_),
+// rather than auto (Da). Fixed in abi version 11
+
+
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
new file mode 100644
index 0000000..31af5b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fabi-version=17 }
+
+// PRs 78621
+
+#include "lambda-mangle-1.h"
+
+// We erroneously mangled lambda auto parms as-if template parameters (T<n>_),
+// rather than auto (Da). Fixed in abi version 11
+// Up to abi version 17 we had a single per-scope discriminator
+
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h
index 8f13535..c91ce01 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h
@@ -23,7 +23,7 @@ template<typename S, typename T>
{
}
-void Foo ()
+inline void Foo ()
{
auto lam = [](auto &) { };
auto lam_1 = [](int &, auto &) { };
@@ -70,6 +70,7 @@ template<typename X> void Bar ()
void Baz ()
{
Bar<short> ();
+ Foo ();
}
// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }