Ada:违反“No_Exception_Propagation” - 第2部分

时间:2017-02-15 23:17:26

标签: ada

我有以下代码将两个字节组合成一个字节数组:

pragma Restrictions (No_Exception_Propagation);

with Interfaces; use Interfaces;

procedure No_Propagation is
   type Byte is new Unsigned_8;
   type Byte_Array is array (Natural range <>) of Byte;

   function Concat (Input_1 : Byte;
                    Input_2 : Byte)
                    return Byte_Array
   is
      Null_Array : Byte_Array (1 .. 0);
   begin
      declare
         Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2);
      begin
         return Output;
      exception
         when Constraint_Error =>
            return Null_Array;
      end;
   end Concat;

   A, B : Byte;
begin
   A := 5;
   B := 0;
   declare
      C : Byte_Array := Concat(A, B);
   begin
      null;
   end;
end No_Propagation;

当我用以下代码编译时:

gnatmake -gnatw.e no_propagation.adb

我收到以下警告:

no_propagation.adb:16:66: warning: pragma Restrictions (No_Exception_Propagation) in effect
no_propagation.adb:16:66: warning: "Constraint_Error" may result in unhandled exception

Q1。当我在Concat函数中的declare块中有异常处理程序时,为什么会收到“Constraint_Error”可能导致未处理异常的警告?

Q2。如何将两个字节粘贴到Byte_Array中会产生约束错误?

2 个答案:

答案 0 :(得分:2)

您程序的一个更简单的版本是:

------------------------------------------------------------------
-- Simpler version of no propogation --
------------------------------------------------------------------
pragma Restrictions (No_Exception_Propagation);

with Interfaces; use Interfaces;

procedure No_Propagation2 is
   type Byte is new Unsigned_8;
   type Byte_Array is array (Natural range <>) of Byte;

   function Concat (Input_1 : Byte;
                    Input_2 : Byte)
                    return Byte_Array
   is
   begin
      return (Input_1, Input_2);
   end Concat;

   A : Byte := 5;
   B : Byte := 0;
   C : Byte_Array := Concat(A, B);
begin
   null;
end No_Propagation2;

答案 1 :(得分:2)

我认为您的代码触发了GNAT过度热情的警告。

要回答问题1,您会看到更进一步

no_propagation.adb:20:10: warning: pragma Restrictions (No_Exception_Propagation) in effect
no_propagation.adb:20:10: warning: this handler can never be entered, and has been removed

,原因是你的异常处理程序为时已晚,正如@BrianDrummond建议的那样。你写了

  declare
     Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2);
  begin
     return Output;
  exception
     when Constraint_Error =>
        return Null_Array;
  end;

如果发生任何异常,则必须在声明区域中,该处理程序不会覆盖该区域。您可以尝试编写

      declare
         Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2);
      begin
         return Output;
      end;
   exception
      when Constraint_Error =>
         return Null_Array;

但你会得到同样的警告;这一次,我认为,因为异常需要传播到它被引发的范围之外。如果是这样,这似乎是规则的不幸后果,或者可能是实施问题:No_Exception_PropagationGNAT extension

  

此限制可确保异常永远不会传播到外部子程序范围。可能引发异常的唯一情况是处理程序静态地位于同一子程序中,因此加注的效果基本上类似于goto语句。任何其他加注声明(隐式或显式)将被视为未处理。允许异常处理程序,但可能不包含异常发生标识符(异常选择)。此外,不允许使用GNAT.Current_Exception包,并且不允许重新加载语句(不使用操作数引发)。

对于问题2,这看起来像另一个编译器问题。 Byte_Array’(Input_1 & Input_2)导致警告,Byte_Array'(Input_1, Input_2)没有。

在任何一种情况下,您都会在致电Concat时收到相同的警告。

最好的方法可能是使用-gnatw.X来抑制所有这些警告,“关闭非本地异常的警告”(这应该是默认值,但我想这些警告会在{ {1}})。