diff mbox series

c++: block-scope extern decl with default args

Message ID 7f5d5cb8-3a4c-3b9b-1769-474961fdec5e@acm.org
State New
Headers show
Series c++: block-scope extern decl with default args | expand

Commit Message

Nathan Sidwell Oct. 20, 2020, 7:19 p.m. UTC
In adding the DECL_LOCAL_DECL handling,	I'd forgotten that the
parm-decls also need cloning -- and resetting of their DECL_CONTEXT.
Also, any default args need droping when adding an alias, as those are
not propagated.	 The std's not totally clear on	this latter point when
there's no exising namespace decl, but that seems like the right thing
and is what clang does.

         gcc/cp/
         * name-lookup.c (push_local_extern_decl_alias): Reconstextualize
         alias' parm decls.  Drop any default args.
         gcc/testsuite/
         * g++.dg/lookup/local-extern.C: New.

pushing to trunk

nathan
diff mbox series

Patch

diff --git c/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c
index e951fb7885b..46374278068 100644
--- c/gcc/cp/name-lookup.c
+++ w/gcc/cp/name-lookup.c
@@ -2969,6 +2969,52 @@  push_local_extern_decl_alias (tree decl)
 	{
 	  /* No existing namespace-scope decl.  Make one.  */
 	  alias = copy_decl (decl);
+	  if (TREE_CODE (alias) == FUNCTION_DECL)
+	    {
+	      /* Recontextualize the parms.  */
+	      for (tree *chain = &DECL_ARGUMENTS (alias);
+		   *chain; chain = &DECL_CHAIN (*chain))
+		{
+		  *chain = copy_decl (*chain);
+		  DECL_CONTEXT (*chain) = alias;
+		}
+
+	      tree type = TREE_TYPE (alias);
+	      for (tree args = TYPE_ARG_TYPES (type);
+		   args; args = TREE_CHAIN (args))
+		if (TREE_PURPOSE (args))
+		  {
+		    /* There are default args.  Lose them.  */
+		    tree nargs = NULL_TREE;
+		    tree *chain = &nargs;
+		    for (args = TYPE_ARG_TYPES (type);
+			 args; args = TREE_CHAIN (args))
+		      if (args == void_list_node)
+			{
+			  *chain = args;
+			  break;
+			}
+		      else
+			{
+			  *chain
+			    = build_tree_list (NULL_TREE, TREE_VALUE (args));
+			  chain = &TREE_CHAIN (*chain);
+			}
+
+		    tree fn_type = build_function_type (TREE_TYPE (type), nargs);
+
+		    fn_type = apply_memfn_quals
+		      (fn_type, type_memfn_quals (type));
+
+		    fn_type = build_cp_fntype_variant
+		      (fn_type, type_memfn_rqual (type),
+		       TYPE_RAISES_EXCEPTIONS (type),
+		       TYPE_HAS_LATE_RETURN_TYPE (type));
+
+		    TREE_TYPE (alias) = fn_type;
+		    break;
+		  }
+	    }
 
 	  /* This is the real thing.  */
 	  DECL_LOCAL_DECL_P (alias) = false;
diff --git c/gcc/testsuite/g++.dg/lookup/local-extern.C w/gcc/testsuite/g++.dg/lookup/local-extern.C
new file mode 100644
index 00000000000..1d6d8617bde
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/local-extern.C
@@ -0,0 +1,13 @@ 
+int foo ()
+{
+  extern int baz (int i = 5);
+  return baz ();
+}
+
+int baz (int i = 0);
+
+int bar ()
+{
+  extern int baz (int i = 6);
+  return baz ();
+}