From: Alexandre Oliva <ol...@adacore.com>

The initial C++ base-type exception interoperation support change
brought all of GNAT.CPP* along with raise-gcc, because of
[__gnat_]Convert_Caught_Object.  Move that private but pragma-exported
function to GNAT.CPP.Std.Type_Info, so that it can rely on the C++
virtual/dispatch calls that justified the introduction of the Ada
wrapper type, to avoid emulating virtual calls in C or bringing in a
dependency on the C++ compiler and runtime.

Drop the CharPtr package instantiation, that brought a huge amount of
unnecessary code, and use string and storage primitives instead, using
the strcmp builtin directly for the C string compares.

Move the conversion to Ada String in Name to the wrapper interface in
GNAT.CPP.Std, adjusting the private internal type to shave off a few
more bytes from the only unit that raise-gcc will still need.

Finally, disable heap finalization for Type_Info_Ptr, to avoid
dragging in all of the finalization code.  Thank to Eric Botcazou for
the suggestion.

gcc/ada/ChangeLog:

        * libgnat/g-cppexc.adb (Convert_Caught_Object): Move...
        * libgnat/g-cstyin.adb (Convert_Caught_Object):  ... here.
        Use object call notation.
        (strcmp): New.
        (Char_Arr, CharPtr, Char_Pointer, To_chars_ptr): Drop.  Do not
        import Interfaces.C.Pointers.
        (To_Pointer): Convert from System.Address.
        (Name_Starts_With_Asterisk): Rename local variable.
        (Name_Past_Asterisk): Rewrite with System.Address and strcmp.
        Import System.Storage_Elements.
        (Equals): Use strcmp.
        (Before): Fix logic error.  Use strcmp.
        (Name): Move conversion to String...
        * libgnat/g-cppstd.adb (Name): ... here.  Import
        Interfaces.C.Strings.
        * libgnat/g-cppstd.ads (Type_Info_Ptr): Disable heap
        finalization.
        * libgnat/g-cstyin.ads (Name): Change return type.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/libgnat/g-cppexc.adb | 40 ------------------
 gcc/ada/libgnat/g-cppstd.adb |  3 +-
 gcc/ada/libgnat/g-cppstd.ads |  4 +-
 gcc/ada/libgnat/g-cstyin.adb | 80 ++++++++++++++++++++++++++----------
 gcc/ada/libgnat/g-cstyin.ads |  2 +-
 5 files changed, 65 insertions(+), 64 deletions(-)

diff --git a/gcc/ada/libgnat/g-cppexc.adb b/gcc/ada/libgnat/g-cppexc.adb
index 11022880670..bad748fdfe3 100644
--- a/gcc/ada/libgnat/g-cppexc.adb
+++ b/gcc/ada/libgnat/g-cppexc.adb
@@ -267,44 +267,4 @@ package body GNAT.CPP_Exceptions is
 
    end Get_Type_Info;
 
-   function Convert_Caught_Object (Choice, Except : Type_Info_Ptr;
-                                   Thrown         : in out Address;
-                                   Lang           : Character)
-                                   return           Interfaces.C.C_bool;
-   pragma Export (Cpp, Convert_Caught_Object, "__gnat_convert_caught_object");
-   --  Convert the exception object at Thrown, under Lang convention,
-   --  from type Except to type Choice, adjusting Thrown as needed and
-   --  returning True, or returning False in case the conversion fails.
-
-   ---------------------------
-   -- Convert_Caught_Object --
-   ---------------------------
-
-   function Convert_Caught_Object (Choice, Except : Type_Info_Ptr;
-                                   Thrown         : in out Address;
-                                   Lang           : Character)
-                                   return           Interfaces.C.C_bool is
-   begin
-      if Equals (Choice, Except) then
-         return C_bool'(True);
-      end if;
-
-      if Lang = 'B' then
-         if Is_Pointer_P (Except) then
-            declare
-               Thrown_Indirect : Address;
-               for Thrown_Indirect'Address use Thrown;
-            begin
-               Thrown := Thrown_Indirect;
-            end;
-         end if;
-
-         if Do_Catch (Choice, Except, Thrown, 1) then
-            return C_bool'(True);
-         end if;
-      end if;
-
-      return C_bool'(False);
-   end Convert_Caught_Object;
-
 end GNAT.CPP_Exceptions;
