[C++] builtin fn creation
diff mbox series

Message ID 9ed2e759-e361-df6c-62d8-616e744dc551@acm.org
State New
Headers show
Series
  • [C++] builtin fn creation
Related show

Commit Message

Nathan Sidwell Oct. 17, 2019, 12:03 p.m. UTC
We're rather lax about setting DECL_CONTEXT correctly on several classes 
of builtins.  This is affecting modules.  But in cleaning it up I 
noticed cxx_builtin_function & cxx_builtin_function_ext_scope
* are doing very similar work (they're identical except for a boolean 
value).
* through a worker that repeats work (builtin_function_1 repeats its 
analysis on the ::std version).
* and the latter incorrectly pushes things intended for ::std into ::, 
(because it uses pushdecl_top_level (decl))

The bug I encountered was that the version pushed to :: had a NULL 
context (rather than FROB_CONTEXT (global_namespace), which is the 
translation unit decl).

This patch
* implements cxx_builtin_function_ext_scope in terms of 
cxx_builtin_function, by wrapping that call in a push_nested_namespace 
(global_namespace).
* folds builtin_function_1 into cxx_builtin_function
* applies the transforms to the incoming decl before cloning it
* uses copy_decl, a c++ decl-specific copy_node, which correctly 
duplicates the lang-specific data
* uses IDENTIFIER_LENGTH rather than strlen
* set DECL_CONTEXT to FROB_CONTEXT (current_namespace).

applying to trunk.

nathan

Patch
diff mbox series

2019-10-17  Nathan Sidwell  <nathan@acm.org>

	* decl.c (builtin_function_1): Merge into ...
	(cxx_builtin_function): ... here.  Nadger the decl before maybe
	copying it.  Set the context.
	(cxx_builtin_function_ext_scope): Push to top level, then call
	cxx_builtin_function.

Index: decl.c
===================================================================
--- decl.c	(revision 277098)
+++ decl.c	(working copy)
@@ -72,5 +72,4 @@  static tree grokvardecl (tree, tree, tre
 static void check_static_variable_definition (tree, tree);
 static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (tree, tree, bool);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static tree local_variable_p_walkfn (tree *, int *, void *);
@@ -4630,10 +4629,11 @@  cp_make_fname_decl (location_t loc, tree
 }
 
-static tree
-builtin_function_1 (tree decl, tree context, bool is_global)
-{
-  tree          id = DECL_NAME (decl);
-  const char *name = IDENTIFIER_POINTER (id);
+/* Install DECL as a builtin function at current (global) scope.
+   Return the new decl (if we found an existing version).  Also
+   installs it into ::std, if it's not '_*'.  */
 
+tree
+cxx_builtin_function (tree decl)
+{
   retrofit_lang_decl (decl);
 
@@ -4645,45 +4645,33 @@  builtin_function_1 (tree decl, tree cont
   DECL_VISIBILITY_SPECIFIED (decl) = 1;
 
-  DECL_CONTEXT (decl) = context;
-
-  /* A function in the user's namespace should have an explicit
-     declaration before it is used.  Mark the built-in function as
-     anticipated but not actually declared.  */
+  tree id = DECL_NAME (decl);
+  const char *name = IDENTIFIER_POINTER (id);
   if (name[0] != '_' || name[1] != '_')
+    /* In the user's namespace, it must be declared before use.  */
+    DECL_ANTICIPATED (decl) = 1;
+  else if (IDENTIFIER_LENGTH (id) > strlen ("___chk")
+	   && 0 != strncmp (name + 2, "builtin_", strlen ("builtin_"))
+	   && 0 == memcmp (name + IDENTIFIER_LENGTH (id) - strlen ("_chk"),
+			   "_chk", strlen ("_chk") + 1))
+    /* Treat __*_chk fortification functions as anticipated as well,
+       unless they are __builtin_*_chk.  */
     DECL_ANTICIPATED (decl) = 1;
-  else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0)
-    {
-      size_t len = strlen (name);
-
-      /* Treat __*_chk fortification functions as anticipated as well,
-	 unless they are __builtin_*.  */
-      if (len > strlen ("___chk")
-	  && memcmp (name + len - strlen ("_chk"),
-		     "_chk", strlen ("_chk") + 1) == 0)
-	DECL_ANTICIPATED (decl) = 1;
-    }
-
-  if (is_global)
-    return pushdecl_top_level (decl);
-  else
-    return pushdecl (decl);
-}
 
-tree
-cxx_builtin_function (tree decl)
-{
-  tree          id = DECL_NAME (decl);
-  const char *name = IDENTIFIER_POINTER (id);
   /* All builtins that don't begin with an '_' should additionally
      go in the 'std' namespace.  */
   if (name[0] != '_')
     {
-      tree decl2 = copy_node(decl);
+      tree std_decl = copy_decl (decl);
+
       push_namespace (std_identifier);
-      builtin_function_1 (decl2, std_node, false);
+      DECL_CONTEXT (std_decl) = FROB_CONTEXT (std_node);
+      pushdecl (std_decl);
       pop_namespace ();
     }
 
-  return builtin_function_1 (decl, NULL_TREE, false);
+  DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+  decl = pushdecl (decl);
+
+  return decl;
 }
 
@@ -4697,18 +4685,9 @@  tree
 cxx_builtin_function_ext_scope (tree decl)
 {
+  push_nested_namespace (global_namespace);
+  decl = cxx_builtin_function (decl);
+  pop_nested_namespace (global_namespace);
 
-  tree          id = DECL_NAME (decl);
-  const char *name = IDENTIFIER_POINTER (id);
-  /* All builtins that don't begin with an '_' should additionally
-     go in the 'std' namespace.  */
-  if (name[0] != '_')
-    {
-      tree decl2 = copy_node(decl);
-      push_namespace (std_identifier);
-      builtin_function_1 (decl2, std_node, true);
-      pop_namespace ();
-    }
-
-  return builtin_function_1 (decl, NULL_TREE, true);
+  return decl;
 }