]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Stop using gnat_envp
authorRonan Desplanques <desplanques@adacore.com>
Tue, 17 Mar 2026 14:38:44 +0000 (15:38 +0100)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Fri, 29 May 2026 08:49:48 +0000 (10:49 +0200)
First, a bit of context: Ada has only had support for manipulating
environment variables in the standard library since Ada 2005 and the
introduction of Ada.Environment_Variables.

Prior to that, GNAT had introduced the implementation-specific
Ada.Command_Line.Environment, which still exists today. Until now,
Ada.Command_Line.Environment used a global variable, gnat_envp, which
must be initialized with envp, the optional third parameter to main in C.
When the main was in Ada, the binder generated the appropriate assignment.
The rest of the time, it was the responsibility of the user to write this
assignment. Failure to do so would cause null pointer dereferences when
using Ada.Command_Line.Environment. Although documented in the spec of
Ada.Command_Line, this was rather easy to miss.

Worse, the assignment caused linking failures in the rather common case
of a C GPR project with'ing an Ada GPR project and linking dynamically.

Also, Ada.Command_Line.Environment was inconsistent across platforms with
regard to how it was affected by calls to putenv.

When we added support for the standard Ada.Environment_Variables, the
gnat_envp machinery wasn't reused. Instead, another mechanism based on
the Unix global variable environ (and its close equivalents on other
platforms) was introduced.

What this patch does is switch Ada.Command_Line.Environment over to this
new environ-based mechanism. All uses of gnat_envp are removed, but the
definition itself is kept for backwards compatibility.

gcc/ada/ChangeLog:

* argv-lynxos178-raven-cert.c: Update comments.
* argv.c (gnat_envp): Add comment about it being unused.
(__gnat_env_count, __gnat_len_env, __gnat_fill_env): Use
__gnat_environ instead of gnat_envp.
* bindgen.adb (Command_Line_Used): Update comment.
(Gen_Main): Remove gnat_envp assignment generation. Remove generated
envp parameter.
(Gen_Output_File_Ada): Remove generated envp parameter.
* env.h: Make usable as C++.
* libgnat/a-colien.ads: Remove comment.
* libgnat/a-comlin.ads: Update comment.
* targparm.ads: Update comment.

gcc/ada/argv-lynxos178-raven-cert.c
gcc/ada/argv.c
gcc/ada/bindgen.adb
gcc/ada/env.h
gcc/ada/libgnat/a-colien.ads
gcc/ada/libgnat/a-comlin.ads
gcc/ada/targparm.ads