diff --git a/gcc/ada/libgnat/g-cppstd.adb b/gcc/ada/libgnat/g-cppstd.adb
index 000dd474c5c..8cb64edaffe 100644
--- a/gcc/ada/libgnat/g-cppstd.adb
+++ b/gcc/ada/libgnat/g-cppstd.adb
@@ -34,6 +34,7 @@
 
 with GNAT.CPP.Std.Type_Info;
 with Ada.Unchecked_Conversion;
+with Interfaces.C.Strings; use Interfaces.C.Strings;
 
 package body GNAT.CPP.Std is
    ----------------------
@@ -53,7 +54,7 @@ package body GNAT.CPP.Std is
 
    function Name (this : Type_Info_Ptr)
                   return String
-   is (this.all.Name);
+   is (Value (this.all.Name));
 
    ---------------
    --  Before  ---
diff --git a/gcc/ada/libgnat/g-cppstd.ads b/gcc/ada/libgnat/g-cppstd.ads
index 63ef03e43dd..be8907c4f77 100644
--- a/gcc/ada/libgnat/g-cppstd.ads
+++ b/gcc/ada/libgnat/g-cppstd.ads
@@ -50,7 +50,8 @@ package GNAT.CPP.Std is
    function Name (this : Type_Info_Ptr)
                   --  return Interfaces.C.Strings.chars_ptr;
                   return String;
-   --  Exposed std::type_info member function.
+   --  Exposed std::type_info member function.  ??? Would it ever be
+   --  desirable to get direct access to the internal chars_ptr?
 
    function Before (this, that : Type_Info_Ptr)
                     --  return Interfaces.C.Extensions.bool;
@@ -89,6 +90,7 @@ private
 
    type Type_Info_Ptr is access constant Type_Info.type_info'Class;
    pragma No_Strict_Aliasing (Type_Info_Ptr);
+   pragma No_Heap_Finalization (Type_Info_Ptr);
 
    No_Type_Info : constant Type_Info_Ptr := null;
 
diff --git a/gcc/ada/libgnat/g-cstyin.adb b/gcc/ada/libgnat/g-cstyin.adb
index 8036ed52762..b194f7f62b7 100644
--- a/gcc/ada/libgnat/g-cstyin.adb
+++ b/gcc/ada/libgnat/g-cstyin.adb
@@ -30,14 +30,17 @@
 ------------------------------------------------------------------------------
 
 with System; use System;
+with System.Storage_Elements; use System.Storage_Elements;
 with Interfaces.C; use Interfaces.C;
-with Interfaces.C.Pointers;
 with Interfaces.C.Extensions; use Interfaces.C.Extensions;
 with Interfaces.C.Strings; use Interfaces.C.Strings;
 with Ada.Unchecked_Conversion;
 
 package body GNAT.CPP.Std.Type_Info is
 
