aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sa_messages.ads
blob: c4483974984ba4636fc9adb1a2b5818650696bbe (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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
------------------------------------------------------------------------------
--                       C O D E P E E R / S P A R K                        --
--                                                                          --
--                     Copyright (C) 2015-2022, AdaCore                     --
--                                                                          --
-- This 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.  This software 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. See the GNU General Public --
-- License for  more details.  You should have  received  a copy of the GNU --
-- General  Public  License  distributed  with  this  software;   see  file --
-- COPYING3.  If not, go to http://www.gnu.org/licenses for a complete copy --
-- of the license.                                                          --
--                                                                          --
------------------------------------------------------------------------------

pragma Ada_2012;

with Ada.Containers;        use Ada.Containers;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package SA_Messages is

   --  This package can be used for reading/writing a file containing a
   --  sequence of static anaysis results. Each element can describe a runtime
   --  check whose outcome has been statically determined, or it might be a
   --  warning or diagnostic message. It is expected that typically CodePeer
   --  will do the writing and SPARK will do the reading; this will allow SPARK
   --  to get the benefit of CodePeer's analysis.
   --
   --  Each item is represented as a pair consisting of a message and an
   --  associated source location. Source locations may refer to a location
   --  within the expansion of an instance of a generic; this is represented
   --  by combining the corresponding location within the generic with the
   --  location of the instance (repeated if the instance itself occurs within
   --  a generic). In addition, the type Iteration_Id is intended for use in
   --  distinguishing messages which refer to a specific iteration of a loop
   --  (this case can arise, for example, if CodePeer chooses to unroll a
   --  for-loop). This data structure is only general enough to support the
   --  kinds of unrolling that are currently planned for CodePeer. For
   --  example, an Iteration_Id can only identify an iteration of the nearest
   --  enclosing loop of the associated File/Line/Column source location.
   --  This is not a problem because CodePeer doesn't unroll loops which
   --  contain other loops.

   type Message_Kind is (

      --  Check kinds

      Array_Index_Check,
      Divide_By_Zero_Check,
      Tag_Check,
      Discriminant_Check,
      Range_Check,
      Overflow_Check,
      Assertion_Check,

      --  Warning kinds

      Suspicious_Range_Precondition_Warning,
      Suspicious_First_Precondition_Warning,
      Suspicious_Input_Warning,
      Suspicious_Constant_Operation_Warning,
      Unread_In_Out_Parameter_Warning,
      Unassigned_In_Out_Parameter_Warning,
      Non_Analyzed_Call_Warning,
      Procedure_Does_Not_Return_Warning,
      Check_Fails_On_Every_Call_Warning,
      Unknown_Call_Warning,
      Dead_Store_Warning,
      Dead_Outparam_Store_Warning,
      Potentially_Dead_Store_Warning,
      Same_Value_Dead_Store_Warning,
      Dead_Block_Warning,
      Infinite_Loop_Warning,
      Dead_Edge_Warning,
      Plain_Dead_Edge_Warning,
      True_Dead_Edge_Warning,
      False_Dead_Edge_Warning,
      True_Condition_Dead_Edge_Warning,
      False_Condition_Dead_Edge_Warning,
      Unrepeatable_While_Loop_Warning,
      Dead_Block_Continuation_Warning,
      Local_Lock_Of_Global_Object_Warning,
      Analyzed_Module_Warning,
      Non_Analyzed_Module_Warning,
      Non_Analyzed_Procedure_Warning,
      Incompletely_Analyzed_Procedure_Warning);

   --  Assertion_Check includes checks for user-defined PPCs (both specific
   --  and class-wide), Assert pragma checks, subtype predicate checks,
   --  type invariant checks (specific and class-wide), and checks for
   --  implementation-defined assertions such as Assert_And_Cut, Assume,
   --  Contract_Cases, Default_Initial_Condition, Initial_Condition,
   --  Loop_Invariant, Loop_Variant, Refined_Post, and Subprogram_Variant.
   --
   --  It might be nice to distinguish these different kinds of assertions
   --  as is done in SPARK's VC_Kind enumeration type, but any distinction
   --  which isn't already present in CP's BE_Message_Subkind enumeration type
   --  would require more work on the CP side.
   --
   --  The warning kinds are pretty much a copy of the set of
   --  Be_Message_Subkind values for which CP's Is_Warning predicate returns
   --  True; see descriptive comment for each in CP's message_kinds.ads .

   subtype Check_Kind is Message_Kind
     range Array_Index_Check .. Assertion_Check;
   subtype Warning_Kind is Message_Kind
     range Message_Kind'Succ (Check_Kind'Last) .. Message_Kind'Last;

   --  Possible outcomes of the static analysis of a runtime check
   --
   --  Not_Statically_Known_With_Low_Severity could be used instead of of
   --  Not_Statically_Known if there is some reason to believe that (although
   --  the tool couldn't prove it) the check is likely to always pass (in CP
   --  terms, if the corresponding CP message has severity Low as opposed to
   --  Medium). It's not clear yet whether SPARK will care about this
   --  distinction.

   type SA_Check_Result is
     (Statically_Known_Success,
      Not_Statically_Known_With_Low_Severity,
      Not_Statically_Known,
      Statically_Known_Failure);

   type SA_Message (Kind : Message_Kind := Message_Kind'Last) is record
      case Kind is
         when Check_Kind =>
            Check_Result : SA_Check_Result;

         when Warning_Kind =>
            null;
      end case;
   end record;

   type Source_Location_Or_Null (<>) is private;
   Null_Location : constant Source_Location_Or_Null;
   subtype Source_Location is Source_Location_Or_Null with
     Dynamic_Predicate => Source_Location /= Null_Location;

   type Line_Number is new Positive;
   type Column_Number is new Positive;

   function File_Name (Location : Source_Location) return String;
   function File_Name (Location : Source_Location) return Unbounded_String;
   function Line      (Location : Source_Location) return Line_Number;
   function Column    (Location : Source_Location) return Column_Number;

   type Iteration_Kind is (None, Initial, Subsequent, Numbered);
   --  None is for the usual no-unrolling case.
   --  Initial and Subsequent are for use in the case where only the first
   --  iteration of a loop (or some part thereof, such as the termination
   --  test of a while-loop) is unrolled.
   --  Numbered is for use in the case where a for-loop with a statically
   --  known number of iterations is fully unrolled.

   subtype Iteration_Number is Integer range 1 .. 255;
   subtype Iteration_Total  is Integer range 2 .. 255;

   type Iteration_Id (Kind : Iteration_Kind := None) is record
      case Kind is
         when Numbered =>
            Number   : Iteration_Number;
            Of_Total : Iteration_Total;
         when others =>
            null;
      end case;
   end record;

   function Iteration (Location : Source_Location) return Iteration_Id;

   function Enclosing_Instance
     (Location : Source_Location) return Source_Location_Or_Null;
   --  For a source location occurring within the expansion of an instance of a
   --  generic unit, the Line, Column, and File_Name selectors will indicate a
   --  location within the generic; the Enclosing_Instance selector yields the
   --  location of the declaration of the instance.

   function Make
     (File_Name : String;
      Line      : Line_Number;
      Column    : Column_Number;
      Iteration : Iteration_Id;
      Enclosing_Instance : Source_Location_Or_Null) return Source_Location;
   --  Constructor

   type Message_And_Location (<>) is private;

   function Location (Item : Message_And_Location) return Source_Location;
   function Message (Item : Message_And_Location) return SA_Message;

   function Make_Msg_Loc
     (Msg : SA_Message;
      Loc : Source_Location) return Message_And_Location;
   --  Selectors

   function "<" (Left, Right : Message_And_Location) return Boolean;
   function Hash (Key : Message_And_Location) return Hash_Type;
   --  Actuals for container instances

   File_Extension : constant String; -- ".json" (but could change in future)
   --  Clients may wish to use File_Extension in constructing
   --  File_Name parameters for calls to Open.

   package Writing is
      function Is_Open return Boolean;

      procedure Open (File_Name : String) with
        Precondition  => not Is_Open,
        Postcondition => Is_Open;
      --  Behaves like Text_IO.Create with respect to error cases

      procedure Write (Message : SA_Message; Location : Source_Location);

      procedure Close with
        Precondition  => Is_Open,
        Postcondition => not Is_Open;
      --  Behaves like Text_IO.Close with respect to error cases
   end Writing;

   package Reading is
      function Is_Open return Boolean;

      procedure Open (File_Name : String; Full_Path : Boolean := True) with
        Precondition  => not Is_Open,
        Postcondition => Is_Open;
      --  Behaves like Text_IO.Open with respect to error cases

      function Done return Boolean with
        Precondition => Is_Open;

      function Get return Message_And_Location with
        Precondition => not Done;

      procedure Close with
        Precondition  => Is_Open,
        Postcondition => not Is_Open;
      --  Behaves like Text_IO.Close with respect to error cases
   end Reading;

private
   type Simple_Source_Location is record
      File_Name : Unbounded_String := Null_Unbounded_String;
      Line      : Line_Number      := Line_Number'Last;
      Column    : Column_Number    := Column_Number'Last;
      Iteration : Iteration_Id     := (Kind => None);
   end record;

   type Source_Locations is
     array (Natural range <>) of Simple_Source_Location;

   type Source_Location_Or_Null (Count : Natural) is record
      Locations : Source_Locations (1 .. Count);
   end record;

   Null_Location : constant Source_Location_Or_Null :=
                     (Count => 0, Locations => (others => <>));

   type Message_And_Location (Count : Positive) is record
      Message  : SA_Message;
      Location : Source_Location (Count => Count);
   end record;

   File_Extension : constant String := ".json";
end SA_Messages;