-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset 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. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY 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 the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

separate (ErrorHandler.Conversions.ToString)
procedure WarningWithPosition (Err_Num          : in     Error_Types.NumericError;
                               With_Explanation : in     Boolean;
                               E_Str            : in out E_Strings.T) is

   procedure WarningWithPositionExpl (E_Str : in out E_Strings.T)
   --# global in Err_Num;
   --# derives E_Str from *,
   --#                    Err_Num;
      is separate;
   -- Note that the parameter names for this subunit are chosen to make it as easy as
   --      possible to auto-generate the subunit from this, its parent, file.  The
   --      generation requires copying the case statement below, stripping out the
   --      current Append'Thing' statements and adding an AppendString for the
   --      explanatory text that is delineated by --! comments.

   procedure Append_Explanation
   --# global in     Err_Num;
   --#        in     With_Explanation;
   --#        in out E_Str;
   --# derives E_Str from *,
   --#                    Err_Num,
   --#                    With_Explanation;
   is
      Explanation_String : E_Strings.T := E_Strings.Empty_String;
   begin
      if With_Explanation then
         -- we need to at least look for an explanation
         WarningWithPositionExpl (Explanation_String);
         if E_Strings.Get_Length (E_Str => Explanation_String) > 0 then
            -- there actually is one
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => ErrorHandler.Explanation_Prefix);
            E_Strings.Append_Examiner_String (E_Str1 => E_Str,
                                              E_Str2 => Explanation_String);
            E_Strings.Append_String (E_Str => E_Str,
                                     Str   => ErrorHandler.Explanation_Postfix);
         end if;
      end if;
   end Append_Explanation;

