diff mbox series

c++: DECL_LOCAL_FUNCTION_P -> DECL_LOCAL_DECL_P

Message ID 9a23f589-aa7f-4ef1-4726-0d54973189e9@acm.org
State New
Headers show
Series c++: DECL_LOCAL_FUNCTION_P -> DECL_LOCAL_DECL_P | expand

Commit Message

Nathan Sidwell Sept. 10, 2020, 12:43 p.m. UTC
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.
         (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/
         * licp1plugin.cc (plugin_build_call_expr): Use DECL_LOCAL_DECL_P.

pushed to trunk

nathan
diff mbox series

Patch

diff --git c/gcc/cp/call.c w/gcc/cp/call.c
index 61bbb38bd2b..5606389f4bd 100644
--- c/gcc/cp/call.c
+++ w/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 c/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h
index 78739411755..b12c78739e4 100644
--- c/gcc/cp/cp-tree.h
+++ w/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 c/gcc/cp/decl.c w/gcc/cp/decl.c
index ce97d19884d..be2bc9db2e5 100644
--- c/gcc/cp/decl.c
+++ w/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 c/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c
index 3c2ddc197e6..bbeaf64104b 100644
--- c/gcc/cp/name-lookup.c
+++ w/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 c/gcc/cp/parser.c w/gcc/cp/parser.c
index 0da383937c2..916ea6cd910 100644
--- c/gcc/cp/parser.c
+++ w/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 c/gcc/cp/pt.c w/gcc/cp/pt.c
index 4e212620eaf..d4ece3818a4 100644
--- c/gcc/cp/pt.c
+++ w/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 c/gcc/cp/semantics.c w/gcc/cp/semantics.c
index 107d39ddb0e..dafb4032c00 100644
--- c/gcc/cp/semantics.c
+++ w/gcc/cp/semantics.c
@@ -2518,7 +2518,7 @@  finish_call_expr (tree fn, vec<tree, va_gc> **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 c/libcc1/libcp1plugin.cc w/libcc1/libcp1plugin.cc
index a83bfeb0a16..c8b30113ce6 100644
--- c/libcc1/libcp1plugin.cc
+++ w/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;
 	}
     }