index 1f4147fb8f6fbc33fae3186d0c2806ec62cc1281..5876fea7c0427769362d11240031e31326f2a1cd 100644 (file)
 extern "C" {
 #endif
 
-/* argc and argv of the main program are saved under gnat_argc and gnat_argv,
-   envp of the main program is saved under gnat_envp.
-   While gnat_argc and gnat_envp are not needed, they are referenced from
-   the binder-generated file so they need to be defined here */
+/* argc and argv of the main program are saved under gnat_argc and gnat_argv.
+   While gnat_argc is not needed, it's referenced from the binder-generated
+   file so it needs to be defined here */
 
 int gnat_argc = 0;
 char **gnat_argv = NULL;
+
+/* It used to be the case that users were required to forward the envp
+   parameter of main to the variable below when using a non-Ada main. The
+   consequences for failing to meet the requirement was improper operation of
+   Ada.Command_Line.Environment.
+
+   Today, users are not required to do anything with gnat_envp and
+   Ada.Command_Line.Environment does not use it anymore. In fact it's not used
+   by anything, but we keep its definition so that programs that obey the old
+   requirement keep linking. */
 char **gnat_envp = NULL;
 
 int
index aed6d2257f15abee5815b1f585d2d22ba9c19e66..6d670e1aa5dd62f8eeadc156109b262cd80e96c1 100644 (file)
    gnat_argv are the values as modified by toplev, and these routines
    are accessed from the Osint package.  */
 
-/* Also routines for accessing the environment from the runtime library.
-   Gnat_envp is the original envp value as stored by the binder generated
-   main program, and these routines are accessed from the
-   Ada.Command_Line.Environment package.  */
-
 #ifdef IN_RTS
 #include "runtime.h"
 #include <stdlib.h>
 #include "adaint.h"
 #endif
 
+#include "env.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* argc and argv of the main program are saved under gnat_argc and gnat_argv,
-   envp of the main program is saved under gnat_envp.  */
+/* argc and argv of the main program are saved under gnat_argc and gnat_argv */
 
 int gnat_argc = 0;
 char **gnat_argv = NULL;
-char **gnat_envp = NULL;
 
-#if defined (_WIN32) && !defined (RTX)
-/* Note that on Windows environment the environ point to a buffer that could
-   be reallocated if needed. It means that gnat_envp needs to be updated
-   before using gnat_envp to point to the right environment space */
-/* for the environ variable definition */
-#define gnat_envp (environ)
-#endif
+/* It used to be the case that users were required to forward the envp
+   parameter of main to the variable below when using a non-Ada main. The
+   consequences for failing to meet the requirement was improper operation of
+   Ada.Command_Line.Environment.
+
+   Today, users are not required to do anything with gnat_envp and
+   Ada.Command_Line.Environment does not use it anymore. In fact it's not used
+   by anything, but we keep its definition so that programs that obey the old
+   requirement keep linking. */
+char **gnat_envp = NULL;
 
 int
 __gnat_arg_count (void)
@@ -100,8 +98,9 @@ int
 __gnat_env_count (void)
 {
   int i;
+  char **envp = __gnat_environ();
 
-  for (i = 0; gnat_envp[i]; i++)
+  for (i = 0; envp[i]; i++)
     ;
   return i;
 }
@@ -109,8 +108,10 @@ __gnat_env_count (void)
 int
 __gnat_len_env (int env_num)
 {
-  if (gnat_envp != NULL)
-    return strlen (gnat_envp[env_num]);
+  char **envp = __gnat_environ();
+
+  if (envp != NULL)
+    return strlen (envp[env_num]);
   else
     return 0;
 }
@@ -118,8 +119,10 @@ __gnat_len_env (int env_num)
 void
 __gnat_fill_env (char *a, int i)
 {
-  if (gnat_envp != NULL)
-    memcpy (a, gnat_envp[i], strlen (gnat_envp[i]));
+  char **envp = __gnat_environ();
+
+  if (envp != NULL)
+    memcpy (a, envp[i], strlen (envp[i]));
 }
 
 #ifdef __cplusplus
index 8e940c314125b1deb3a72945c02db94f53bd6609..2f13cd6dee40dad8979b43aaf9d15500657e389b 100644 (file)
@@ -61,8 +61,8 @@ package body Bindgen is
    --  Flag indicating whether the unit Ada.Command_Line is in the closure of
    --  the partition. This is set by Resolve_Binder_Options, and is used to
    --  determine whether or not to import and use symbols defined in
-   --  Ada.Command_Line's support packages (gnat_argc, gnat_argv, gnat_envp
-   --  and gnat_exit_status). Conservatively, it is always set to True for
+   --  Ada.Command_Line's support packages (gnat_argc, gnat_argv and
+   --  gnat_exit_status). Conservatively, it is always set to True for
    --  non-configurable run-times as parts of the compiler and run-time assume
    --  these symbols are available and can be imported directly.
 
@@ -2021,8 +2021,7 @@ package body Bindgen is
       if Command_Line_Args_On_Target then
          Write_Statement_Buffer;
          WBI ("     (argc : Integer;");
-         WBI ("      argv : System.Address;");
-         WBI ("      envp : System.Address)");
+         WBI ("      argv : System.Address)");
 
          if Exit_Status_Supported_On_Target then
             WBI ("      return Integer");
