1

次のように共用体型を宣言します。

type Access_Kind is (Named, Indexed);
type Array_Type is array (0 .. 1) of Integer;

type Record_Type (Kind : Access_Kind := Access_Kind'First) is record
   case Kind is
      when Named =>
         X, Y : Integer;
      when Indexed =>
         S : Array_Type;
   end case;
end record;
pragma Unchecked_Union (Record_Type);
pragma Convention (C_Pass_By_Copy, Record_Type);

function Create (X, Y : Integer) return Record_Type;

今、派生型を作成しようとすると:

type Integer2 is new Record_Type;

GNAT は次の警告を表示します。

warning: in instantiation at line [pragma Convention...]
warning: variant record has no direct equivalent in C
warning: use of convention for type "Integer2" is dubious

したがって、派生型にはプラグマ Convention が適用されているように見えますが、Unchecked_Union は適用されていません。Record_Typeプリミティブ操作が既に定義されているため (Integer2は別のパッケージで定義されています) 、派生型に再度適用することはできません。

これは正しい動作ですか、それとも GNAT のバグですか? 新しい型が Unchecked_Union プラグマを継承するように、Unchecked_Union 型から正しく派生させるにはどうすればよいですか?

GNAT バージョン: GNAT GPL 2012 (20120509)。

4

2 に答える 2

4

1つの可能性はRecord_Type、ネストされたパッケージでの操作を宣言しOpsて、それらがプリミティブにならないようにすることです。

package Union is

   type Access_Kind is (Named, Indexed);
   type Array_Type is array (0 .. 1) of Integer;

   type Record_Type (Kind : Access_Kind := Access_Kind'First) is record
      case Kind is
         when Named =>
            X, Y : Integer;
         when Indexed =>
            S : Array_Type;
      end case;
   end record;
   pragma Unchecked_Union (Record_Type);
   pragma Convention (C_Pass_By_Copy, Record_Type);

   --  If P was declared immediately within Union, it would be
   --  primitive, and it wouldn't be possible to declare
   --  representation aspects for Integer2.
   package Ops is
      procedure P (R : Record_Type) is null;
      --  "is null" only so that I can use -gnatR without needing a
      --  body.
   end Ops;

   type Integer2 is new Record_Type;
   pragma Unchecked_Union (Integer2);
   pragma Convention (C_Pass_By_Copy, Integer2);

end Union;

-gnatR選択した表現を表示するために使用すると、

$ gnatmake -c -u -f -gnatwa union.ads -gnatR
gcc -c -gnatwa -gnatR -gnat05 union.ads

Representation information for unit Union (spec)
------------------------------------------------

for Array_Type'Size use 64;
for Array_Type'Alignment use 4;
for Array_Type'Component_Size use 32;

for Record_Type'Size use 64;
for Record_Type'Alignment use 4;
for Record_Type use record
   Kind at ?? range  0 ..  -1;
   X    at  0 range  0 .. 31;
   Y    at  4 range  0 .. 31;
   S    at  0 range  0 .. 63;
end record;

for Integer2'Size use 64;
for Integer2'Alignment use 4;
for Integer2 use record
   Kind at ?? range  0 ..  -1;
   X    at  0 range  0 .. 31;
   Y    at  4 range  0 .. 31;
   S    at  0 range  0 .. 63;
end record;

そうは言っても、GNATの振る舞いは間違っていると思います。

ARM 13.1(0.1)は、表現運用の側面があると述べており、 (1)は表現の側面を定義しています。(10)は、プリミティブ操作を回避する必要がある理由です。(15)表現的側面は、派生型によって継承されると述べています。しかし、(15.1)は、特定の側面について「指定されていない限り」、運用上の側面は指定されていないと述べています。「指定された」とは、「言語定義の側面についてはARMで、ベンダー定義の側面についてはベンダーによって」を意味すると思います。

B3.3(3.1)Unchecked_Unionは、それが表現の側面であると述べています。したがって、継承する必要があります。

B3.1(0.1)は、を含むインターフェースの側面Conventionは表現の側面であると述べています。C_Pass_By_Copyしたがって、継承する必要があります。

バグレポートを作成します。

于 2013-02-03T10:34:24.507 に答える
1

Ada 2012 では、pragma Unchecked_Unionは廃止され、現在は shader を指定できますUnchecked_Union。どちらの場合でも、Rationale for Ada 2005: 6.4 Pragmas and Restrictionsで説明されているように、この警告は、チェックされていない共用体型が「Ada 2005 で導入されたのは、C プログラムとのインターフェイスのみを目的としており、危険にさらすためではない」ことを思い出させるものです。派生型Record_Typeは禁止されていません。セクションに示されているように、誤った実行の機会が広がるため、これは悪い考えです。代わりに、ユニオンをバインディングの本体にカプセル化し、より高いレベルの型から派生させます。

補遺:参照用に古いバージョンを確認すると、

グナト 4.6
Copyright 1996-2010, Free Software Foundation, Inc.
...
ユニット未チェック(本体)の表記情報
-------------------------------------------------- --

Array_Type'Size には 64 を使用します。
Array_Type'Alignment には 4 を使用します。
Array_Type'Component_Size には 32 を使用します。

Record_Type'Size には 64 を使用します。
Record_Type'Alignment には 4 を使用します。
Record_Type の使用レコード
   種類?? 範囲 0 .. -1;
   X 0 の範囲 0 .. 31;
   4 の Y 範囲 0 .. 31;
   0 の S 範囲 0 .. 63;
レコードを終了します。

Integer2'Size の場合は 96 を使用します。
Integer2'Alignment の場合は 4 を使用します。
Integer2 使用レコードの場合
   0 の種類 範囲 0 .. 7;
   X の 4 範囲 0 .. 31;
   8 の Y 範囲 0 .. 31;
   4 範囲 0 の S .. 63;
レコードを終了します。
于 2013-02-02T16:19:19.250 に答える