+   function strcmp (L, R : chars_ptr) return Interfaces.C.int;
+   pragma Import (Intrinsic, strcmp, "__builtin_strcmp");
+
    function Name_Starts_With_Asterisk (this : access constant type_info'Class)
                                        return Boolean;
 
@@ -46,35 +49,27 @@ package body GNAT.CPP.Std.Type_Info is
 
    function To_Address is
       new Ada.Unchecked_Conversion (chars_ptr, System.Address);
-
-   type Char_Arr is array (Natural range <>) of aliased char;
-   package CharPtr is
-      new Interfaces.C.Pointers (Natural, char, Char_Arr, nul);
-   type Char_Pointer is new CharPtr.Pointer;
-
    function To_Pointer is
-      new Ada.Unchecked_Conversion (chars_ptr, Char_Pointer);
-   function To_chars_ptr is
-      new Ada.Unchecked_Conversion (Char_Pointer, chars_ptr);
+      new Ada.Unchecked_Conversion (System.Address, chars_ptr);
 
    function Name_Starts_With_Asterisk (this : access constant type_info'Class)
                                        return Boolean is
-      A : constant Address := To_Address (this.Raw_Name);
+      Addr : constant System.Address := To_Address (this.Raw_Name);
       C : aliased char;
-      for C'Address use A;
+      for C'Address use Addr;
    begin
       return C = '*';
    end Name_Starts_With_Asterisk;
 
    function Name_Past_Asterisk (this : access constant type_info'Class)
                                 return chars_ptr is
-      Addr : Char_Pointer := To_Pointer (this.Raw_Name);
+      Addr : System.Address := To_Address (this.Raw_Name);
    begin
       if this.Name_Starts_With_Asterisk then
-         Increment (Addr);
+         Addr := Addr + Storage_Offset (1);
       end if;
 
-      return To_chars_ptr (Addr);
+      return To_Pointer (Addr);
    end Name_Past_Asterisk;
 
    ------------
@@ -82,8 +77,8 @@ package body GNAT.CPP.Std.Type_Info is
    ------------
 
    function Name (this : access constant type_info'Class)
-                  return String
-   is (Value (this.Name_Past_Asterisk));
+                  return chars_ptr
+   is (this.Name_Past_Asterisk);
 
    --------------
    --  Before  --
@@ -92,10 +87,10 @@ package body GNAT.CPP.Std.Type_Info is
    function Before (this, that : access constant type_info'Class)
                     return       Boolean is
    begin
-      if this.Name_Starts_With_Asterisk
-        or else that.Name_Starts_With_Asterisk
+      if not this.Name_Starts_With_Asterisk
+        or else not that.Name_Starts_With_Asterisk
       then
-         return this.Name < that.Name;
+         return strcmp (this.Raw_Name, that.Raw_Name) < 0;
       end if;
 
       return To_Address (this.Raw_Name) < To_Address (that.Raw_Name);
@@ -116,7 +111,50 @@ package body GNAT.CPP.Std.Type_Info is
          return False;
       end if;
 
-      return this.Name = that.Name;
+      return strcmp (this.Raw_Name, that.Raw_Name) = 0;
    end Equals;
 
+   function Convert_Caught_Object (Choice, Except : access type_info'Class;
+                                   Thrown         : in out Address;
+                                   Lang           : Character)
+                                   return           Interfaces.C.C_bool;
+   pragma Export (Cpp, Convert_Caught_Object, "__gnat_convert_caught_object");
+   --  Convert the exception object at Thrown, under Lang convention,
+   --  from type Except to type Choice, adjusting Thrown as needed and
+   --  returning True, or returning False in case the conversion
+   --  fails.  This is called from raise-gcc, and it is placed here
+   --  rather than in GNAT.CPP_Exceptions to avoid dragging all that
+   --  in when the program doesn't use C++ exceptions.
+
+   ---------------------------
+   -- Convert_Caught_Object --
+   ---------------------------
+
+   function Convert_Caught_Object (Choice, Except : access type_info'Class;
+                                   Thrown         : in out Address;
+                                   Lang           : Character)
+                                   return           Interfaces.C.C_bool is
+   begin
+      if Choice.Equals (Except) then
+         return C_bool'(True);
+      end if;
+
+      if Lang = 'B' then
+         if Except.Is_Pointer_P then
+            declare
+               Thrown_Indirect : Address;
+               for Thrown_Indirect'Address use Thrown;
+            begin
+               Thrown := Thrown_Indirect;
+            end;
+         end if;
+
+         if Choice.Do_Catch (Except, Thrown, 1) then
+            return C_bool'(True);
+         end if;
+      end if;
+
+      return C_bool'(False);
+   end Convert_Caught_Object;
+
 end GNAT.CPP.Std.Type_Info;
diff --git a/gcc/ada/libgnat/g-cstyin.ads b/gcc/ada/libgnat/g-cstyin.ads
index 06ed9588d53..37dad4544f4 100644
--- a/gcc/ada/libgnat/g-cstyin.ads
+++ b/gcc/ada/libgnat/g-cstyin.ads
@@ -71,7 +71,7 @@ private package GNAT.CPP.Std.Type_Info is
    --  Reimplemented in Ada, using Ada types.
    function Name (this : access constant type_info'Class)
                   --  return Interfaces.C.Strings.chars_ptr;
-                  return String;
+                  return Interfaces.C.Strings.chars_ptr;
    --  pragma Import (CPP, Name, "_ZNKSt9type_info4nameEv");
    pragma Machine_Attribute (Name, "nothrow");
 
-- 
2.43.0

Reply via email to