From f40866967d69079fdde293feb32d2eb52cb93cc8 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 10 Sep 2020 05:38:29 -0700 Subject: [PATCH] c++: DECL_LOCAL_FUNCTION_P -> DECL_LOCAL_DECL_P Our handling of block-scope extern decls is insufficient for modern C++, in particular modules, (but also constexprs). We mark such local function decls, and this patch extends that to marking local var decls too, so mainly a macro rename. Also, we set this flag earlier, rather than learning about it when pushing the decl. This is a step towards handling these properly. gcc/cp/ * cp-tree.h (DECL_LOCAL_FUNCTION_P): Rename to ... (DECL_LOCAL_DECL_P): ... here. Accept both fns and vars. * decl.c (start_decl): Set DECL_LOCAL_DECL_P for local externs. (omp_declare_variant_finalize_one): Use DECL_LOCAL_DECL_P. (local_variable_p): Simplify. * name-lookup.c (set_decl_context_in_fn): Assert DECL_LOCAL_DECL_P is as expected. Simplify. (do_pushdecl): Don't set decl_context_in_fn for friends. (is_local_extern): Simplify. * call.c (equal_functions): Use DECL_LOCAL_DECL_P. * parser.c (cp_parser_postfix_expression): Likewise. (cp_parser_omp_declare_reduction): Likewise. * pt.c (check_default_tmpl_args): Likewise. (tsubst_expr): Assert nested reduction function is local. (type_dependent_expression_p): Use DECL_LOCAL_DECL_P. * semantics.c (finish_call_expr): Likewise. libcc1/ * libcp1plugin.cc (plugin_build_call_expr): Use DECL_LOCAL_DECL_P. --- gcc/cp/call.c | 2 +- gcc/cp/cp-tree.h | 10 +++++----- gcc/cp/decl.c | 19 ++++++++++-------- gcc/cp/name-lookup.c | 45 +++++++++++------------------------------- gcc/cp/parser.c | 3 ++- gcc/cp/pt.c | 5 +++-- gcc/cp/semantics.c | 2 +- libcc1/libcp1plugin.cc | 2 +- 8 files changed, 36 insertions(+), 52 deletions(-) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 61bbb38bd2b..5606389f4bd 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3631,7 +3631,7 @@ equal_functions (tree fn1, tree fn2) return 0; if (TREE_CODE (fn1) == TEMPLATE_DECL) return fn1 == fn2; - if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2) + if (DECL_LOCAL_DECL_P (fn1) || DECL_LOCAL_DECL_P (fn2) || DECL_EXTERN_C_FUNCTION_P (fn1)) return decls_match (fn1, fn2); return fn1 == fn2; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 78739411755..b12c78739e4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -506,7 +506,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; Usage of DECL_LANG_FLAG_?: 0: DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL) - DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL) + DECL_LOCAL_DECL_P (in FUNCTION_DECL, VAR_DECL) DECL_MUTABLE_P (in FIELD_DECL) DECL_DEPENDENT_P (in USING_DECL) LABEL_DECL_BREAK (in LABEL_DECL) @@ -4009,10 +4009,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define TYPE_CONTAINS_VPTR_P(NODE) \ (TYPE_POLYMORPHIC_P (NODE) || CLASSTYPE_VBASECLASSES (NODE)) -/* Nonzero if NODE is a FUNCTION_DECL (for a function with global - scope) declared in a local scope. */ -#define DECL_LOCAL_FUNCTION_P(NODE) \ - DECL_LANG_FLAG_0 (FUNCTION_DECL_CHECK (NODE)) +/* Nonzero if NODE is a FUNCTION_DECL or VARIABLE_DECL (for a decl + with namespace scope) declared in a local scope. */ +#define DECL_LOCAL_DECL_P(NODE) \ + DECL_LANG_FLAG_0 (VAR_OR_FUNCTION_DECL_CHECK (NODE)) /* Nonzero if NODE is the target for genericization of 'break' stmts. */ #define LABEL_DECL_BREAK(NODE) \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ce97d19884d..be2bc9db2e5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5199,8 +5199,8 @@ groktypename (cp_decl_specifier_seq *type_specifiers, return type; } -/* Process a DECLARATOR for a function-scope variable declaration, - namespace-scope variable declaration, or function declaration. +/* Process a DECLARATOR for a function-scope or namespace-scope + variable or function declaration. (Function definitions go through start_function; class member declarations appearing in the body of the class go through grokfield.) The DECL corresponding to the DECLARATOR is returned. @@ -5410,6 +5410,11 @@ start_decl (const cp_declarator *declarator, was_public = TREE_PUBLIC (decl); + if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) + && current_function_decl) + /* A function-scope decl of some namespace-scope decl. */ + DECL_LOCAL_DECL_P (decl) = true; + /* Enter this declaration into the symbol table. Don't push the plain VAR_DECL for a variable template. */ if (!template_parm_scope_p () @@ -7360,7 +7365,7 @@ omp_declare_variant_finalize_one (tree decl, tree attr) fn = STRIP_TEMPLATE (fn); if (!((TREE_CODE (fn) == USING_DECL && DECL_DEPENDENT_P (fn)) || DECL_FUNCTION_MEMBER_P (fn) - || DECL_LOCAL_FUNCTION_P (fn))) + || DECL_LOCAL_DECL_P (fn))) { koenig_p = true; if (!any_type_dependent_arguments_p (args)) @@ -13877,11 +13882,9 @@ int local_variable_p (const_tree t) { if ((VAR_P (t) - /* A VAR_DECL with a context that is a _TYPE is a static data - member. */ - && !TYPE_P (CP_DECL_CONTEXT (t)) - /* Any other non-local variable must be at namespace scope. */ - && !DECL_NAMESPACE_SCOPE_P (t)) + && (DECL_LOCAL_DECL_P (t) + || !DECL_CONTEXT (t) + || TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)) || (TREE_CODE (t) == PARM_DECL)) return 1; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3c2ddc197e6..bbeaf64104b 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2855,14 +2855,13 @@ check_local_shadow (tree decl) static void set_decl_context_in_fn (tree ctx, tree decl) { + if (TREE_CODE (decl) == FUNCTION_DECL + || (VAR_P (decl) && DECL_EXTERNAL (decl))) + /* Make sure local externs are marked as such. */ + gcc_checking_assert (DECL_LOCAL_DECL_P (decl) + && DECL_NAMESPACE_SCOPE_P (decl)); + if (!DECL_CONTEXT (decl) - /* A local declaration for a function doesn't constitute - nesting. */ - && TREE_CODE (decl) != FUNCTION_DECL - /* A local declaration for an `extern' variable is in the - scope of the current namespace, not the current - function. */ - && !(VAR_P (decl) && DECL_EXTERNAL (decl)) /* When parsing the parameter list of a function declarator, don't set DECL_CONTEXT to an enclosing function. When we push the PARM_DECLs in order to process the function body, @@ -2871,12 +2870,6 @@ set_decl_context_in_fn (tree ctx, tree decl) && current_binding_level->kind == sk_function_parms && current_binding_level->this_entity == NULL)) DECL_CONTEXT (decl) = ctx; - - /* If this is the declaration for a namespace-scope function, - but the declaration itself is in a local scope, mark the - declaration. */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (decl)) - DECL_LOCAL_FUNCTION_P (decl) = 1; } /* DECL is a local-scope decl with linkage. SHADOWED is true if the @@ -2998,7 +2991,7 @@ do_pushdecl (tree decl, bool is_friend) if (decl == error_mark_node) return error_mark_node; - if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl) + if (!DECL_TEMPLATE_PARM_P (decl) && current_function_decl && !is_friend) set_decl_context_in_fn (current_function_decl, decl); /* The binding level we will be pushing into. During local class @@ -6682,29 +6675,15 @@ lookup_type_scope (tree name, tag_scope scope) } /* Returns true iff DECL is a block-scope extern declaration of a function - or variable. */ + or variable. We will already have determined validity of the decl + when pushing it. So we do not have to redo that lookup. */ bool is_local_extern (tree decl) { - cxx_binding *binding; - - /* For functions, this is easy. */ - if (TREE_CODE (decl) == FUNCTION_DECL) - return DECL_LOCAL_FUNCTION_P (decl); - - if (!VAR_P (decl)) - return false; - if (!current_function_decl) - return false; - - /* For variables, this is not easy. We need to look at the binding stack - for the identifier to see whether the decl we have is a local. */ - for (binding = IDENTIFIER_BINDING (DECL_NAME (decl)); - binding && binding->scope->kind != sk_namespace; - binding = binding->previous) - if (binding->value == decl) - return LOCAL_BINDING_P (binding); + if ((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL)) + return DECL_LOCAL_DECL_P (decl); return false; } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0da383937c2..916ea6cd910 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7467,7 +7467,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, if ((TREE_CODE (fn) == USING_DECL && DECL_DEPENDENT_P (fn)) || DECL_FUNCTION_MEMBER_P (fn) - || DECL_LOCAL_FUNCTION_P (fn)) + || DECL_LOCAL_DECL_P (fn)) { do_adl_p = false; break; @@ -42582,6 +42582,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, { block_scope = true; DECL_CONTEXT (fndecl) = global_namespace; + DECL_LOCAL_DECL_P (fndecl) = true; if (!processing_template_decl) pushdecl (fndecl); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4e212620eaf..d4ece3818a4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5417,7 +5417,7 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary, class template. */ if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL - || (TREE_CODE (decl) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (decl))) + || (TREE_CODE (decl) == FUNCTION_DECL && DECL_LOCAL_DECL_P (decl))) /* You can't have a function template declaration in a local scope, nor you can you define a member of a class template in a local scope. */ @@ -18080,6 +18080,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, /* We pretend this is regular local extern decl of a namespace-scope fn. Then we make it really local, it is a nested function. */ + gcc_checking_assert (DECL_LOCAL_DECL_P (decl)); DECL_CONTEXT (decl) = global_namespace; pushdecl (decl); DECL_CONTEXT (decl) = current_function_decl; @@ -26978,7 +26979,7 @@ type_dependent_expression_p (tree expression) && DECL_FRIEND_P (expression) && (!DECL_FRIEND_CONTEXT (expression) || dependent_type_p (DECL_FRIEND_CONTEXT (expression)))) - && !DECL_LOCAL_FUNCTION_P (expression)) + && !DECL_LOCAL_DECL_P (expression)) { gcc_assert (!dependent_type_p (TREE_TYPE (expression)) || undeduced_auto_decl (expression)); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 107d39ddb0e..dafb4032c00 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2518,7 +2518,7 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, { tree ifn = get_first_fn (fn); if (TREE_CODE (ifn) == FUNCTION_DECL - && DECL_LOCAL_FUNCTION_P (ifn)) + && DECL_LOCAL_DECL_P (ifn)) orig_fn = DECL_NAME (ifn); } diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index a83bfeb0a16..c8b30113ce6 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -3294,7 +3294,7 @@ plugin_build_call_expr (cc1_plugin::connection *self, fn = STRIP_TEMPLATE (fn); if (!DECL_FUNCTION_MEMBER_P (fn) - && !DECL_LOCAL_FUNCTION_P (fn)) + && !DECL_LOCAL_DECL_P (fn)) koenig_p = true; } } -- 2.30.2