为什么这个 Ada 程序没有抛出约束错误?

Why does this Ada program not throw a constraint error?

我预计以下代码会在编译时引发约束错误,但它没有。它也不会在 c2 赋值时抛出运行时错误。编辑:运行 带有-gnata 的编译器解决了编译警告问题,但没有解决缺少运行时错误问题。它是使用 GNAT FSF 编译的,没有优化,只是:gnatmake main 编辑:gnatmake -gnata main

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
    subtype cat is Integer with Dynamic_Predicate => cat in 1 .. 9;

    c1 : cat;
    c2 : cat;
begin
    c1 := 5;
    c2 := 99;
end Main;

我认为 Dynamic_Predicate 行本质上等同于以下内容:

subtype cat is Integer range 1 .. 9;

当我构建您的示例时,我收到编译时警告和 运行 时错误:

$ gnatmake -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn -m -j0 main.adb
gcc-6 -c -gnata -gnato -fstack-check -gnat12 -gnatyO -gnatv -gnati1 -gnatf -gnatn main.adb

GNAT 6.3.0 20170516
Copyright 1992-2016, Free Software Foundation, Inc.

Compiling: main.adb
Source file time stamp: 2018-08-02 06:08:55
Compiled at: 2018-08-02 08:11:00

    10.     c2 := 99;
                  |
        >>> warning: expression fails predicate check on "cat"

 11 lines: No errors, 1 warning
gnatbind-6 -x main.ali
gnatlink-6 main.ali -fstack-check
$ ./main

raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : Dynamic_Predicate failed at main.adb:10
$ 

我想问你的问题是 GCC/GNAT 中的默认断言策略是 Ignore。我使用标志 -gnata 来覆盖它。

请注意,编译器只会给您一个警告。那是因为该程序是完全合法的,即使它会在 运行 时间引发异常。 (这个是一样的,不管你用rangeStatic_Predicate还是Dynamic_Predicate来指定子集。)