aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat/g-cstyin.adb
blob: 9d88c3fc255494c819a3c82d5e9d463d6ff5c60e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
------------------------------------------------------------------------------
--                                                                          --
--                         GNAT RUN-TIME COMPONENTS                         --
--                                                                          --
--               G N A T . C P P . S T D . T Y P E _ I N F O                --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--                     Copyright (C) 2022-2025, AdaCore                     --
--                                                                          --
-- 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- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- 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; use System;
with System.Storage_Elements; use System.Storage_Elements;
with Interfaces.C; use Interfaces.C;
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;

   function Name_Past_Asterisk (this : access constant type_info'Class)
                                return chars_ptr;

   function To_Address is
      new Ada.Unchecked_Conversion (chars_ptr, System.Address);
   function To_Pointer is
      new Ada.Unchecked_Conversion (System.Address, chars_ptr);

   function Name_Starts_With_Asterisk (this : access constant type_info'Class)
                                       return Boolean is
      Addr : constant System.Address := To_Address (this.Raw_Name);
      C : aliased char;
      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 : System.Address := To_Address (this.Raw_Name);
   begin
      if this.Name_Starts_With_Asterisk then
         Addr := Addr + Storage_Offset (1);
      end if;

      return To_Pointer (Addr);
   end Name_Past_Asterisk;

   ------------
   --  Name  --
   ------------

   function Name (this : access constant type_info'Class)
                  return chars_ptr
   is (this.Name_Past_Asterisk);

   --------------
   --  Before  --
   --------------

   function Before (this, that : access constant type_info'Class)
                    return       Boolean is
   begin
      if not this.Name_Starts_With_Asterisk
        or else not that.Name_Starts_With_Asterisk
      then
         return strcmp (this.Raw_Name, that.Raw_Name) < 0;
      end if;

      return To_Address (this.Raw_Name) < To_Address (that.Raw_Name);
   end Before;

   --------------
   --  Equals  --
   --------------

   function Equals (this, that : access constant type_info'Class)
                    return       Boolean is
   begin
      if this = that then
         return True;
      end if;

      if this.Name_Starts_With_Asterisk then
         return False;
      end if;

      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;