aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lambda.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/lambda.cc')
-rw-r--r--gcc/cp/lambda.cc96
1 files changed, 49 insertions, 47 deletions
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)
{