@@ -2135,7 +2134,6 @@ package body Bindgen is
          WBI ("         gnat_argc := argc;");
          WBI ("         gnat_argv := argv;");
          WBI ("      end if;");
-         WBI ("      gnat_envp := envp;");
          WBI ("");
       end if;
 
@@ -2613,12 +2611,10 @@ package body Bindgen is
             WBI ("");
             WBI ("   gnat_argc : Integer;");
             WBI ("   gnat_argv : System.Address;");
-            WBI ("   gnat_envp : System.Address;");
 
             WBI ("");
             WBI ("   pragma Import (C, gnat_argc);");
             WBI ("   pragma Import (C, gnat_argv);");
-            WBI ("   pragma Import (C, gnat_envp);");
          end if;
 
          --  Define exit status if supported by the target. The exit status is
@@ -2723,9 +2719,8 @@ package body Bindgen is
          if Command_Line_Args_On_Target then
             Write_Statement_Buffer;
             WBI ("     (argc : Integer;");
-            WBI ("      argv : System.Address;");
             Set_String
-                ("      envp : System.Address)");
+                ("      argv : System.Address)");
 
             if Exit_Status_Supported_On_Target then
                Write_Statement_Buffer;
index 29c96fd762fec38923cd2132f2270c1566a6e4c5..5bf69e7f5bbd94f52f8572482a531bc2fcf99d89 100644 (file)
  *                                                                          *
  ****************************************************************************/
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern void __gnat_getenv (char *name, int *len, char **value);
 extern void __gnat_setenv (char *name, char *value);
 extern char **__gnat_environ (void);
 extern void __gnat_unsetenv (char *name);
 extern void __gnat_clearenv(void);
+
+#ifdef __cplusplus
+}
+#endif
index b687f083cea639cb625bc509957532ef4ca1d8f6..a84e3cd520234629a784790916a08031f5c54d9d 100644 (file)
 --                                                                          --
 ------------------------------------------------------------------------------
 
---  Note: Services offered by this package are guaranteed to be platform
---  independent as long as no call to GNAT.OS_Lib.Setenv or to C putenv
---  routine is done. On some platforms the services below will report new
---  environment variables (e.g. Windows) on some others it will not
---  (e.g. GNU/Linux and Solaris).
-
 package Ada.Command_Line.Environment is
 
    function Environment_Count return Natural;
index a7d37a7151f63c3642fbf7db0aba83076f5b58bc..f6e2cf2a6fbd7875a22dbf2acd15bf4bf488f825 100644 (file)
@@ -100,14 +100,12 @@ package Ada.Command_Line is
    --  main program, and the following is an example of a complete C main
    --  program that stores the required information:
 
-   --    main(int argc, char **argv, char **envp)
+   --    main(int argc, char **argv)
    --    {
    --       extern int    gnat_argc;
    --       extern char **gnat_argv;
-   --       extern char **gnat_envp;
    --       gnat_argc = argc;
    --       gnat_argv = argv;
-   --       gnat_envp = envp;
 
    --       adainit();
    --       adamain();
index d5004baa85c5a4aec5b8cebfd1c17a0a62fe57e2..0ece5857ee0ef8011bac93fd2cca6f8dbcac7e20 100644 (file)
@@ -267,10 +267,10 @@ package Targparm is
    --
    --  This has some specific effects as follows
    --
-   --    The binder generates the gnat_argc/argv/envp variables in the
-   --    binder file instead of being imported from the run-time library.
-   --    If Command_Line_Args_On_Target is set to False, then the
-   --    generation of these variables is suppressed completely.
+   --    The binder generates the gnat_argc/argv variables in the binder file
+   --    instead of being imported from the run-time library. If
+   --    Command_Line_Args_On_Target is set to False, then the generation of
+   --    these variables is suppressed completely.
    --
    --    The routine __gnat_break_start is defined within the binder file
    --    instead of being imported from the run-time library.