[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Thu, 12 Jan 2017 16:01:16 +0000 (17:01 +0100)
committerArnaud Charlet <charlet@gcc.gnu.org>
Thu, 12 Jan 2017 16:01:16 +0000 (17:01 +0100)
2017-01-12  Tristan Gingold  <gingold@adacore.com>

* s-mmap.ads, s-mmap.adb, s-mmosin-unix.ads, s-mmosin-unix.adb,
s-mmauni-long.ads, s-mmosin-mingw.ads, s-mmosin-mingw.adb: New files.

2017-01-12  Yannick Moy  <moy@adacore.com>

* errout.adb, errout.ads (Initialize): Factor common treatment
in Reset_Warnings.
(Reset_Warnings): New procedure to reset counts related to warnings.
(Record_Compilation_Errors): New variable to store the presence of an
error, used in gnat2why to allow changing the Warning_Mode.
(Compilation_Errors): Use new variable Record_Compilation_Errors to
store the presence of an error.

2017-01-12  Javier Miranda  <miranda@adacore.com>

* sem_ch13.adb (Analyze_Aspect_Specifications):
For Interrupt_Handler and Attach_ Handler aspects, decorate the
internally built reference to the protected procedure as coming
from sources and force its analysis.

2017-01-12  Ed Schonberg  <schonberg@adacore.com>

* sem_ch3.adb (Build_Derived_Type): For a scalar derived type,
inherit predicates if any from the first_subtype of the parent,
not from the anonymous parent type.
* sem_eval.adb (Is_Static_Subtype): A type that inherits a dynamic
predicate is not a static subtype.

2017-01-12  Gary Dismukes  <dismukes@adacore.com>

* freeze.adb (Check_Suspicious_Convention): New procedure
performing a warning check on discriminated record types with
convention C or C++. Factored out of procedure Freeze_Record_Type,
and changed to only apply to base types (to avoid spurious
warnings on subtypes). Minor improvement of warning messages
to refer to discriminated rather than variant record types.
(Freeze_Record_Type): Remove code for performing a suspicious
convention check.
(Freeze_Entity): Only call Freeze_Record_Type
on types that aren't declared within any enclosing generic units
(rather than just excluding the type when the innermost scope
is generic). Call Check_Suspicious_Convention whether or not
the type is declared within a generic unit.
* sem_ch8.adb (In_Generic_Scope): Move this function to Sem_Util.
* sem_util.ads, sem_util.adb (In_Generic_Scope): New function (moved
from Sem_Ch8).

2017-01-12  Tristan Gingold  <gingold@adacore.com>

* sysdep.c, adaint.c, rtinit.c, ming32.h:
(__gnat_current_codepage): Renamed from CurrentCodePage
(__gnat_current_ccs_encoding): Renamed from CurrentCCSEncoding

2017-01-12  Ed Schonberg  <schonberg@adacore.com>

* sem_ch6.adb (Fully_Conformant_Expressions): Handle properly
quantified expressions, following AI12-050: the loop parameters
of two quantified expressions are conformant if they have the
same identifier.

From-SVN: r244369

22 files changed:
gcc/ada/ChangeLog
gcc/ada/adaint.c
gcc/ada/errout.adb
gcc/ada/errout.ads
gcc/ada/freeze.adb
gcc/ada/mingw32.h
gcc/ada/rtinit.c
gcc/ada/s-mmap.adb [new file with mode: 0644]
gcc/ada/s-mmap.ads [new file with mode: 0644]
gcc/ada/s-mmauni-long.ads [new file with mode: 0644]
gcc/ada/s-mmosin-mingw.adb [new file with mode: 0644]
gcc/ada/s-mmosin-mingw.ads [new file with mode: 0644]
gcc/ada/s-mmosin-unix.adb [new file with mode: 0644]
gcc/ada/s-mmosin-unix.ads [new file with mode: 0644]
gcc/ada/sem_ch13.adb
gcc/ada/sem_ch3.adb
gcc/ada/sem_ch6.adb
gcc/ada/sem_ch8.adb
gcc/ada/sem_eval.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads
gcc/ada/sysdep.c

index 04e5b8ad45a9b919c7cf124ea4909d5fe4d786b2..9af0589b60c9ff4e5fc61ca296f9ea6756c21ed3 100644 (file)
@@ -1,3 +1,65 @@
+2017-01-12  Tristan Gingold  <gingold@adacore.com>
+
+       * s-mmap.ads, s-mmap.adb, s-mmosin-unix.ads, s-mmosin-unix.adb,
+       s-mmauni-long.ads, s-mmosin-mingw.ads, s-mmosin-mingw.adb: New files.
+
+2017-01-12  Yannick Moy  <moy@adacore.com>
+
+       * errout.adb, errout.ads (Initialize): Factor common treatment
+       in Reset_Warnings.
+       (Reset_Warnings): New procedure to reset counts related to warnings.
+       (Record_Compilation_Errors): New variable to store the presence of an
+       error, used in gnat2why to allow changing the Warning_Mode.
+       (Compilation_Errors): Use new variable Record_Compilation_Errors to
+       store the presence of an error.
+
+2017-01-12  Javier Miranda  <miranda@adacore.com>
+
+       * sem_ch13.adb (Analyze_Aspect_Specifications):
+       For Interrupt_Handler and Attach_ Handler aspects, decorate the
+       internally built reference to the protected procedure as coming
+       from sources and force its analysis.
+
+2017-01-12  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch3.adb (Build_Derived_Type): For a scalar derived type,
+       inherit predicates if any from the first_subtype of the parent,
+       not from the anonymous parent type.
+       * sem_eval.adb (Is_Static_Subtype): A type that inherits a dynamic
+       predicate is not a static subtype.
+
+2017-01-12  Gary Dismukes  <dismukes@adacore.com>
+
+       * freeze.adb (Check_Suspicious_Convention): New procedure
+       performing a warning check on discriminated record types with
+       convention C or C++. Factored out of procedure Freeze_Record_Type,
+       and changed to only apply to base types (to avoid spurious
+       warnings on subtypes). Minor improvement of warning messages
+       to refer to discriminated rather than variant record types.
+       (Freeze_Record_Type): Remove code for performing a suspicious
+       convention check.
+       (Freeze_Entity): Only call Freeze_Record_Type
+       on types that aren't declared within any enclosing generic units
+       (rather than just excluding the type when the innermost scope
+       is generic). Call Check_Suspicious_Convention whether or not
+       the type is declared within a generic unit.
+       * sem_ch8.adb (In_Generic_Scope): Move this function to Sem_Util.
+       * sem_util.ads, sem_util.adb (In_Generic_Scope): New function (moved
+       from Sem_Ch8).
+
+2017-01-12  Tristan Gingold  <gingold@adacore.com>
+
+       * sysdep.c, adaint.c, rtinit.c, ming32.h:
+       (__gnat_current_codepage): Renamed from CurrentCodePage
+       (__gnat_current_ccs_encoding): Renamed from CurrentCCSEncoding
+
+2017-01-12  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch6.adb (Fully_Conformant_Expressions): Handle properly
+       quantified expressions, following AI12-050: the loop parameters
+       of two quantified expressions are conformant if they have the
+       same identifier.
+
 2017-01-12  Arnaud Charlet  <charlet@adacore.com>
 
        * gcc-interface/Makefile.in: Clean up VxWorks targets.
index 819ea47e449725b08c1a531b340ddc6a74b0e5db..54a1d6e25c3196bd5ac91d190d5ba964545fd913 100644 (file)
@@ -128,8 +128,8 @@ extern "C" {
 #include "mingw32.h"
 
 /* Current code page and CCS encoding to use, set in initialize.c.  */
-UINT CurrentCodePage;
-UINT CurrentCCSEncoding;
+UINT __gnat_current_codepage;
+UINT __gnat_current_ccs_encoding;
 
 #include <sys/utime.h>
 
index 49aa2a7765f2fdce47ab1aa22ebab97e42a79e8a..001072d5b8f97ae00c181aa4d041e3683d114a09 100644 (file)
@@ -60,6 +60,13 @@ package body Errout is
    Finalize_Called : Boolean := False;
    --  Set True if the Finalize routine has been called
 
+   Record_Compilation_Errors : Boolean := False;
+   --  Record that a compilation error was witnessed during a given phase of
+   --  analysis for gnat2why. This is needed as Warning_Mode is modified twice
+   --  in gnat2why, hence Erroutc.Compilation_Errors can only return a suitable
+   --  value for each phase of analysis separately. This is updated at each
+   --  call to Compilation_Errors.
+
    Warn_On_Instance : Boolean;
    --  Flag set true for warning message to be posted on instance
 
@@ -236,8 +243,17 @@ package body Errout is
    begin
       if not Finalize_Called then
          raise Program_Error;
+
+      --  Record that a compilation error was witnessed during a given phase of
+      --  analysis for gnat2why. This is needed as Warning_Mode is modified
+      --  twice in gnat2why, hence Erroutc.Compilation_Errors can only return a
+      --  suitable value for each phase of analysis separately.
+
       else
-         return Erroutc.Compilation_Errors;
+         Record_Compilation_Errors := Record_Compilation_Errors or else
+           Erroutc.Compilation_Errors;
+
+         return Record_Compilation_Errors;
       end if;
    end Compilation_Errors;
 
@@ -1615,13 +1631,13 @@ package body Errout is
       Last_Error_Msg := No_Error_Msg;
       Serious_Errors_Detected := 0;
       Total_Errors_Detected := 0;
-      Warnings_Treated_As_Errors := 0;
-      Warnings_Detected := 0;
-      Info_Messages := 0;
-      Warnings_As_Errors_Count := 0;
       Cur_Msg := No_Error_Msg;
       List_Pragmas.Init;
 
+      --  Reset counts for warnings
+
+      Reset_Warnings;
+
       --  Initialize warnings tables
 
       Warnings.Init;
@@ -2357,6 +2373,18 @@ package body Errout is
       end if;
    end Remove_Warning_Messages;
 
+   --------------------
+   -- Reset_Warnings --
+   --------------------
+
+   procedure Reset_Warnings is
+   begin
+      Warnings_Treated_As_Errors := 0;
+      Warnings_Detected := 0;
+      Info_Messages := 0;
+      Warnings_As_Errors_Count := 0;
+   end Reset_Warnings;
+
    ----------------------
    -- Adjust_Name_Case --
    ----------------------
index e2e7de4a67ed37368436f83e1a001256036ea8c5..a8e4d6c15afdb43dd20ded65e8cad184aafdef0a 100644 (file)
@@ -803,6 +803,11 @@ package Errout is
    --  Remove warnings on all elements of a list (Calls Remove_Warning_Messages
    --  on each element of the list, see above).
 
+   procedure Reset_Warnings;
+   --  Reset the counts related to warnings. This is used both to initialize
+   --  these counts and to reset them after each phase of analysis for a given
+   --  value of Opt.Warning_Mode in gnat2why.
+
    procedure Set_Ignore_Errors (To : Boolean);
    --  Following a call to this procedure with To=True, all error calls are
    --  ignored. A call with To=False restores the default treatment in which
@@ -852,9 +857,9 @@ package Errout is
    function Compilation_Errors return Boolean;
    --  Returns True if errors have been detected, or warnings in -gnatwe (treat
    --  warnings as errors) mode. Note that it is mandatory to call Finalize
-   --  before calling this routine. Always returns False in formal verification
-   --  mode, because errors issued when analyzing code are not compilation
-   --  errors, and should not result in exiting with an error status.
+   --  before calling this routine. To account for changes to Warning_Mode in
+   --  gnat2why between phases, the past or current presence of an error is
+   --  recorded in a global variable at each call.
 
    procedure Error_Msg_CRT (Feature : String; N : Node_Id);
    --  Posts a non-fatal message on node N saying that the feature identified
index 6c90bd39537a09bdc706d2c2b4ff26823b74c957..0cc588102e2b80da585699be9911a24e10d5ae9d 100644 (file)
@@ -2035,6 +2035,13 @@ package body Freeze is
       --  which is the current instance type can only be applied when the type
       --  is limited.
 
+      procedure Check_Suspicious_Convention (Rec_Type : Entity_Id);
+      --  Give a warning for pragma Convention with language C or C++ applied
+      --  to a discriminated record type. This is suppressed for the unchecked
+      --  union case, since the whole point in this case is interface C. We
+      --  also do not generate this within instantiations, since we will have
+      --  generated a message on the template.
+
       procedure Check_Suspicious_Modulus (Utype : Entity_Id);
       --  Give warning for modulus of 8, 16, 32, or 64 given as an explicit
       --  integer literal without an explicit corresponding size clause. The
@@ -2249,6 +2256,51 @@ package body Freeze is
          end if;
       end Check_Current_Instance;
 
+      ---------------------------------
+      -- Check_Suspicious_Convention --
+      ---------------------------------
+
+      procedure Check_Suspicious_Convention (Rec_Type : Entity_Id) is
+      begin
+         if Has_Discriminants (Rec_Type)
+           and then Is_Base_Type (Rec_Type)
+           and then not Is_Unchecked_Union (Rec_Type)
+           and then (Convention (Rec_Type) = Convention_C
+                       or else
+                     Convention (Rec_Type) = Convention_CPP)
+           and then Comes_From_Source (Rec_Type)
+           and then not In_Instance
+           and then not Has_Warnings_Off (Rec_Type)
+         then
+            declare
+               Cprag : constant Node_Id :=
+                         Get_Rep_Pragma (Rec_Type, Name_Convention);
+               A2    : Node_Id;
+
+            begin
+               if Present (Cprag) then
+                  A2 := Next (First (Pragma_Argument_Associations (Cprag)));
+
+                  if Convention (Rec_Type) = Convention_C then
+                     Error_Msg_N
+                       ("?x?discriminated record has no direct " &
+                        "equivalent in C",
+                        A2);
+                  else
+                     Error_Msg_N
+                       ("?x?discriminated record has no direct " &
+                        "equivalent in C++",
+                        A2);
+                  end if;
+
+                  Error_Msg_NE
+                    ("\?x?use of convention for type& is dubious",
+                     A2, Rec_Type);
+               end if;
+            end;
+         end if;
+      end Check_Suspicious_Convention;
+
       ------------------------------
       -- Check_Suspicious_Modulus --
       ------------------------------
@@ -4348,46 +4400,6 @@ package body Freeze is
             end loop;
          end if;
 
-         --  Generate warning for applying C or C++ convention to a record
-         --  with discriminants. This is suppressed for the unchecked union
-         --  case, since the whole point in this case is interface C. We also
-         --  do not generate this within instantiations, since we will have
-         --  generated a message on the template.
-
-         if Has_Discriminants (E)
-           and then not Is_Unchecked_Union (E)
-           and then (Convention (E) = Convention_C
-                       or else
-                     Convention (E) = Convention_CPP)
-           and then Comes_From_Source (E)
-           and then not In_Instance
-           and then not Has_Warnings_Off (E)
-           and then not Has_Warnings_Off (Base_Type (E))
-         then
-            declare
-               Cprag : constant Node_Id := Get_Rep_Pragma (E, Name_Convention);
-               A2    : Node_Id;
-
-            begin
-               if Present (Cprag) then
-                  A2 := Next (First (Pragma_Argument_Associations (Cprag)));
-
-                  if Convention (E) = Convention_C then
-                     Error_Msg_N
-                       ("?x?variant record has no direct equivalent in C",
-                        A2);
-                  else
-                     Error_Msg_N
-                       ("?x?variant record has no direct equivalent in C++",
-                        A2);
-                  end if;
-
-                  Error_Msg_NE
-                    ("\?x?use of convention for type& is dubious", A2, E);
-               end if;
-            end;
-         end if;
-
          --  See if Size is too small as is (and implicit packing might help)
 
          if not Is_Packed (Rec)
@@ -5643,11 +5655,17 @@ package body Freeze is
          --  for the case of a private type with record extension (we will do
          --  that later when the full type is frozen).
 
-         elsif Ekind_In (E, E_Record_Type, E_Record_Subtype)
-           and then not (Present (Scope (E))
-                          and then Is_Generic_Unit (Scope (E)))
-         then
-            Freeze_Record_Type (E);
+         elsif Ekind_In (E, E_Record_Type, E_Record_Subtype) then
+            if not In_Generic_Scope (E) then
+               Freeze_Record_Type (E);
+            end if;
+
+            --  Report a warning if a discriminated record base type has a
+            --  convention with language C or C++ applied to it. This check is
+            --  done even within generic scopes (but not in instantiations),
+            --  which is why we don't do it as part of Freeze_Record_Type.
+
+            Check_Suspicious_Convention (E);
 
          --  For a concurrent type, freeze corresponding record type. This does
          --  not correspond to any specific rule in the RM, but the record type
index 77caec2642525ed5273a3d9a1e1146dda58f2754..cf2d9de1715cf1f8ad73eb1a0cadf64810189fc0 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                              C Header File                               *
  *                                                                          *
- *          Copyright (C) 2002-2014, Free Software Foundation, Inc.         *
+ *          Copyright (C) 2002-2016, Free Software Foundation, Inc.         *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
 
 #ifdef GNAT_UNICODE_SUPPORT
 
-extern UINT CurrentCodePage;
-extern UINT CurrentCCSEncoding;
+extern UINT __gnat_current_codepage;
+extern UINT __gnat_current_ccs_encoding;
 
-/*  Macros to convert to/from the code page specified in CurrentCodePage.  */
+/*  Macros to convert to/from the code page specified in
+    __gnat_current_codepage.  */
 #define S2WSC(wstr,str,len) \
-   MultiByteToWideChar (CurrentCodePage,0,str,-1,wstr,len)
+   MultiByteToWideChar (__gnat_current_codepage,0,str,-1,wstr,len)
 #define WS2SC(str,wstr,len) \
-   WideCharToMultiByte (CurrentCodePage,0,wstr,-1,str,len,NULL,NULL)
+   WideCharToMultiByte (__gnat_current_codepage,0,wstr,-1,str,len,NULL,NULL)
 
 /*  Macros to convert to/from UTF-8 code page.  */
 #define S2WSU(wstr,str,len) \
index dcd0903db5df91fea3ac74386cad8c91a6388403..42defa8ca134e84f6eeeead7f0a9d41abbb91db2 100644 (file)
@@ -169,14 +169,14 @@ __gnat_runtime_initialize(int install_handler)
      char *codepage = getenv ("GNAT_CODE_PAGE");
 
      /* Default code page is UTF-8.  */
-     CurrentCodePage = CP_UTF8;
+     __gnat_current_codepage = CP_UTF8;
 
      if (codepage != NULL)
        {
         if (strcmp (codepage, "CP_ACP") == 0)
-          CurrentCodePage = CP_ACP;
+          __gnat_current_codepage = CP_ACP;
         else if (strcmp (codepage, "CP_UTF8") == 0)
-          CurrentCodePage = CP_UTF8;
+          __gnat_current_codepage = CP_UTF8;
        }
    }
 
@@ -185,29 +185,29 @@ __gnat_runtime_initialize(int install_handler)
      char *ccsencoding = getenv ("GNAT_CCS_ENCODING");
 
      /* Default CCS Encoding.  */
-     CurrentCCSEncoding = _O_TEXT;
+     __gnat_current_ccs_encoding = _O_TEXT;
      __gnat_wide_text_translation_required = 0;
 
      if (ccsencoding != NULL)
        {
         if (strcmp (ccsencoding, "U16TEXT") == 0)
            {
-             CurrentCCSEncoding = _O_U16TEXT;
+             __gnat_current_ccs_encoding = _O_U16TEXT;
              __gnat_wide_text_translation_required = 1;
            }
         else if (strcmp (ccsencoding, "TEXT") == 0)
            {
-             CurrentCCSEncoding = _O_TEXT;
+             __gnat_current_ccs_encoding = _O_TEXT;
              __gnat_wide_text_translation_required = 0;
            }
         else if (strcmp (ccsencoding, "WTEXT") == 0)
            {
-             CurrentCCSEncoding = _O_WTEXT;
+             __gnat_current_ccs_encoding = _O_WTEXT;
              __gnat_wide_text_translation_required = 1;
            }
         else if (strcmp (ccsencoding, "U8TEXT") == 0)
            {
-             CurrentCCSEncoding = _O_U8TEXT;
+             __gnat_current_ccs_encoding = _O_U8TEXT;
              __gnat_wide_text_translation_required = 1;
            }
        }
diff --git a/gcc/ada/s-mmap.adb b/gcc/ada/s-mmap.adb
new file mode 100644 (file)
index 0000000..e9b2aff
--- /dev/null
@@ -0,0 +1,548 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--                          S Y S T E M . M M A P                           --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.IO_Exceptions;
+with Ada.Unchecked_Conversion;
+with Ada.Unchecked_Deallocation;
+
+with System.Strings; use System.Strings;
+
+with System.Mmap.OS_Interface; use System.Mmap.OS_Interface;
+
+package body System.Mmap is
+
+   type Mapped_File_Record is record
+      Current_Region     : Mapped_Region;
+      --  The legacy API enables only one region to be mapped, directly
+      --  associated with the mapped file. This references this region.
+
+      File               : System_File;
+      --  Underlying OS-level file
+   end record;
+
+   type Mapped_Region_Record is record
+      File          : Mapped_File;
+      --  The file this region comes from. Be careful: for reading file, it is
+      --  valid to have it closed before one of its regions is free'd.
+
+      Write         : Boolean;
+      --  Whether the file this region comes from is open for writing.
+
+      Data          : Str_Access;
+      --  Unbounded access to the mapped content.
+
+      System_Offset : File_Size;
+      --  Position in the file of the first byte actually mapped in memory
+
+      User_Offset   : File_Size;
+      --  Position in the file of the first byte requested by the user
+
+      System_Size   : File_Size;
+      --  Size of the region actually mapped in memory
+
+      User_Size     : File_Size;
+      --  Size of the region requested by the user
+
+      Mapped        : Boolean;
+      --  Whether this region is actually memory mapped
+
+      Mutable       : Boolean;
+      --  If the file is opened for reading, wheter this region is writable
+
+      Buffer        : System.Strings.String_Access;
+      --  When this region is not actually memory mapped, contains the
+      --  requested bytes.
+
+      Mapping       : System_Mapping;
+      --  Underlying OS-level data for the mapping, if any
+   end record;
+
+   Invalid_Mapped_Region_Record : constant Mapped_Region_Record :=
+     (null, False, null, 0, 0, 0, 0, False, False, null,
+      Invalid_System_Mapping);
+   Invalid_Mapped_File_Record : constant Mapped_File_Record :=
+     (Invalid_Mapped_Region, Invalid_System_File);
+
+   Empty_String : constant String := "";
+   --  Used to provide a valid empty Data for empty files, for instanc.
+
+   procedure Dispose is new Ada.Unchecked_Deallocation
+     (Mapped_File_Record, Mapped_File);
+   procedure Dispose is new Ada.Unchecked_Deallocation
+     (Mapped_Region_Record, Mapped_Region);
+
+   function Convert is new Ada.Unchecked_Conversion
+     (Standard.System.Address, Str_Access);
+
+   procedure Compute_Data (Region : Mapped_Region);
+   --  Fill the Data field according to system and user offsets. The region
+   --  must actually be mapped or bufferized.
+
+   procedure From_Disk (Region : Mapped_Region);
+   --  Read a region of some file from the disk
+
+   procedure To_Disk (Region : Mapped_Region);
+   --  Write the region of the file back to disk if necessary, and free memory
+
+   ---------------
+   -- Open_Read --
+   ---------------
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return Mapped_File
+   is
+      File : constant System_File :=
+         Open_Read (Filename, Use_Mmap_If_Available);
+   begin
+      return new Mapped_File_Record'
+        (Current_Region => Invalid_Mapped_Region,
+         File           => File);
+   end Open_Read;
+
+   ----------------
+   -- Open_Write --
+   ----------------
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return Mapped_File
+   is
+      File : constant System_File :=
+         Open_Write (Filename, Use_Mmap_If_Available);
+   begin
+      return new Mapped_File_Record'
+        (Current_Region => Invalid_Mapped_Region,
+         File           => File);
+   end Open_Write;
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close (File : in out Mapped_File) is
+   begin
+      --  Closing a closed file is allowed and should do nothing
+
+      if File = Invalid_Mapped_File then
+         return;
+      end if;
+
+      if File.Current_Region /= null then
+         Free (File.Current_Region);
+      end if;
+
+      if File.File /= Invalid_System_File then
+         Close (File.File);
+      end if;
+
+      Dispose (File);
+   end Close;
+
+   ----------
+   -- Free --
+   ----------
+
+   procedure Free (Region : in out Mapped_Region) is
+      Ignored : Integer;
+      pragma Unreferenced (Ignored);
+   begin
+      --  Freeing an already free'd file is allowed and should do nothing
+
+      if Region = Invalid_Mapped_Region then
+         return;
+      end if;
+
+      if Region.Mapping /= Invalid_System_Mapping then
+         Dispose_Mapping (Region.Mapping);
+      end if;
+      To_Disk (Region);
+      Dispose (Region);
+   end Free;
+
+   ----------
+   -- Read --
+   ----------
+
+   procedure Read
+     (File    : Mapped_File;
+      Region  : in out Mapped_Region;
+      Offset  : File_Size := 0;
+      Length  : File_Size := 0;
+      Mutable : Boolean := False)
+   is
+      File_Length      : constant File_Size := Mmap.Length (File);
+
+      Req_Offset       : constant File_Size := Offset;
+      Req_Length       : File_Size := Length;
+      --  Offset and Length of the region to map, used to adjust mapping
+      --  bounds, reflecting what the user will see.
+
+      Region_Allocated : Boolean := False;
+   begin
+      --  If this region comes from another file, or simply if the file is
+      --  writeable, we cannot re-use this mapping: free it first.
+
+      if Region /= Invalid_Mapped_Region
+        and then
+          (Region.File /= File or else File.File.Write)
+      then
+         Free (Region);
+      end if;
+
+      if Region = Invalid_Mapped_Region then
+         Region := new Mapped_Region_Record'(Invalid_Mapped_Region_Record);
+         Region_Allocated := True;
+      end if;
+
+      Region.File := File;
+
+      if Req_Offset >= File_Length then
+         --  If the requested offset goes beyond file size, map nothing
+
+         Req_Length := 0;
+
+      elsif Length = 0
+        or else
+          Length > File_Length - Req_Offset
+      then
+         --  If Length is 0 or goes beyond file size, map till end of file
+
+         Req_Length := File_Length - Req_Offset;
+
+      else
+         Req_Length := Length;
+      end if;
+
+      --  Past this point, the offset/length the user will see is fixed. On the
+      --  other hand, the system offset/length is either already defined, from
+      --  a previous mapping, or it is set to 0. In the latter case, the next
+      --  step will set them according to the mapping.
+
+      Region.User_Offset := Req_Offset;
+      Region.User_Size := Req_Length;
+
+      --  If the requested region is inside an already mapped region, adjust
+      --  user-requested data and do nothing else.
+
+      if (File.File.Write or else Region.Mutable = Mutable)
+        and then
+        Req_Offset >= Region.System_Offset
+        and then
+            (Req_Offset + Req_Length
+             <= Region.System_Offset + Region.System_Size)
+      then
+         Region.User_Offset := Req_Offset;
+         Compute_Data (Region);
+         return;
+
+      elsif Region.Buffer /= null then
+         --  Otherwise, as we are not going to re-use the buffer, free it
+
+         System.Strings.Free (Region.Buffer);
+         Region.Buffer := null;
+
+      elsif Region.Mapping /= Invalid_System_Mapping then
+         --  Otherwise, there is a memory mapping that we need to unmap.
+         Dispose_Mapping (Region.Mapping);
+      end if;
+
+      --  mmap() will sometimes return NULL when the file exists but is empty,
+      --  which is not what we want, so in the case of a zero length file we
+      --  fall back to read(2)/write(2)-based mode.
+
+      if File_Length > 0 and then File.File.Mapped then
+
+         Region.System_Offset := Req_Offset;
+         Region.System_Size := Req_Length;
+         Create_Mapping
+           (File.File,
+            Region.System_Offset, Region.System_Size,
+            Mutable,
+            Region.Mapping);
+         Region.Mapped := True;
+         Region.Mutable := Mutable;
+
+      else
+         --  There is no alignment requirement when manually reading the file.
+
+         Region.System_Offset := Req_Offset;
+         Region.System_Size := Req_Length;
+         Region.Mapped := False;
+         Region.Mutable := True;
+         From_Disk (Region);
+      end if;
+
+      Region.Write := File.File.Write;
+      Compute_Data (Region);
+
+   exception
+      when others =>
+         --  Before propagating any exception, free any region we allocated
+         --  here.
+
+         if Region_Allocated then
+            Dispose (Region);
+         end if;
+         raise;
+   end Read;
+
+   ----------
+   -- Read --
+   ----------
+
+   procedure Read
+     (File    : Mapped_File;
+      Offset  : File_Size := 0;
+      Length  : File_Size := 0;
+      Mutable : Boolean := False)
+   is
+   begin
+      Read (File, File.Current_Region, Offset, Length, Mutable);
+   end Read;
+
+   ----------
+   -- Read --
+   ----------
+
+   function Read
+     (File    : Mapped_File;
+      Offset  : File_Size := 0;
+      Length  : File_Size := 0;
+      Mutable : Boolean := False) return Mapped_Region
+   is
+      Region  : Mapped_Region := Invalid_Mapped_Region;
+   begin
+      Read (File, Region, Offset, Length, Mutable);
+      return Region;
+   end Read;
+
+   ------------
+   -- Length --
+   ------------
+
+   function Length (File : Mapped_File) return File_Size is
+   begin
+      return File.File.Length;
+   end Length;
+
+   ------------
+   -- Offset --
+   ------------
+
+   function Offset (Region : Mapped_Region) return File_Size is
+   begin
+      return Region.User_Offset;
+   end Offset;
+
+   ------------
+   -- Offset --
+   ------------
+
+   function Offset (File : Mapped_File) return File_Size is
+   begin
+      return Offset (File.Current_Region);
+   end Offset;
+
+   ----------
+   -- Last --
+   ----------
+
+   function Last (Region : Mapped_Region) return Integer is
+   begin
+      return Integer (Region.User_Size);
+   end Last;
+
+   ----------
+   -- Last --
+   ----------
+
+   function Last (File : Mapped_File) return Integer is
+   begin
+      return Last (File.Current_Region);
+   end Last;
+
+   -------------------
+   -- To_Str_Access --
+   -------------------
+
+   function To_Str_Access
+     (Str : System.Strings.String_Access) return Str_Access is
+   begin
+      if Str = null then
+         return null;
+      else
+         return Convert (Str.all'Address);
+      end if;
+   end To_Str_Access;
+
+   ----------
+   -- Data --
+   ----------
+
+   function Data (Region : Mapped_Region) return Str_Access is
+   begin
+      return Region.Data;
+   end Data;
+
+   ----------
+   -- Data --
+   ----------
+
+   function Data (File : Mapped_File) return Str_Access is
+   begin
+      return Data (File.Current_Region);
+   end Data;
+
+   ----------------
+   -- Is_Mutable --
+   ----------------
+
+   function Is_Mutable (Region : Mapped_Region) return Boolean is
+   begin
+      return Region.Mutable or Region.Write;
+   end Is_Mutable;
+
+   ----------------
+   -- Is_Mmapped --
+   ----------------
+
+   function Is_Mmapped (File : Mapped_File) return Boolean is
+   begin
+      return File.File.Mapped;
+   end Is_Mmapped;
+
+   -------------------
+   -- Get_Page_Size --
+   -------------------
+
+   function Get_Page_Size return Integer is
+      Result : constant File_Size := Get_Page_Size;
+   begin
+      return Integer (Result);
+   end Get_Page_Size;
+
+   ---------------------
+   -- Read_Whole_File --
+   ---------------------
+
+   function Read_Whole_File
+     (Filename           : String;
+      Empty_If_Not_Found : Boolean := False)
+     return System.Strings.String_Access
+   is
+      File   : Mapped_File := Open_Read (Filename);
+      Region : Mapped_Region renames File.Current_Region;
+      Result : String_Access;
+   begin
+      Read (File);
+
+      if Region.Data /= null then
+         Result := new String'(String
+                               (Region.Data (1 .. Last (Region))));
+
+      elsif Region.Buffer /= null then
+         Result := Region.Buffer;
+         Region.Buffer := null;  --  So that it is not deallocated
+      end if;
+
+      Close (File);
+
+      return Result;
+
+   exception
+      when Ada.IO_Exceptions.Name_Error =>
+         if Empty_If_Not_Found then
+            return new String'("");
+         else
+            return null;
+         end if;
+
+      when others =>
+         Close (File);
+         return null;
+   end Read_Whole_File;
+
+   ---------------
+   -- From_Disk --
+   ---------------
+
+   procedure From_Disk (Region : Mapped_Region) is
+   begin
+      pragma Assert (Region.File.all /= Invalid_Mapped_File_Record);
+      pragma Assert (Region.Buffer = null);
+
+      Region.Buffer := Read_From_Disk
+        (Region.File.File, Region.User_Offset, Region.User_Size);
+      Region.Mapped := False;
+   end From_Disk;
+
+   -------------
+   -- To_Disk --
+   -------------
+
+   procedure To_Disk (Region : Mapped_Region) is
+   begin
+      if Region.Write and then Region.Buffer /= null then
+         pragma Assert (Region.File.all /= Invalid_Mapped_File_Record);
+         Write_To_Disk
+           (Region.File.File,
+            Region.User_Offset, Region.User_Size,
+            Region.Buffer);
+      end if;
+
+      System.Strings.Free (Region.Buffer);
+      Region.Buffer := null;
+   end To_Disk;
+
+   ------------------
+   -- Compute_Data --
+   ------------------
+
+   procedure Compute_Data (Region : Mapped_Region) is
+      Base_Data : Str_Access;
+      --  Address of the first byte actually mapped in memory
+
+      Data_Shift : constant Integer :=
+        Integer (Region.User_Offset - Region.System_Offset);
+   begin
+      if Region.User_Size = 0 then
+         Region.Data := Convert (Empty_String'Address);
+         return;
+      elsif Region.Mapped then
+         Base_Data := Convert (Region.Mapping.Address);
+      else
+         Base_Data := Convert (Region.Buffer.all'Address);
+      end if;
+      Region.Data := Convert (Base_Data (Data_Shift + 1)'Address);
+   end Compute_Data;
+
+end System.Mmap;
diff --git a/gcc/ada/s-mmap.ads b/gcc/ada/s-mmap.ads
new file mode 100644 (file)
index 0000000..8eed366
--- /dev/null
@@ -0,0 +1,276 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--                          S Y S T E M . M M A P                           --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package provides memory mapping of files. Depending on your operating
+--  system, this might provide a more efficient method for accessing the
+--  contents of files.
+--  A description of memory-mapping is available on the sqlite page, at:
+--      http://www.sqlite.org/mmap.html
+--
+--  The traditional method for reading a file is to allocate a buffer in the
+--  application address space, then open the file and copy its contents. When
+--  memory mapping is available though, the application asks the operating
+--  system to return a pointer to the requested page, if possible. If the
+--  requested page has been or can be mapped into the application address
+--  space, the system returns a pointer to that page for the application to
+--  use without having to copy anything. Skipping the copy step is what makes
+--  memory mapped I/O faster.
+--
+--  When memory mapping is not available, this package automatically falls
+--  back to the traditional copy method.
+--
+--  Example of use for this package, when reading a file that can be fully
+--  mapped
+--
+--  declare
+--     File : Mapped_File;
+--     Str  : Str_Access;
+--  begin
+--     File := Open_Read ("/tmp/file_on_disk");
+--     Read (File);  --  read the whole file
+--     Str := Data (File);
+--     for S in 1 .. Last (File) loop
+--         Put (Str (S));
+--     end loop;
+--     Close (File);
+--  end;
+--
+--  When the file is big, or you only want to access part of it at a given
+--  time, you can use the following type of code.
+
+--  declare
+--     File   : Mapped_File;
+--     Str    : Str_Access;
+--     Offs   : File_Size := 0;
+--     Page   : constant Integer := Get_Page_Size;
+--  begin
+--     File := Open_Read ("/tmp/file_on_disk");
+--     while Offs < Length (File) loop
+--         Read (File, Offs, Length => Long_Integer (Page) * 4);
+--         Str := Data (File);
+--
+--         --  Print characters for this chunk:
+--         for S in Integer (Offs - Offset (File)) + 1 .. Last (File) loop
+--            Put (Str (S));
+--         end loop;
+--
+--         --  Since we are reading multiples of Get_Page_Size, we can simplify
+--         --  with
+--         --    for S in 1 .. Last (File) loop ...
+--
+--         Offs := Offs + Long_Integer (Last (File));
+--     end loop;
+
+with Interfaces.C;
+
+with System.Strings;
+
+package System.Mmap is
+
+   type Mapped_File is private;
+   --  File to be mapped in memory.
+
+   --  This package will use the fastest possible algorithm to load the
+   --  file in memory. On systems that support it, the file is not really
+   --  loaded in memory. Instead, a call to the mmap() system call (or
+   --  CreateFileMapping()) will keep the file on disk, but make it
+   --  accessible as if it was in memory.
+
+   --  When the system does not support it, the file is actually loaded in
+   --  memory through calls to read(), and written back with write() when you
+   --  close it. This is of course much slower.
+
+   --  Legacy: each mapped file has a "default" mapped region in it.
+
+   type Mapped_Region is private;
+   --  A representation of part of a file in memory. Actual reading/writing
+   --  is done through a mapped region. After being returned by Read, a mapped
+   --  region must be free'd when done. If the original Mapped_File was open
+   --  for reading, it can be closed before the mapped region is free'd.
+
+   Invalid_Mapped_File : constant Mapped_File;
+   Invalid_Mapped_Region : constant Mapped_Region;
+
+   type Unconstrained_String is new String (Positive);
+   type Str_Access is access all Unconstrained_String;
+   pragma No_Strict_Aliasing (Str_Access);
+
+   type File_Size is new Interfaces.C.size_t;
+
+   function To_Str_Access
+     (Str : System.Strings.String_Access) return Str_Access;
+   --  Convert Str. The returned value points to the same memory block, but no
+   --  longer includes the bounds, which you need to manage yourself
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return Mapped_File;
+   --  Open a file for reading. The same file can be shared by multiple
+   --  processes, that will see each others's changes as they occur.
+   --  Any attempt to write the data might result in a segmentation fault,
+   --  depending on how the file is open.
+   --  Name_Error is raised if the file does not exist.
+   --  Filename should be compatible with the filesystem.
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return Mapped_File;
+   --  Open a file for writing.
+   --  You cannot change the length of the file.
+   --  Name_Error is raised if the file does not exist
+   --  Filename should be compatible with the filesystem.
+
+   procedure Close (File : in out Mapped_File);
+   --  Close the file, and unmap the memory that is used for the region
+   --  contained in File. If the system does not support the unmmap() system
+   --  call or equivalent, or these were not available for the file itself,
+   --  then the file is written back to the disk if it was opened for writing.
+
+   procedure Free (Region : in out Mapped_Region);
+   --  Unmap the memory that is used for this region and deallocate the region
+
+   procedure Read
+     (File   : Mapped_File;
+      Region : in out Mapped_Region;
+      Offset : File_Size := 0;
+      Length : File_Size := 0;
+      Mutable : Boolean := False);
+   --  Read a specific part of File and set Region to the corresponding mapped
+   --  region, or re-use it if possible.
+   --  Offset is the number of bytes since the beginning of the file at which
+   --  we should start reading. Length is the number of bytes that should be
+   --  read. If set to 0, as much of the file as possible is read (presumably
+   --  the whole file unless you are reading a _huge_ file).
+   --  Note that no (un)mapping is is done if that part of the file is already
+   --  available through Region.
+   --  If the file was opened for writing, any modification you do to the
+   --  data stored in File will be stored on disk (either immediately when the
+   --  file is opened through a mmap() system call, or when the file is closed
+   --  otherwise).
+   --  Mutable is processed only for reading files. If set to True, the
+   --  data can be modified, even through it will not be carried through the
+   --  underlying file, nor it is guaranteed to be carried through remapping.
+   --  This function takes care of page size alignment issues. The accessors
+   --  below only expose the region that has been requested by this call, even
+   --  if more bytes were actually mapped by this function.
+   --  TODO??? Enable to have a private copy for readable files
+
+   function Read
+     (File    : Mapped_File;
+      Offset  : File_Size := 0;
+      Length  : File_Size := 0;
+      Mutable : Boolean := False) return Mapped_Region;
+   --  Likewise, return a new mapped region
+
+   procedure Read
+     (File    : Mapped_File;
+      Offset  : File_Size := 0;
+      Length  : File_Size := 0;
+      Mutable : Boolean := False);
+   --  Likewise, use the legacy "default" region in File
+
+   function Length (File : Mapped_File) return File_Size;
+   --  Size of the file on the disk
+
+   function Offset (Region : Mapped_Region) return File_Size;
+   --  Return the offset, in the physical file on disk, corresponding to the
+   --  requested mapped region. The first byte in the file has offest 0.
+
+   function Offset (File : Mapped_File) return File_Size;
+   --  Likewise for the region contained in File
+
+   function Last (Region : Mapped_Region) return Integer;
+   --  Return the number of requested bytes mapped in this region. It is
+   --  erroneous to access Data for indices outside 1 .. Last (Region).
+   --  Such accesses may cause Storage_Error to be raised.
+
+   function Last (File : Mapped_File) return Integer;
+   --  Return the number of requested bytes mapped in the region contained in
+   --  File. It is erroneous to access Data for indices outside of 1 .. Last
+   --  (File); such accesses may cause Storage_Error to be raised.
+
+   function Data (Region : Mapped_Region) return Str_Access;
+   --  The data mapped in Region as requested. The result is an unconstrained
+   --  string, so you cannot use the usual 'First and 'Last attributes.
+   --  Instead, these are respectively 1 and Size.
+
+   function Data (File : Mapped_File) return Str_Access;
+   --  Likewise for the region contained in File
+
+   function Is_Mutable (Region : Mapped_Region) return Boolean;
+   --  Return whether it is safe to change bytes in Data (Region). This is true
+   --  for regions from writeable files, for regions mapped with the "Mutable"
+   --  flag set, and for regions that are copied in a buffer. Note that it is
+   --  not specified whether empty regions are mutable or not, since there is
+   --  no byte no modify.
+
+   function Is_Mmapped (File : Mapped_File) return Boolean;
+   --  Whether regions for this file are opened through an mmap() system call
+   --  or equivalent. This is in general irrelevant to your application, unless
+   --  the file can be accessed by multiple concurrent processes or tasks. In
+   --  such a case, and if the file is indeed mmap-ed, then the various parts
+   --  of the file can be written simulatenously, and thus you cannot ensure
+   --  the integrity of the file. If the file is not mmapped, the latest
+   --  process to Close it overwrite what other processes have done.
+
+   function Get_Page_Size return Integer;
+   --  Returns the number of bytes in a page. Once a file is mapped from the
+   --  disk, its offset and Length should be multiples of this page size (which
+   --  is ensured by this package in any case). Knowing this page size allows
+   --  you to map as much memory as possible at once, thus potentially reducing
+   --  the number of system calls to read the file by chunks.
+
+   function Read_Whole_File
+     (Filename           : String;
+      Empty_If_Not_Found : Boolean := False)
+     return System.Strings.String_Access;
+   --  Returns the whole contents of the file.
+   --  The returned string must be freed by the user.
+   --  This is a convenience function, which is of course slower than the ones
+   --  above since we also need to allocate some memory, actually read the file
+   --  and copy the bytes.
+   --  If the file does not exist, null is returned. However, if
+   --  Empty_If_Not_Found is True, then the empty string is returned instead.
+   --  Filename should be compatible with the filesystem.
+
+private
+   pragma Inline (Data, Length, Last, Offset, Is_Mmapped, To_Str_Access);
+
+   type Mapped_File_Record;
+   type Mapped_File is access Mapped_File_Record;
+
+   type Mapped_Region_Record;
+   type Mapped_Region is access Mapped_Region_Record;
+
+   Invalid_Mapped_File   : constant Mapped_File := null;
+   Invalid_Mapped_Region : constant Mapped_Region := null;
+
+end System.Mmap;
diff --git a/gcc/ada/s-mmauni-long.ads b/gcc/ada/s-mmauni-long.ads
new file mode 100644 (file)
index 0000000..f7fa0bd
--- /dev/null
@@ -0,0 +1,69 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--                      S Y S T E M . M M A P . U N I X                     --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Declaration of off_t/mmap/munmap. This particular implementation
+--  supposes off_t is long.
+
+with System.OS_Lib;
+with Interfaces.C;
+
+package System.Mmap.Unix is
+
+   type Mmap_Prot is new Interfaces.C.int;
+--     PROT_NONE  : constant Mmap_Prot := 16#00#;
+--     PROT_EXEC  : constant Mmap_Prot := 16#04#;
+   PROT_READ  : constant Mmap_Prot := 16#01#;
+   PROT_WRITE : constant Mmap_Prot := 16#02#;
+
+   type Mmap_Flags is new Interfaces.C.int;
+--     MAP_NONE    : constant Mmap_Flags := 16#00#;
+--     MAP_FIXED   : constant Mmap_Flags := 16#10#;
+   MAP_SHARED  : constant Mmap_Flags := 16#01#;
+   MAP_PRIVATE : constant Mmap_Flags := 16#02#;
+
+   type off_t is new Long_Integer;
+
+   function Mmap (Start  : Address := Null_Address;
+                  Length : Interfaces.C.size_t;
+                  Prot   : Mmap_Prot := PROT_READ;
+                  Flags  : Mmap_Flags := MAP_PRIVATE;
+                  Fd     : System.OS_Lib.File_Descriptor;
+                  Offset : off_t) return Address;
+   pragma Import (C, Mmap, "mmap");
+
+   function Munmap (Start  : Address;
+                    Length : Interfaces.C.size_t) return Integer;
+   pragma Import (C, Munmap, "munmap");
+
+   function Is_Mapping_Available return Boolean is (True);
+   --  Wheter memory mapping is actually available on this system. It is an
+   --  error to use Create_Mapping and Dispose_Mapping if this is False.
+end System.Mmap.Unix;
diff --git a/gcc/ada/s-mmosin-mingw.adb b/gcc/ada/s-mmosin-mingw.adb
new file mode 100644 (file)
index 0000000..0785f3c
--- /dev/null
@@ -0,0 +1,341 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--              S Y S T E M . M M A P . O S _ I N T E R F A C E             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.IO_Exceptions;
+with System.Strings; use System.Strings;
+
+package body System.Mmap.OS_Interface is
+
+   use Win;
+
+   function Align
+     (Addr : File_Size) return File_Size;
+   --  Align some offset/length to the lowest page boundary
+
+   function Open_Common
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean;
+      Write                 : Boolean) return System_File;
+
+   function From_UTF8 (Path : String) return Wide_String;
+   --  Convert from UTF-8 to Wide_String
+
+   ---------------
+   -- From_UTF8 --
+   ---------------
+
+   function From_UTF8 (Path : String) return Wide_String is
+      function MultiByteToWideChar
+        (Codepage : Interfaces.C.unsigned;
+         Flags    : Interfaces.C.unsigned;
+         Mbstr    : Address;
+         Mb       : Natural;
+         Wcstr    : Address;
+         Wc       : Natural) return Integer;
+      pragma Import (C, MultiByteToWideChar);
+
+      Current_Codepage : Interfaces.C.unsigned;
+      pragma Import (C, Current_Codepage, "__gnat_current_codepage");
+
+      Len : Natural;
+   begin
+      --  Compute length of the result
+      Len := MultiByteToWideChar
+        (Current_Codepage, 0, Path'Address, Path'Length, Null_Address, 0);
+      if Len = 0 then
+         raise Constraint_Error;
+      end if;
+
+      declare
+         --  Declare result
+         Res : Wide_String (1 .. Len);
+      begin
+         --  And compute it
+         Len := MultiByteToWideChar
+           (Current_Codepage, 0,
+            Path'Address, Path'Length,
+            Res'Address, Len);
+         if Len = 0 then
+            raise Constraint_Error;
+         end if;
+         return Res;
+      end;
+   end From_UTF8;
+
+   -----------------
+   -- Open_Common --
+   -----------------
+
+   function Open_Common
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean;
+      Write                 : Boolean) return System_File
+   is
+      dwDesiredAccess, dwShareMode : DWORD;
+      PageFlags                    : DWORD;
+
+      W_Filename                   : constant Wide_String :=
+         From_UTF8 (Filename) & Wide_Character'Val (0);
+      File_Handle, Mapping_Handle  : HANDLE;
+
+      SizeH                        : aliased DWORD;
+      Size                         : File_Size;
+   begin
+      if Write then
+         dwDesiredAccess := GENERIC_READ + GENERIC_WRITE;
+         dwShareMode     := 0;
+         PageFlags       := Win.PAGE_READWRITE;
+      else
+         dwDesiredAccess := GENERIC_READ;
+         dwShareMode     := Win.FILE_SHARE_READ;
+         PageFlags       := Win.PAGE_READONLY;
+      end if;
+
+      --  Actually open the file
+
+      File_Handle := CreateFile
+        (W_Filename'Address, dwDesiredAccess, dwShareMode,
+         null, OPEN_EXISTING, Win.FILE_ATTRIBUTE_NORMAL, 0);
+
+      if File_Handle = Win.INVALID_HANDLE_VALUE then
+         raise Ada.IO_Exceptions.Name_Error
+           with "Cannot open " & Filename;
+      end if;
+
+      --  Compute its size
+
+      Size := File_Size (Win.GetFileSize (File_Handle, SizeH'Access));
+
+      if Size = Win.INVALID_FILE_SIZE then
+         raise Ada.IO_Exceptions.Use_Error;
+      end if;
+
+      if SizeH /= 0 and then File_Size'Size > 32 then
+         Size := Size + (File_Size (SizeH) * 2 ** 32);
+      end if;
+
+      --  Then create a mapping object, if needed. On Win32, file memory
+      --  mapping is always available.
+
+      if Use_Mmap_If_Available then
+         Mapping_Handle :=
+            Win.CreateFileMapping
+              (File_Handle, null, PageFlags,
+               0, DWORD (Size), Standard.System.Null_Address);
+      else
+         Mapping_Handle := Win.INVALID_HANDLE_VALUE;
+      end if;
+
+      return
+        (Handle         => File_Handle,
+         Mapped         => Use_Mmap_If_Available,
+         Mapping_Handle => Mapping_Handle,
+         Write          => Write,
+         Length         => Size);
+   end Open_Common;
+
+   ---------------
+   -- Open_Read --
+   ---------------
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File is
+   begin
+      return Open_Common (Filename, Use_Mmap_If_Available, False);
+   end Open_Read;
+
+   ----------------
+   -- Open_Write --
+   ----------------
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File is
+   begin
+      return Open_Common (Filename, Use_Mmap_If_Available, True);
+   end Open_Write;
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close (File : in out System_File) is
+      Ignored : BOOL;
+      pragma Unreferenced (Ignored);
+   begin
+      Ignored := CloseHandle (File.Mapping_Handle);
+      Ignored := CloseHandle (File.Handle);
+      File.Handle := Win.INVALID_HANDLE_VALUE;
+      File.Mapping_Handle := Win.INVALID_HANDLE_VALUE;
+   end Close;
+
+   --------------------
+   -- Read_From_Disk --
+   --------------------
+
+   function Read_From_Disk
+     (File           : System_File;
+      Offset, Length : File_Size) return System.Strings.String_Access
+   is
+      Buffer : String_Access := new String (1 .. Integer (Length));
+
+      Pos    : DWORD;
+      NbRead : aliased DWORD;
+      pragma Unreferenced (Pos);
+   begin
+      Pos := Win.SetFilePointer
+        (File.Handle, LONG (Offset), null, Win.FILE_BEGIN);
+
+      if Win.ReadFile
+         (File.Handle, Buffer.all'Address,
+          DWORD (Length), NbRead'Unchecked_Access, null) = Win.FALSE
+      then
+         System.Strings.Free (Buffer);
+         raise Ada.IO_Exceptions.Device_Error;
+      end if;
+      return Buffer;
+   end Read_From_Disk;
+
+   -------------------
+   -- Write_To_Disk --
+   -------------------
+
+   procedure Write_To_Disk
+     (File           : System_File;
+      Offset, Length : File_Size;
+      Buffer         : System.Strings.String_Access)
+   is
+      Pos       : DWORD;
+      NbWritten : aliased DWORD;
+      pragma Unreferenced (Pos);
+   begin
+      pragma Assert (File.Write);
+      Pos := Win.SetFilePointer
+        (File.Handle, LONG (Offset), null, Win.FILE_BEGIN);
+
+      if Win.WriteFile
+         (File.Handle, Buffer.all'Address,
+          DWORD (Length), NbWritten'Unchecked_Access, null) = Win.FALSE
+      then
+         raise Ada.IO_Exceptions.Device_Error;
+      end if;
+   end Write_To_Disk;
+
+   --------------------
+   -- Create_Mapping --
+   --------------------
+
+   procedure Create_Mapping
+     (File           : System_File;
+      Offset, Length : in out File_Size;
+      Mutable        : Boolean;
+      Mapping        : out System_Mapping)
+   is
+      Flags : DWORD;
+   begin
+      if File.Write then
+         Flags := Win.FILE_MAP_WRITE;
+      elsif Mutable then
+         Flags := Win.FILE_MAP_COPY;
+      else
+         Flags := Win.FILE_MAP_READ;
+      end if;
+
+      --  Adjust offset and mapping length to account for the required
+      --  alignment of offset on page boundary.
+
+      declare
+         Queried_Offset : constant File_Size := Offset;
+      begin
+         Offset := Align (Offset);
+
+         --  First extend the length to compensate the offset shift, then align
+         --  it on the upper page boundary, so that the whole queried area is
+         --  covered.
+
+         Length := Length + Queried_Offset - Offset;
+         Length := Align (Length + Get_Page_Size - 1);
+
+         --  But do not exceed the length of the file
+         if Offset + Length > File.Length then
+            Length := File.Length - Offset;
+         end if;
+      end;
+
+      if Length > File_Size (Integer'Last) then
+         raise Ada.IO_Exceptions.Device_Error;
+      else
+         Mapping := Invalid_System_Mapping;
+         Mapping.Address :=
+            Win.MapViewOfFile
+              (File.Mapping_Handle, Flags,
+               0, DWORD (Offset), SIZE_T (Length));
+         Mapping.Length := Length;
+      end if;
+   end Create_Mapping;
+
+   ---------------------
+   -- Dispose_Mapping --
+   ---------------------
+
+   procedure Dispose_Mapping
+     (Mapping : in out System_Mapping)
+   is
+      Ignored : BOOL;
+      pragma Unreferenced (Ignored);
+   begin
+      Ignored := Win.UnmapViewOfFile (Mapping.Address);
+      Mapping := Invalid_System_Mapping;
+   end Dispose_Mapping;
+
+   -------------------
+   -- Get_Page_Size --
+   -------------------
+
+   function Get_Page_Size return File_Size is
+      SystemInfo : aliased SYSTEM_INFO;
+   begin
+      GetSystemInfo (SystemInfo'Unchecked_Access);
+      return File_Size (SystemInfo.dwAllocationGranularity);
+   end Get_Page_Size;
+
+   -----------
+   -- Align --
+   -----------
+
+   function Align
+     (Addr : File_Size) return File_Size is
+   begin
+      return Addr - Addr mod Get_Page_Size;
+   end Align;
+
+end System.Mmap.OS_Interface;
diff --git a/gcc/ada/s-mmosin-mingw.ads b/gcc/ada/s-mmosin-mingw.ads
new file mode 100644 (file)
index 0000000..76874a8
--- /dev/null
@@ -0,0 +1,235 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--              S Y S T E M . M M A P . O S _ I N T E R F A C E             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  OS pecularities abstraction package for Win32 systems.
+
+package System.Mmap.OS_Interface is
+
+   --  The Win package contains copy of definition found in recent System.Win32
+   --  unit provided with the GNAT compiler. The copy is needed to be able to
+   --  compile this unit with older compilers. Note that this internal Win
+   --  package can be removed when GNAT 6.1.0 is not supported anymore.
+
+   package Win is
+
+      subtype PVOID is Standard.System.Address;
+
+      type HANDLE is new Interfaces.C.ptrdiff_t;
+
+      type WORD   is new Interfaces.C.unsigned_short;
+      type DWORD  is new Interfaces.C.unsigned_long;
+      type LONG   is new Interfaces.C.long;
+      type SIZE_T is new Interfaces.C.size_t;
+
+      type BOOL   is new Interfaces.C.int;
+      for BOOL'Size use Interfaces.C.int'Size;
+
+      FALSE : constant := 0;
+
+      GENERIC_READ  : constant := 16#80000000#;
+      GENERIC_WRITE : constant := 16#40000000#;
+      OPEN_EXISTING : constant := 3;
+
+      type OVERLAPPED is record
+         Internal     : DWORD;
+         InternalHigh : DWORD;
+         Offset       : DWORD;
+         OffsetHigh   : DWORD;
+         hEvent       : HANDLE;
+      end record;
+
+      type SECURITY_ATTRIBUTES is record
+         nLength             : DWORD;
+         pSecurityDescriptor : PVOID;
+         bInheritHandle      : BOOL;
+      end record;
+
+      type SYSTEM_INFO is record
+         dwOemId : DWORD;
+         dwPageSize : DWORD;
+         lpMinimumApplicationAddress : PVOID;
+         lpMaximumApplicationAddress : PVOID;
+         dwActiveProcessorMask       : PVOID;
+         dwNumberOfProcessors        : DWORD;
+         dwProcessorType             : DWORD;
+         dwAllocationGranularity     : DWORD;
+         wProcessorLevel             : WORD;
+         wProcessorRevision          : WORD;
+      end record;
+      type LP_SYSTEM_INFO is access all SYSTEM_INFO;
+
+      INVALID_HANDLE_VALUE  : constant HANDLE := -1;
+      FILE_BEGIN            : constant := 0;
+      FILE_SHARE_READ       : constant := 16#00000001#;
+      FILE_ATTRIBUTE_NORMAL : constant := 16#00000080#;
+      FILE_MAP_COPY         : constant := 1;
+      FILE_MAP_READ         : constant := 4;
+      FILE_MAP_WRITE        : constant := 2;
+      PAGE_READONLY         : constant := 16#0002#;
+      PAGE_READWRITE        : constant := 16#0004#;
+      INVALID_FILE_SIZE     : constant := 16#FFFFFFFF#;
+
+      function CreateFile
+        (lpFileName            : Standard.System.Address;
+         dwDesiredAccess       : DWORD;
+         dwShareMode           : DWORD;
+         lpSecurityAttributes  : access SECURITY_ATTRIBUTES;
+         dwCreationDisposition : DWORD;
+         dwFlagsAndAttributes  : DWORD;
+         hTemplateFile         : HANDLE) return HANDLE;
+      pragma Import (Stdcall, CreateFile, "CreateFileW");
+
+      function WriteFile
+        (hFile                  : HANDLE;
+         lpBuffer               : Standard.System.Address;
+         nNumberOfBytesToWrite  : DWORD;
+         lpNumberOfBytesWritten : access DWORD;
+         lpOverlapped           : access OVERLAPPED) return BOOL;
+      pragma Import (Stdcall, WriteFile, "WriteFile");
+
+      function ReadFile
+        (hFile                : HANDLE;
+         lpBuffer             : Standard.System.Address;
+         nNumberOfBytesToRead : DWORD;
+         lpNumberOfBytesRead  : access DWORD;
+         lpOverlapped         : access OVERLAPPED) return BOOL;
+      pragma Import (Stdcall, ReadFile, "ReadFile");
+
+      function CloseHandle (hObject : HANDLE) return BOOL;
+      pragma Import (Stdcall, CloseHandle, "CloseHandle");
+
+      function GetFileSize
+        (hFile : HANDLE; lpFileSizeHigh : access DWORD) return DWORD;
+      pragma Import (Stdcall, GetFileSize, "GetFileSize");
+
+      function SetFilePointer
+        (hFile                : HANDLE;
+         lDistanceToMove      : LONG;
+         lpDistanceToMoveHigh : access LONG;
+         dwMoveMethod         : DWORD) return DWORD;
+      pragma Import (Stdcall, SetFilePointer, "SetFilePointer");
+
+      function CreateFileMapping
+        (hFile                : HANDLE;
+         lpSecurityAttributes : access SECURITY_ATTRIBUTES;
+         flProtect            : DWORD;
+         dwMaximumSizeHigh    : DWORD;
+         dwMaximumSizeLow     : DWORD;
+         lpName               : Standard.System.Address) return HANDLE;
+      pragma Import (Stdcall, CreateFileMapping, "CreateFileMappingW");
+
+      function MapViewOfFile
+        (hFileMappingObject   : HANDLE;
+         dwDesiredAccess      : DWORD;
+         dwFileOffsetHigh     : DWORD;
+         dwFileOffsetLow      : DWORD;
+         dwNumberOfBytesToMap : SIZE_T) return Standard.System.Address;
+      pragma Import (Stdcall, MapViewOfFile, "MapViewOfFile");
+
+      function UnmapViewOfFile
+         (lpBaseAddress : Standard.System.Address) return BOOL;
+      pragma Import (Stdcall, UnmapViewOfFile, "UnmapViewOfFile");
+
+      procedure GetSystemInfo (lpSystemInfo : LP_SYSTEM_INFO);
+      pragma Import (Stdcall, GetSystemInfo, "GetSystemInfo");
+
+   end Win;
+
+   type System_File is record
+      Handle         : Win.HANDLE;
+
+      Mapped         : Boolean;
+      --  Whether mapping is requested by the user and available on the system
+
+      Mapping_Handle : Win.HANDLE;
+
+      Write          : Boolean;
+      --  Whether this file can be written to
+
+      Length         : File_Size;
+      --  Length of the file. Used to know what can be mapped in the file
+   end record;
+
+   type System_Mapping is record
+      Address        : Standard.System.Address;
+      Length         : File_Size;
+   end record;
+
+   Invalid_System_File    : constant System_File :=
+     (Win.INVALID_HANDLE_VALUE, False, Win.INVALID_HANDLE_VALUE, False, 0);
+   Invalid_System_Mapping : constant System_Mapping :=
+     (Standard.System.Null_Address, 0);
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File;
+   --  Open a file for reading and return the corresponding System_File. Raise
+   --  a Ada.IO_Exceptions.Name_Error if unsuccessful.
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File;
+   --  Likewise for writing to a file
+
+   procedure Close (File : in out System_File);
+   --  Close a system file
+
+   function Read_From_Disk
+     (File           : System_File;
+      Offset, Length : File_Size) return System.Strings.String_Access;
+   --  Read a fragment of a file. It is up to the caller to free the result
+   --  when done with it.
+
+   procedure Write_To_Disk
+     (File           : System_File;
+      Offset, Length : File_Size;
+      Buffer         : System.Strings.String_Access);
+   --  Write some content to a fragment of a file
+
+   procedure Create_Mapping
+     (File           : System_File;
+      Offset, Length : in out File_Size;
+      Mutable        : Boolean;
+      Mapping        : out System_Mapping);
+   --  Create a memory mapping for the given File, for the area starting at
+   --  Offset and containing Length bytes. Store it to Mapping.
+   --  Note that Offset and Length may be modified according to the system
+   --  needs (for boudaries, for instance). The caller must cope with actually
+   --  wider mapped areas.
+
+   procedure Dispose_Mapping
+     (Mapping : in out System_Mapping);
+   --  Unmap a previously-created mapping
+
+   function Get_Page_Size return File_Size;
+   --  Return the number of bytes in a system page.
+
+end System.Mmap.OS_Interface;
diff --git a/gcc/ada/s-mmosin-unix.adb b/gcc/ada/s-mmosin-unix.adb
new file mode 100644 (file)
index 0000000..a68c59f
--- /dev/null
@@ -0,0 +1,231 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--              S Y S T E M . M M A P . O S _ I N T E R F A C E             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.IO_Exceptions;
+with System; use System;
+
+with System.OS_Lib; use System.OS_Lib;
+with System.Mmap.Unix; use System.Mmap.Unix;
+
+package body System.Mmap.OS_Interface is
+
+   function Align
+     (Addr : File_Size) return File_Size;
+   --  Align some offset/length to the lowest page boundary
+
+   function Is_Mapping_Available return Boolean renames
+     System.Mmap.Unix.Is_Mapping_Available;
+   --  Wheter memory mapping is actually available on this system. It is an
+   --  error to use Create_Mapping and Dispose_Mapping if this is False.
+
+   ---------------
+   -- Open_Read --
+   ---------------
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File is
+      Fd : constant File_Descriptor :=
+        Open_Read (Filename, Binary);
+   begin
+      if Fd = Invalid_FD then
+         raise Ada.IO_Exceptions.Name_Error
+           with "Cannot open " & Filename;
+      end if;
+      return
+        (Fd     => Fd,
+         Mapped => Use_Mmap_If_Available and then Is_Mapping_Available,
+         Write  => False,
+         Length => File_Size (File_Length (Fd)));
+   end Open_Read;
+
+   ----------------
+   -- Open_Write --
+   ----------------
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File is
+      Fd : constant File_Descriptor :=
+        Open_Read_Write (Filename, Binary);
+   begin
+      if Fd = Invalid_FD then
+         raise Ada.IO_Exceptions.Name_Error
+         with "Cannot open " & Filename;
+      end if;
+      return
+        (Fd     => Fd,
+         Mapped => Use_Mmap_If_Available and then Is_Mapping_Available,
+         Write  => True,
+         Length => File_Size (File_Length (Fd)));
+   end Open_Write;
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close (File : in out System_File) is
+   begin
+      Close (File.Fd);
+      File.Fd := Invalid_FD;
+   end Close;
+
+   --------------------
+   -- Read_From_Disk --
+   --------------------
+
+   function Read_From_Disk
+     (File           : System_File;
+      Offset, Length : File_Size) return System.Strings.String_Access
+   is
+      Buffer : String_Access := new String (1 .. Integer (Length));
+   begin
+      --  ??? Lseek offset should be a size_t instead of a Long_Integer
+
+      Lseek (File.Fd, Long_Integer (Offset), Seek_Set);
+      if System.OS_Lib.Read (File.Fd, Buffer.all'Address, Integer (Length))
+        /= Integer (Length)
+      then
+         System.Strings.Free (Buffer);
+         raise Ada.IO_Exceptions.Device_Error;
+      end if;
+      return Buffer;
+   end Read_From_Disk;
+
+   -------------------
+   -- Write_To_Disk --
+   -------------------
+
+   procedure Write_To_Disk
+     (File           : System_File;
+      Offset, Length : File_Size;
+      Buffer         : System.Strings.String_Access) is
+   begin
+      pragma Assert (File.Write);
+      Lseek (File.Fd, Long_Integer (Offset), Seek_Set);
+      if System.OS_Lib.Write (File.Fd, Buffer.all'Address, Integer (Length))
+        /= Integer (Length)
+      then
+         raise Ada.IO_Exceptions.Device_Error;
+      end if;
+   end Write_To_Disk;
+
+   --------------------
+   -- Create_Mapping --
+   --------------------
+
+   procedure Create_Mapping
+     (File           : System_File;
+      Offset, Length : in out File_Size;
+      Mutable        : Boolean;
+      Mapping        : out System_Mapping)
+   is
+      Prot  : Mmap_Prot;
+      Flags : Mmap_Flags;
+   begin
+      if File.Write then
+         Prot  := PROT_READ + PROT_WRITE;
+         Flags := MAP_SHARED;
+      else
+         Prot := PROT_READ;
+         if Mutable then
+            Prot := Prot + PROT_WRITE;
+         end if;
+         Flags := MAP_PRIVATE;
+      end if;
+
+      --  Adjust offset and mapping length to account for the required
+      --  alignment of offset on page boundary.
+
+      declare
+         Queried_Offset : constant File_Size := Offset;
+      begin
+         Offset := Align (Offset);
+
+         --  First extend the length to compensate the offset shift, then align
+         --  it on the upper page boundary, so that the whole queried area is
+         --  covered.
+
+         Length := Length + Queried_Offset - Offset;
+         Length := Align (Length + Get_Page_Size - 1);
+      end;
+
+      if Length > File_Size (Integer'Last) then
+         raise Ada.IO_Exceptions.Device_Error;
+      else
+         Mapping :=
+           (Address => System.Mmap.Unix.Mmap
+              (Offset => off_t (Offset),
+               Length => Interfaces.C.size_t (Length),
+               Prot   => Prot,
+               Flags  => Flags,
+               Fd     => File.Fd),
+            Length  => Length);
+      end if;
+   end Create_Mapping;
+
+   ---------------------
+   -- Dispose_Mapping --
+   ---------------------
+
+   procedure Dispose_Mapping
+     (Mapping : in out System_Mapping)
+   is
+      Ignored : Integer;
+      pragma Unreferenced (Ignored);
+   begin
+      Ignored := Munmap
+        (Mapping.Address, Interfaces.C.size_t (Mapping.Length));
+      Mapping := Invalid_System_Mapping;
+   end Dispose_Mapping;
+
+   -------------------
+   -- Get_Page_Size --
+   -------------------
+
+   function Get_Page_Size return File_Size is
+      function Internal return Integer;
+      pragma Import (C, Internal, "getpagesize");
+   begin
+      return File_Size (Internal);
+   end Get_Page_Size;
+
+   -----------
+   -- Align --
+   -----------
+
+   function Align
+     (Addr : File_Size) return File_Size is
+   begin
+      return Addr - Addr mod Get_Page_Size;
+   end Align;
+
+end System.Mmap.OS_Interface;
diff --git a/gcc/ada/s-mmosin-unix.ads b/gcc/ada/s-mmosin-unix.ads
new file mode 100644 (file)
index 0000000..0157639
--- /dev/null
@@ -0,0 +1,105 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
+--                                                                          --
+--              S Y S T E M . M M A P . O S _ I N T E R F A C E             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                     Copyright (C) 2007-2016, AdaCore                     --
+--                                                                          --
+-- This library is free software;  you can redistribute it and/or modify it --
+-- under terms of the  GNU General Public License  as published by the Free --
+-- Software  Foundation;  either version 3,  or (at your  option) any later --
+-- version. This library is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
+-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with System.OS_Lib;
+
+--  OS pecularities abstraction package for Unix systems.
+
+package System.Mmap.OS_Interface is
+
+   type System_File is record
+      Fd     : System.OS_Lib.File_Descriptor;
+
+      Mapped : Boolean;
+      --  Whether mapping is requested by the user and available on the system
+
+      Write  : Boolean;
+      --  Whether this file can be written to
+
+      Length : File_Size;
+      --  Length of the file. Used to know what can be mapped in the file
+   end record;
+
+   type System_Mapping is record
+      Address : Standard.System.Address;
+      Length  : File_Size;
+   end record;
+
+   Invalid_System_File    : constant System_File :=
+     (System.OS_Lib.Invalid_FD, False, False, 0);
+   Invalid_System_Mapping : constant System_Mapping :=
+     (Standard.System.Null_Address, 0);
+
+   function Open_Read
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File;
+   --  Open a file for reading and return the corresponding System_File. Raise
+   --  a Ada.IO_Exceptions.Name_Error if unsuccessful.
+
+   function Open_Write
+     (Filename              : String;
+      Use_Mmap_If_Available : Boolean := True) return System_File;
+   --  Likewise for writing to a file
+
+   procedure Close (File : in out System_File);
+   --  Close a system file
+
+   function Read_From_Disk
+     (File           : System_File;
+      Offset, Length : File_Size) return System.Strings.String_Access;
+   --  Read a fragment of a file. It is up to the caller to free the result
+   --  when done with it.
+
+   procedure Write_To_Disk
+     (File           : System_File;
+      Offset, Length : File_Size;
+      Buffer         : System.Strings.String_Access);
+   --  Write some content to a fragment of a file
+
+   procedure Create_Mapping
+     (File           : System_File;
+      Offset, Length : in out File_Size;
+      Mutable        : Boolean;
+      Mapping        : out System_Mapping);
+   --  Create a memory mapping for the given File, for the area starting at
+   --  Offset and containing Length bytes. Store it to Mapping.
+   --  Note that Offset and Length may be modified according to the system
+   --  needs (for boudaries, for instance). The caller must cope with actually
+   --  wider mapped areas.
+
+   procedure Dispose_Mapping
+     (Mapping : in out System_Mapping);
+   --  Unmap a previously-created mapping
+
+   function Get_Page_Size return File_Size;
+   --  Return the number of bytes in a system page.
+
+end System.Mmap.OS_Interface;
index 7a23005fae20bc898d25a696779a468f9d4fc887..a88f8486d80db36bd09de50bccc078e640aab623 100644 (file)
@@ -59,10 +59,10 @@ with Sem_Res;  use Sem_Res;
 with Sem_Type; use Sem_Type;
 with Sem_Util; use Sem_Util;
 with Sem_Warn; use Sem_Warn;
+with Sinfo;    use Sinfo;
 with Sinput;   use Sinput;
 with Snames;   use Snames;
 with Stand;    use Stand;
-with Sinfo;    use Sinfo;
 with Targparm; use Targparm;
 with Ttypes;   use Ttypes;
 with Tbuild;   use Tbuild;
@@ -1888,7 +1888,7 @@ package body Sem_Ch13 is
                Set_From_Aspect_Specification (Aitem);
             end Make_Aitem_Pragma;
 
-         --  Start of processing for Analyze_Aspect_Specifications
+         --  Start of processing for Analyze_One_Aspect
 
          begin
             --  Skip aspect if already analyzed, to avoid looping in some cases
@@ -1934,8 +1934,25 @@ package body Sem_Ch13 is
 
             Set_Analyzed (Aspect);
             Set_Entity (Aspect, E);
+
+            --  Build the reference to E that will be used in the built pragmas
+
             Ent := New_Occurrence_Of (E, Sloc (Id));
 
+            if A_Id = Aspect_Attach_Handler
+              or else A_Id = Aspect_Interrupt_Handler
+            then
+               --  Decorate the reference as comming from the sources and force
+               --  its reanalysis to generate the reference to E; required to
+               --  avoid reporting spurious warning on E as unreferenced entity
+               --  (because aspects are not fully analyzed).
+
+               Set_Comes_From_Source (Ent, Comes_From_Source (Id));
+               Set_Entity (Ent, Empty);
+
+               Analyze (Ent);
+            end if;
+
             --  Check for duplicate aspect. Note that the Comes_From_Source
             --  test allows duplicate Pre/Post's that we generate internally
             --  to escape being flagged here.
index 512615fe4b9858151c9fee69ee6def88222d0022..ec47142644e2e03c6011ad42b1d277dbbd558f8e 100644 (file)
@@ -9127,9 +9127,13 @@ package body Sem_Ch3 is
          end if;
       end if;
 
-      --  We similarly inherit predicates
+      --  We similarly inherit predicates. Note that for scalar derived types
+      --  the predicate is inherited from the first subtype, and not from its
+      --  (anonymous) base type.
 
-      if Has_Predicates (Parent_Type) then
+      if Has_Predicates (Parent_Type)
+        or else  Has_Predicates (First_Subtype (Parent_Type))
+      then
          Set_Has_Predicates (Derived_Type);
       end if;
 
index ec449c1efcb502b0df32a111e31119bb8da404a7..b3e597f3d09256e311f7f4a76e535bd03bd6947b 100644 (file)
@@ -8476,9 +8476,21 @@ package body Sem_Ch6 is
       elsif Is_Entity_Name (E1) and then Is_Entity_Name (E2) then
          if Present (Entity (E1)) then
             return Entity (E1) = Entity (E2)
+
+              --  One may be a discriminant that has been replaced by
+              --  the correspondding discriminal
+
               or else (Chars (Entity (E1)) = Chars (Entity (E2))
                         and then Ekind (Entity (E1)) = E_Discriminant
-                        and then Ekind (Entity (E2)) = E_In_Parameter);
+                        and then Ekind (Entity (E2)) = E_In_Parameter)
+
+             --  AI12-050 : the loop variables of quantified expressions
+             --  match if the have the same identifier, even though they
+             --  are different entities.
+
+              or else (Chars (Entity (E1)) = Chars (Entity (E2))
+                       and then Ekind (Entity (E1)) = E_Loop_Parameter
+                       and then Ekind (Entity (E2)) = E_Loop_Parameter);
 
          elsif Nkind (E1) = N_Expanded_Name
            and then Nkind (E2) = N_Expanded_Name
index ea868811e62a14f108772287648313c4707641af..1a81cbfc4497e64e8be9d323f9fffc811168e117 100644 (file)
@@ -760,9 +760,6 @@ package body Sem_Ch8 is
       --  has already established its actual subtype. This is only relevant
       --  if the renamed object is an explicit dereference.
 
-      function In_Generic_Scope (E : Entity_Id) return Boolean;
-      --  Determine whether entity E is inside a generic cope
-
       ------------------------------
       -- Check_Constrained_Object --
       ------------------------------
@@ -824,26 +821,6 @@ package body Sem_Ch8 is
          end if;
       end Check_Constrained_Object;
 
-      ----------------------
-      -- In_Generic_Scope --
-      ----------------------
-
-      function In_Generic_Scope (E : Entity_Id) return Boolean is
-         S : Entity_Id;
-
-      begin
-         S := Scope (E);
-         while Present (S) and then S /= Standard_Standard loop
-            if Is_Generic_Unit (S) then
-               return True;
-            end if;
-
-            S := Scope (S);
-         end loop;
-
-         return False;
-      end In_Generic_Scope;
-
    --  Start of processing for Analyze_Object_Renaming
 
    begin
index fce4643dfbf524d65d4adaf7f56c1a17ebeeb8be..531dd70a388dc401432598ae871aac744dad1adf 100644 (file)
@@ -23,6 +23,7 @@
 --                                                                          --
 ------------------------------------------------------------------------------
 
+with Aspects;  use Aspects;
 with Atree;    use Atree;
 with Checks;   use Checks;
 with Debug;    use Debug;
@@ -4989,7 +4990,13 @@ package body Sem_Eval is
       then
          return False;
 
-      elsif Has_Dynamic_Predicate_Aspect (Typ) then
+      --  If there is a dynamic predicate for the type (declared or inherited)
+      --  the expression is not static.
+
+      elsif Has_Dynamic_Predicate_Aspect (Typ)
+        or else (Is_Derived_Type (Typ)
+                  and then Has_Aspect (Typ, Aspect_Dynamic_Predicate))
+      then
          return False;
 
       --  String types
index ead3efdd8dbcd283c82983141e35a8cd6fa63749..58a157bdd5aea571e5e325f1f62af7225694feab 100644 (file)
@@ -10518,6 +10518,26 @@ package body Sem_Util is
           and then Assertion_Expression_Pragma (Get_Pragma_Id (Prag));
    end In_Assertion_Expression_Pragma;
 
+   ----------------------
+   -- In_Generic_Scope --
+   ----------------------
+
+   function In_Generic_Scope (E : Entity_Id) return Boolean is
+      S : Entity_Id;
+
+   begin
+      S := Scope (E);
+      while Present (S) and then S /= Standard_Standard loop
+         if Is_Generic_Unit (S) then
+            return True;
+         end if;
+
+         S := Scope (S);
+      end loop;
+
+      return False;
+   end In_Generic_Scope;
+
    -----------------
    -- In_Instance --
    -----------------
index f1a12a9380e871ceaa239ba9096411253d83da1c..a1e79b1c330b9cb89c9a6e10c99eb4e2799b8f0e 100644 (file)
@@ -556,13 +556,11 @@ package Sem_Util is
    --  Returns the declaration node enclosing N (including possibly N itself),
    --  if any, or Empty otherwise.
 
-   function Enclosing_Generic_Body
-     (N : Node_Id) return Node_Id;
+   function Enclosing_Generic_Body (N : Node_Id) return Node_Id;
    --  Returns the Node_Id associated with the innermost enclosing generic
    --  body, if any. If none, then returns Empty.
 
-   function Enclosing_Generic_Unit
-     (N : Node_Id) return Node_Id;
+   function Enclosing_Generic_Unit (N : Node_Id) return Node_Id;
    --  Returns the Node_Id associated with the innermost enclosing generic
    --  unit, if any. If none, then returns Empty.
 
@@ -1193,6 +1191,9 @@ package Sem_Util is
    --  Returns True if node N appears within a pragma that acts as an assertion
    --  expression. See Sem_Prag for the list of qualifying pragmas.
 
+   function In_Generic_Scope (E : Entity_Id) return Boolean;
+   --  Returns True if entity E is inside a generic scope
+
    function In_Instance return Boolean;
    --  Returns True if the current scope is within a generic instance
 
index 5390209fd168798deb274c4df7eeaa89de4748af..679c70a77f788eaff32233eb210805858b281342 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *         Copyright (C) 1992-2015, Free Software Foundation, Inc.          *
+ *         Copyright (C) 1992-2016, Free Software Foundation, Inc.          *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
@@ -193,7 +193,7 @@ __gnat_set_mode (int handle, int mode)
 
  switch (mode) {
     case 0 : WIN_SETMODE (handle, _O_BINARY);          break;
-    case 1 : WIN_SETMODE (handle, CurrentCCSEncoding); break;
+    case 1 : WIN_SETMODE (handle, __gnat_current_ccs_encoding); break;
     case 2 : WIN_SETMODE (handle, _O_TEXT);            break;
     case 3 : WIN_SETMODE (handle, _O_U8TEXT);          break;
     case 4 : WIN_SETMODE (handle, _O_WTEXT);           break;