begin

   -- HTML Directives
   --! <NameFormat> <"warning-"><Name>
   --! <ErrorFormat> <"--- Warning : "><Name><" : "><Error>

   case Err_Num.ErrorNum is

      when 1 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The identifier ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is either undeclared or not visible at this point");
         --! This warning will appear against an identifier in a with clause if
         --! it is not also present in an inherit clause. Such an identifier
         --! cannot be used in any non-hidden part of
         --! a SPARK program. The use of with without inherit is permitted to
         --! allow reference in hidden
         --! parts of the text to imported packages which are not legal SPARK.
         --! For example, the body of
         --! SPARK_IO is hidden and implements the exported operations of the
         --! package by use of package
         --! TEXT_IO. For this reason TEXT_IO must appear in the with clause of
         --! SPARK_IO. (warning control file keyword:<b> with_clauses</b>)

      when 2 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Representation clause - ignored by the Examiner");
         --! The significance of representation clauses cannot be assessed by the
         --! Examiner because
         --! it depends on the specific memory architecture of the target system.
         --! Like pragmas,
         --! representation clauses can change the meaning of a SPARK program and
         --! the warning
         --! highlights the need to ensure their correctness by other means.
         --! (warning control file
         --! keyword:<b> representation_clauses</b>)

      when 3 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Pragma - ignored by the Examiner");
         --! All pragmas encountered by the Examiner generate this warning.
         --! While many pragmas (e.g.
         --! pragma page) are harmless others can change a program's meaning,
         --! for example by causing
         --! two variables to share a single memory location.
         --! (warning control file keyword:<b> pragma</b>
         --! pragma_identifier or <b>pragma all</b>)

      when 4 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "declare annotation - ignored by the Examiner");
         --! The declare annotation is ignored by the Examiner if the profile
         --! is not Ravenscar. (warning control file keyword: <b>declare_annotations</b>)

      when 5 =>
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " contains interrupt handlers; it is important that an interrupt identifier is " &
              "not used by more than one handler");
         --! Interrupt identifiers are implementation defined and the Examiner cannot check that values are
         --! used only once.  Duplication can occur by declaring more than object of a single (sub)type where
         --! that type defines handlers.  It may also occur if interrupt identifiers are set via discriminants
         --! and two or more actual discriminants generate the same value.
         --! (warning control file keyword: <b>interrupt_handlers</b>)

      when 6 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Machine code insertion.  Code insertions are ignored by the Examiner");
         --! Machine code is inherently implementation dependent and cannot be analysed
         --! by the Examiner.  Users are responsible for ensuring that the behaviour
         --! of the inserted machine code matches the annotation of the subprogram containing it.

      when 7 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This identifier is an Ada2005 reserved word");
         --! Such identifiers will be rejected by an Ada2005 compiler and by the SPARK
         --! Examiner for SPARK2005. It is recommended to rename
         --! such identifiers for future upward compatibility.
         --! (warning control file keyword: <b>ada2005_reserved_words</b>)

      when 11 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Unnecessary others clause - case statement is already complete");
         --! The others clause is non-executable because all case choices have
         --! already been
         --! covered explicitly.  If the range of the case choice is altered later
         --! then the
         --! others clause may be executed with unexpected results.  It is better
         --! to omit the
         --! others clause in which case any extension of the case range will result in a
         --! compilation error.

      when 12 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is an instantiation of Unchecked_Conversion");
         --! See ALRM 13.9.  The use of Unchecked_Conversion can result in implementation-defined
         --! values being returned.  The function should be used with great care.  The principal
         --! use of Unchecked_Conversion is SPARK programs is the for the reading of external ports
         --! prior to performing a validity check; here the suppression of constraint checking prior
         --! to validation is useful.  The Examiner does not assume that the value returned by
         --! an unchecked conversion is valid and so unprovable run-time check VCs will result if
         --! a suitable validity check is not carried out before the value is used.
         --! (warning control file keyword: <b>unchecked_conversion</b>)

      when 13 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " is an instantiation of Unchecked_Conversion returning a type for which run-time checks" &
              " are not generated.  Users must take steps to ensure the validity of the returned value");
         --! See ALRM 13.9.  The use of Unchecked_Conversion can result in invalid
         --! values being returned.  The function should be used with great care especially, as in
         --! this case, where the type returned does not generate Ada run-time checks nor SPARK
         --! run-time verification conditions.  For such types, this warning is the ONLY reminder
         --! the Examiner generates that the generated value may have an invalid representation.
         --! For this reason the warning is NOT suppressed by the warning control file keyword
         --! unchecked_conversion.
         --! The principal use of Unchecked_Conversion is SPARK programs is the for the reading of external ports
         --! prior to performing a validity check; here the suppression of constraint checking prior
         --! to validation is useful.

         -- Warnings associated with the justification mechanism
      when 120 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Unexpected unmatched 'end accept' annotation ignored");
         --! This end accept annotation does not match any preceding start accept in this unit.

      when 121 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "No warning message matches this accept annotation");
         --! The accept annotation is used to indicate that a particular flow error or semantic warning
         --! message is expected and can be justified.  This error indicates that the expected message
         --! did not actually occur.  Note that when matching any information flow error messages containing
         --! two variable names, the export should be placed first and the import second (the order
         --! in the error message may differ from this depending on the style of information flow
         --! error reporting selected).  For example: --# accept Flow, 601, X, Y, &quot;...&quot;; justifies
         --! the message: &quot;X may be derived from the imported value(s) of Y&quot; or the alternative
         --! form: &quot;Y may be used in the derivation of X&quot;.

      when 122 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "Maximum number of error or warning justifications reached, subsequent accept annotations will be ignored");
         --! The number of justifications per source file is limited.  If you reach this limit
         --! it is worth careful consideration of why the code generates so many warnings.

         -- end of warnings associated with justification mechanism

      when 169 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Direct update of own variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => ", which is an own variable of a non-enclosing package");
         --! With the publication of Edition 3.1 of the SPARK Definition the
         --! previous restriction
         --! prohibiting the direct updating of own variables of non-enclosing
         --! packages was removed; however, the preferred use of packages as
         --! abstract state machines is compromised by such action which is
         --! therefore discouraged. (warning control file keyword:<b> direct_updates</b>)

      when 200 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This static expression cannot be evaluated by the Examiner");
         --! Issued if a static expression exceeds the internal limits of the Examiner
         --! because its
         --! value is, for example, too large to be evaluated using infinite precision
         --! arithmetic. No
         --! value will be recorded for the expression and this may limit the
         --! Examiner's ability to
         --! detect certain sorts of errors such as numeric constraints.
         --! (warning control file keyword: <b>static_expressions</b>)

      when 201 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "This expression cannot be evaluated statically because its value may be implementation-defined");
         --! Raised, for example, when evaluating 'Size of a type
         --! that does not have an explicit Size representation clause.
         --! Attributes of implementation-defined types, such as
         --! Integer'Last may also be
         --! unknown to be Examiner if they are not specified in the
         --! configuration file
         --! (warning control file keyword: <b>static_expressions</b>)

      when 202 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "An arithmetic overflow has occurred. Constraint checks have not been performed");
         --! Raised when comparing two real numbers. The examiner cannot deal
         --! with real numbers specified to
         --! such a high degree of precision. Consider reducing the precision
         --! of these numbers.

      when 300 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "VCs cannot be built for multi-dimensional array aggregates");
         --! Issued when an aggregate of a multi-dimensional array is found.
         --! Suppresses generation
         --! of VCs for that subprogram. Can be worked round by using
         --! arrays of arrays.

      when 301 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Called subprogram exports abstract types for which RTCs are not possible");

      when 302 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "This expression may be re-ordered by a compiler. Add parentheses to remove ambiguity");
         --! Issued when a potentially re-orderable expression is encountered.
         --! For example x := a + b + c; Whether
         --! intermediate sub-expression values overflow may depend on the
         --! order of evaluation which is
         --! compiler-dependent.
         --! Therefore, code generating this warning should be parenthesized to
         --! remove the ambiguity.
         --! e.g. x := (a + b) + c;

      when 303 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Overlapping choices may not be detected");
         --! Issued where choices in an array aggregate or case statement are
         --! outside the range
         --! which can be detected because of limits on the size of a table
         --! internal to the Examiner.

      when 304 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Case statement may be incomplete");
         --! Issued when the Examiner cannot determine the completeness of a
         --! case statement because
         --! the bounds of the type of the controlling expression exceed the
         --! size of the internal table
         --! used to perform the checks.

      when 305 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Value too big for internal representation");
         --! Issued when the Examiner cannot determine the completeness of an
         --! array aggregate or
         --! case statement because the number used in a choice exceed the size
         --! allowed in the internal
         --! table used to perform the checks.

      when 306 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Aggregate may be incomplete");
         --! Issued when the Examiner cannot determine the completeness of an
         --! array aggregate
         --! because its bounds exceed the size of the internal table used to
         --! perform the checks.

      when 307 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Completeness checking incomplete: index type(s) undefined or not discrete");
         --! Issued where the array index (sub)type is inappropriate: this is
         --! probably because there
         --! is an error in its definition, which will have been indicated by
         --! a previous error message.

      when 308 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Use of equality operator with floating point type");
         --! The use of this operator is discouraged in SPARK because of the
         --! difficulty in
         --! determining exactly what it means to say that two instances of a
         --! floating point number are
         --! equal

      when 309 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Type conversion to own type, consider using type qualification instead");
         --! Issued where a type conversion is either converting from a (sub)type
         --! to the same
         --! (sub)type or is converting between two subtypes of the same type.
         --! In the former case the
         --! type conversion may be safely removed because no constraint check
         --! is required; in the
         --! latter case the type conversion may be safely replaced by a type
         --! qualification which
         --! preserves the constraint check.(warning control file keyword:<b>
         --! type_conversions</b>)

      when 310 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Use of obsolescent Ada 83 language feature");
         --! Issued when a language feature defined by Ada 95 to be obsolescent is
         --! used.  Use of such
         --! features is not recommended because compiler support for them cannot
         --! be guaranteed.(warning control file keyword:<b>obsolescent_features</b>)

      when 311 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Priority pragma for ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is unavailable and has not been considered in the ceiling priority check");

      when 312 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Replacement rules cannot be built for multi-dimensional array constant ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         --! Issued when a VC or PF references a multi-dimensional array constant.
         --! Can be worked round by using arrays of arrays.

      when 313 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The constant ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " has semantic errors in its initializing expression or has " &
              "a hidden completion which prevent generation of a replacement rule");
         --! Issued when replacement rules are requested for a composite constant which
         --! had semantic errors in its initializing expression, or is
         --! a deferred constant whose completion is hidden from the Examiner.
         --! Semantic errors must be eliminated before replacement rules can be generated.

      when 314 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The constant ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " has semantic errors in its type which prevent generation of rules");
         --! Issued when an attempt is made to generate type deduction rules for a constant
         --! which has semantic errors in its type.  These semantic errors
         --! must be eliminated before type deduction rules can be generated.

      when 315 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The procedure ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " does not have a derives annotation. The analysis of this call assumes " &
              "that each of its exports is derived from all of its imports");
         --! Issued in flow=auto mode when a function calls a procedure that does not have a
         --! derives annotation. In most cases this assumption will not affect
         --! the validity of the analysis, but if the called procedure derives
         --! null from an import this can have an impact. Note that functions
         --! are considered to have implicit derives annotations so this warning
         --! is not issued for calls to functions.

      when 320 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The proof function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " has a non-boolean return and a return annotation. Please make sure " &
              "that the return is always in-type");
         --! Any proof function with a non-bool return can introduce unsoundness if
         --! the result could overflow. For example a return of (x + 1) is not ok if
         --! x can take the value of integer'last.
         --! (warning control file keyword: <b>proof_function_non_boolean</b>)

      when 321 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The proof function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " has an implicit return annotation. Please be careful not to introduce unsoundness");
         --! Any proof function with an implicit return can easily introduce
         --! unsoundness as they do not have a body which we can check to
         --! expose any contradictions. For example: return B => False.
         --! (warning control file keyword: <b>proof_function_implicit</b>)

      when 322 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The return refinement for proof function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " is assumed to hold as it is axiomatic and thus cannot be checked");
         --! (warning control file keyword: <b>proof_function_refinement</b>)

      when 323 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The precondition refinement for proof function ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " is assumed to hold as it is axiomatic and thus cannot be checked");
         --! (warning control file keyword: <b>proof_function_refinement</b>)

      when 350 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Unexpected pragma Import.  Variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is not identified as an external (stream) variable");
         --! The presence of a pragma Import makes it possible that the variable
         --! is connected
         --! to some external device.  The behaviour of such variables is best
         --! captured by
         --! making them moded own variables (or &quot;stream&quot; variables).  If variables
         --! connected
         --! to the external environment are treated as if they are normal program
         --! variables then
         --! misleading analysis results are inevitable.  The use of pragma Import on local
         --! variables of subprograms is particularly deprecated. The warning
         --! may safely be
         --! disregarded if the variable is not associated with memory-mapped
         --! input/output
         --! or if the variable concerned is an own variable and the operations on it are
         --! suitably annotated to indicate volatile, stream-like behaviour.
         --! Where pragma Import is used, it is essential that the variable is properly
         --! initialized at the point from which it is imported.
         --! (warning control file keyword:<b>imported_objects</b>)

      when 351 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Unexpected address clause. ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is a constant");
         --! Great care is needed when attaching an address clause to a constant.  The use
         --! of such a clause is safe if, and only if, the address supplied provides a valid
         --! value for the constant which does not vary during the execution life of the program,
         --! for example, mapping the constant to PROM data.
         --! If the address clause causes the constant to have a value which may alter, or worse,
         --! change dynamically under the influence of some device external to the program, then
         --! misleading or incorrect analysis is certain to result.
         --! If the intention is to create an input port of some kind, then a constant should not
         --! be used.  Instead a moded own variable (or &quot;stream&quot; variables) should be used.
         --! (warning control file keyword:<b> address_clauses</b>)

      when 360 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have zero or one arguments");

      when 361 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have exactly one argument");

      when 362 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have exactly two arguments");

      when 363 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have at least one argument");

      when 364 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have between two and four arguments");

      when 365 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have exactly zero arguments");

      when 366 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "This pragma must have one or two arguments");

      when 380 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Casing inconsistent with declaration. Expected casing is ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);

         --! The Examiner checks the case used for an identifier against the
         --! declaration of that identifier and warns if they do not match.
         --! (warning control file keyword:<b>style_check_casing</b>)

      when 389 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "Generation of VCs for consistency of generic and instantiated subprogram constraints " &
              "is not yet supported. It will be supported in a future release of the Examiner");

      when 390 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "This generic subprogram has semantic errors in its declaration which prevent instantiations of it");
         --! Issued to inform the user that a generic subprogram instantiation
         --! cannot be completed because of earlier errors in the generic declaration.

      when 391 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "If the identifier ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " represents a package which " &
              "contains a task or an interrupt handler then the partition-level " &
              "analysis performed by the Examiner " &
              "will be incomplete.  Such packages must be inherited as well as withed");

      when 392 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "External variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " may have an invalid representation and its assignment may " &
              "cause a run-time exception which is outside the scope of " &
              "the absence of RTE proof");
         --! Where values are read from external variables (i.e. variables
         --! connected to the external
         --! environment) there is no guarantee that the bit pattern read will
         --! be a valid representation for
         --! the type of the external variable.  Unexpected behaviour may result
         --! if invalid values are used in expressions.
         --! If the code is compiled with Ada run-time checks enabled the
         --! assignment of an invalid value may (but need not) raise a
         --! run-time exception dependent on the compiler.
         --! A compiler may provide facilities to apply extended checking
         --! which may also raise a run-time exception if an invalid value is used.
         --! The SPARK Toolset does not check the validity of the external variable
         --! and therefore any possible exception arising from its assignment is
         --! outside the scope of proof of absence of RTE.
         --! To ensure that a run-time exception cannot occur make the type of
         --! the external variable such that any possible bit pattern that
         --! may be read from the external source is a valid value.
         --! If the desired type is such a type then the always_valid assertion
         --! may be applied to the external variable; otherwise use explicit tests
         --! to ensure it has a valid value for the desired type before converting
         --! to an object of the desired type.
         --! In SPARK 95 the 'Valid attribute (see ALRM 13.9.2) may be used to
         --! determine the validity of a value if it can be guaranteed that the
         --! assignment of an invalid value read from an external variable will
         --! not raise a run time exception, either by compiling the code with
         --! checks off or by ensuring the compiler does not apply constraint
         --! checks when assigning same subtype objects.
         --! Note that when the Examiner is used to generate run-time checks, it
         --! will not be possible to discharge those involving external variables
         --! unless one of the above steps is taken.
         --! More information on interfacing can be found in the INFORMED manual
         --! and the SPARK Proof Manual.
         --! (warning control file
         --! keyword:<b> external_assignment</b>)

      when 393 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "External variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " may have an invalid representation and is of a type for which run-time checks " &
              "are not generated but its assignment may cause a run-time exception.  " &
              "Users must take steps to ensure the validity of the " &
              "assigned or returned value");
         --! Where values are read from external variables (i.e. variables
         --! connected to the external
         --! environment) there is no guarantee that the bit pattern read will
         --! be a valid representation for
         --! the type of the external variable.  Unexpected behaviour may result
         --! if invalid values are used in expressions.
         --! If the code is compiled with Ada run-time checks enabled the
         --! assignment of an invalid value may (but need not) raise a
         --! run-time exception dependent on the compiler.
         --! A compiler may provide facilities to apply extended checking
         --! which may also raise a run-time exception if an invalid value is used
         --! The SPARK Toolset does not check the validity of the external variable
         --! and therefore any possible exception arising from its assignment is
         --! outside the scope of proof of absence of RTE.
         --! Where, as in this case, the type is one for which
         --! Ada run-time checks need not be generated and SPARK run-time
         --! verification conditions are not generated, extra care is required.
         --! For such types, this warning is the ONLY reminder
         --! the Examiner generates that the external value may have an invalid
         --! representation.
         --! For this reason the warning is NOT suppressed by the warning
         --! control file keyword <b> external_assignment</b>.
         --! To ensure that a run-time exception cannot occur make the type of
         --! the external variable such that any possible bit pattern that
         --! may be read from the external source is a valid value.
         --! Explicit tests of the value may then be used to determine the
         --! value of an object of the desired type.
         --! In SPARK 95 the 'Valid attribute (see ALRM 13.9.2) may be used to
         --! determine the validity of a value if it can be guaranteed that the
         --! assignment of an invalid value read from an external variable will
         --! not raise a run time exception, either by compiling the code with
         --! checks off or by ensuring the compiler does not apply constraint
         --! checks when assigning same subtype objects.
         --! Boolean external variables require special care since the Examiner
         --! does not generate run-time checks
         --! for Boolean variables; use of 'Valid is essential when reading
         --! Boolean external variables.
         --! More information on interfacing can be found in the INFORMED manual
         --! and the SPARK Proof Manual.

      when 394 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Variables of type ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " cannot be initialized using the facilities of this package");
         --! A variable of a private type can only be used (without generating
         --! a data flow error) if there is some way of
         --! giving it an initial value.  For a limited private type only a
         --! procedure that has an export of that type
         --! and no imports of that type is suitable.  For a private type either
         --! a procedure, function or (deferred)
         --! constant is required.  The required facility may be placed in, or
         --! already available in, a public
         --! child package.
         --! (warning control file keyword:<b> private_types</b>)

      when 395 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => " is an external (stream) variable but does not have an address clause or a pragma import");
         --! When own variables are given modes they are considered to be inputs
         --! from or outputs
         --! to the external environment.  The Examiner regards them as being
         --! volatile (i.e. their
         --! values can change in ways not visible from an inspection of the
         --! source code).  If
         --! a variable is declared in that way but it is actually an ordinary
         --! variable which is NOT
         --! connected to the environment then misleading analysis is inevitable.
         --! The Examiner
         --! expects to find an address clause or pragma import for variables of this kind to
         --! indicate that they
         --! are indeed memory-mapped input/output ports.  This warning is issued
         --! if an address
         --! clause or pragma import is not found.

      when 396 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Unexpected address clause.  Variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " is not identified as an external (stream) variable");
         --! The presence of an address clause makes it possible that the variable
         --! is connected
         --! to some external device.  The behaviour of such variables is best
         --! captured by
         --! making them moded own variables (or &quot;stream&quot; variables).  If variables
         --! connected
         --! to the external environment are treated as if they are normal program
         --! variables then
         --! misleading analysis results are inevitable.  The use of address clauses
         --! on local
         --! variables of subprograms is particularly deprecated. The warning
         --! may safely be
         --! disregarded if the variable is not associated with memory-mapped
         --! input/output
         --! or if the variable concerned is an own variable and the operations on it are
         --! suitably annotated to indicate volatile, stream-like behaviour.
         --! (warning control file keyword:<b> address_clauses</b>)

      when 397 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "Variables of type ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " can never be initialized before use");
         --! A variable of a private type can only be used (without generating a data
         --! flow error) if there is some way of
         --! giving it an initial value.  For a limited private type only a procedure
         --! that has an export of that type
         --! and no imports of that type is suitable.  For a private type either a
         --! procedure, function or (deferred)
         --! constant is required.

      when 398 =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "The own variable ");
         Append_Name (E_Str => E_Str,
                      Name  => Err_Num.Name1,
                      Scope => Err_Num.Scope);
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => " can never be initialized before use");
         --! The own variable can only be used (without generating a data flow error)
         --! if there is some way of
         --! giving it an initial value.  If it is
         --! initialized during package elaboration (or implicitly by the environment
         --!  because it represents an
         --! input port) it should be placed in an &quot;initializes&quot; annotation.
         --! Otherwise there needs to be some way
         --! of assigning an initial value during program execution.  Either the own
         --! variable needs to be declared
         --! in the visible part of the package so that a direct assignment can be
         --! made to it or, more usually, the
         --! package must declare at least one procedure for which the own variable
         --! is an export but not an import.
         --! Note that if the own variable is an abstract own variable with some
         --! constituents initialized
         --! during elaboration and some during program execution then it will never
         --! be possible correctly to
         --! initialize it; such abstract own variables must be divided into separate
         --! initialized and uninitialized
         --! components.

      when 399 =>
         E_Strings.Append_String
           (E_Str => E_Str,
            Str   => "The called subprogram has semantic errors in its interface " &
              "(parameters and/or " &
              "annotations) which prevent flow analysis of this call");
         --! Issued to inform the user that flow analysis has been suppressed
         --! because of the error in the called subprogram's interface.

      when others =>
         E_Strings.Append_String (E_Str => E_Str,
                                  Str   => "UNKNOWN ERROR NUMBER PASSED TO WarningWithPosition");

   end case;

   Append_Explanation;
   E_Strings.Append_String (E_Str => E_Str,
                            Str   => ".");
end WarningWithPosition;
