diff options
Diffstat (limited to 'gcc/cp/lambda.cc')
-rw-r--r-- | gcc/cp/lambda.cc | 96 |
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) { |