-------------------------------------------------------------------------------
-- (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 (Sem)
procedure Check_Suspendable_Property_Consistency
  (Sym                 : in     Dictionary.Symbol;
   Type_Sym            : in     Dictionary.Symbol;
   Is_In_Suspends_List : in     Boolean;
   Error_Node_Pos      : in     LexTokenManager.Token_Position;
   Consistent          :    out Boolean)
is

   The_Error : Natural := 0;

   function Type_Is_Suspendable (Type_Sym : Dictionary.Symbol) return Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   is
   begin
      -- To suspend the type must be a protected type with an entry or
      -- a suspension object type.
      return (Dictionary.IsProtectedTypeMark (Type_Sym)
                and then Dictionary.GetProtectedTypeHasEntry (Dictionary.GetRootType (Type_Sym)))
        or else Dictionary.IsPredefinedSuspensionObjectType (Type_Sym);
   end Type_Is_Suspendable;

begin -- Check_Suspendable_Property_Consistency
   if Is_In_Suspends_List then
      if not (Dictionary.IsOwnVariable (Sym) or else Dictionary.IsConstituent (Sym)) then
         -- We have an entry in a suspends list that it not being applied
         -- to an own variable.
         The_Error := 924;
      elsif Dictionary.IsOwnVariable (Sym) and then not Dictionary.GetOwnVariableProtected (Sym) then
         -- The own variable is not protected and hence cannot suspend.
         The_Error := 924;
      elsif (Dictionary.Is_Declared (Item => Type_Sym) or else Dictionary.IsPredefined (Type_Sym))
        and then not Type_Is_Suspendable (Type_Sym => Type_Sym) then
         -- We have a protected own variable whose type we know cannot suspend.
         The_Error := 924;
      end if;
   elsif Dictionary.IsOwnVariable (Sym)
     and then Dictionary.GetOwnVariableProtected (Sym)
     and then Type_Is_Suspendable (Type_Sym => Type_Sym) then
      -- We are declaring an object that can suspend but does not have a
      -- suspendable property declared in the own variable annotation.
      The_Error := 889;
   end if;
   if The_Error /= 0 then
      ErrorHandler.Semantic_Error
        (Err_Num   => The_Error,
         Reference => ErrorHandler.No_Reference,
         Position  => Error_Node_Pos,
         Id_Str    => Dictionary.GetSimpleName (Sym));
   end if;
   Consistent := The_Error = 0;
end Check_Suspendable_Property_Consistency;
