From: vldmr on
For the folllowing variant record:
------------------------------------------
type t_X520CommonName_Choice_Id is (
X520CommonName_teletexString,
X520CommonName_printableString
-- more choices
);
type t_X520CommonName (choice_Id : t_X520CommonName_Choice_Id :=
X520CommonName_teletexString) is record -- CHOICE
case choice_Id is
when X520CommonName_teletexString =>
teletexString : t_TeletexString_Acc; -- TeletexString
(SIZE (1..ub-common-name))
when X520CommonName_printableString =>
printableString : t_PrintableString_Acc; --
PrintableString (SIZE (1..ub-common-name))
-- ... more choices
end case;
end record;
----------------------------------
the following code:
---------------------------------
procedure BDec_X520CommonNameContent(tagId0 : t_Asn_Tag;v: out
t_X520CommonName;) is
begin
case tagId0 is
when
16#14000000# | -- UNIV PRIM TELETEXSTRING_TAG_CODE
16#34000000# -- UNIV CONS TELETEXSTRING_TAG_CODE
=>
declare
teletexString : t_TeletexString_Acc;
begin
teletexString := Adr_2_t_TeletexString_Acc
( Asn1_Alloc ( t_TeletexString'Size / 8));
Check_Asn1_Alloc (teletexString.all'Address,
exceptProc);
BDec_TeletexStringContent (tagId0, elmtLen0,
teletexString.all, totalElmtsLen1, exceptProc);
v := (choice_Id => X520CommonName_teletexString,
teletexString => teletexString); -- CONSTRAINT_ERROR
end;
-- ... more choices
end case;
end BDec_X520CommonNameContent;
--------------------------------------
when executed produces 'discriminant check failed' error on assignment
to v.

Why is that? As far as I understand the variable v shall be mutable.
Any hint is greatly appreciated

Thanks,
Vladimir
From: Adam Beneschan on
On Sep 2, 7:25 am, vldmr <vldm...(a)gmail.com> wrote:
> For the folllowing variant record:
> ------------------------------------------
> type t_X520CommonName_Choice_Id is (
>         X520CommonName_teletexString,
>         X520CommonName_printableString
> -- more choices
>     );
> type t_X520CommonName (choice_Id : t_X520CommonName_Choice_Id :=
> X520CommonName_teletexString) is record -- CHOICE
>     case choice_Id is
>         when X520CommonName_teletexString =>
>             teletexString : t_TeletexString_Acc; -- TeletexString
> (SIZE (1..ub-common-name))
>         when X520CommonName_printableString =>
>             printableString : t_PrintableString_Acc; --
> PrintableString (SIZE (1..ub-common-name))
> -- ... more choices
>      end case;
> end record;
> ----------------------------------
> the following code:
> ---------------------------------
>     procedure BDec_X520CommonNameContent(tagId0 : t_Asn_Tag;v: out
> t_X520CommonName;) is
>     begin
>         case tagId0 is
>             when
>                 16#14000000# | -- UNIV PRIM TELETEXSTRING_TAG_CODE
>                 16#34000000#   -- UNIV CONS TELETEXSTRING_TAG_CODE
>                 =>
>                 declare
>                     teletexString : t_TeletexString_Acc;
>                 begin
>                     teletexString := Adr_2_t_TeletexString_Acc
> ( Asn1_Alloc ( t_TeletexString'Size / 8));
>                     Check_Asn1_Alloc (teletexString.all'Address,
> exceptProc);
>                     BDec_TeletexStringContent (tagId0, elmtLen0,
> teletexString.all, totalElmtsLen1, exceptProc);
>                     v := (choice_Id => X520CommonName_teletexString,
> teletexString => teletexString); -- CONSTRAINT_ERROR
>                 end;
>         -- ... more choices
>        end case;
>     end BDec_X520CommonNameContent;
> --------------------------------------
> when executed produces 'discriminant check failed' error on assignment
> to v.
>
> Why is that? As far as I understand the variable v shall be mutable.

Only if the actual parameter is mutable when you call the procedure.

Say you declare

XYZ : t_X520CommonName (X520CommonName_printableString);

....
BDec_X520CommonNameContent (Something, XYZ);

XYZ is a constrained record. You wouldn't want
BDec_X520CommonNameContent violating the constranit of XYZ by changing
the discriminant, would you?

On the other hand, if you declare

ZYX : t_X520CommonName;
....
BDec_X520CommonNameContent (Something, ZYX);

ZYX is unconstrained, so it's OK for BDec_X520CommonNameContent to
change the discriminant. This means that the compiler has to generate
a little extra code to pass something to the procedure to tell it
whether it's OK to change the discriminant.

OK, so I'll bet your next question is: So how do I declare an object
to be unconstrained (mutable), but give its discriminant an initial
value other than the default (X520CommonName_teletexString)?

WXY : t_X520CommonName := (choice_Id =>
X520CommonName_printableString,
others => <>);

-- Adam
From: vldmr on
On Sep 2, 9:52 am, Adam Beneschan <a...(a)irvine.com> wrote:
> On Sep 2, 7:25 am, vldmr <vldm...(a)gmail.com> wrote:
>
> Only if the actual parameter is mutable when you call the procedure.
....
>
> OK, so I'll bet your next question is: So how do I declare an object
> to be unconstrained (mutable), but give its discriminant an initial
> value other than the default (X520CommonName_teletexString)?
>
>    WXY : t_X520CommonName := (choice_Id =>
> X520CommonName_printableString,
>                               others => <>);
>
>                                           -- Adam

Oh, thank, make sense now. At least I see where my problem is. In my
case WXY is actually declared as access to record, and is initialized
using Unchecked_Conversion from external memory address, pointing to
zero filled memory.

Any advice how to declare an access to variant record to be mutable?

Thank you,

Vladimir
From: Adam Beneschan on
On Sep 2, 8:09 am, vldmr <vldm...(a)gmail.com> wrote:
> On Sep 2, 9:52 am, Adam Beneschan <a...(a)irvine.com> wrote:
>
> > On Sep 2, 7:25 am, vldmr <vldm...(a)gmail.com> wrote:
>
> > Only if the actual parameter is mutable when you call the procedure.
> ...
>
> > OK, so I'll bet your next question is: So how do I declare an object
> > to be unconstrained (mutable), but give its discriminant an initial
> > value other than the default (X520CommonName_teletexString)?
>
> >    WXY : t_X520CommonName := (choice_Id =>
> > X520CommonName_printableString,
> >                               others => <>);
>
> >                                           -- Adam
>
> Oh, thank, make sense now. At least I see where my problem is. In my
> case WXY is actually declared as access to record, and is initialized
> using Unchecked_Conversion from external memory address, pointing to
> zero filled memory.
>
> Any advice how to declare an access to variant record to be mutable?

I don't think the language will let you do this, directly. If you
declare a type "type acc_t_X520CommonName is access all
t_X520CommonName", and an object Acc of this access type, then Acc.all
is assumed to be constrained, and if you pass Acc.all to your
procedure, the procedure can't change it. (The original motivation
was, I think, that you can declare a constrained subtype of the access
type; if you have an access object of that constrained subtype and
make it point to an object with the correct discriminant, it would be
bad if the language let you change the discriminant via a different,
unconstrained, access object. There have been some language changes
regarding discriminants on access types, and I'm not familiar with all
of them, so maybe you can do things you previously couldn't. I'm not
sure.)

However, you can get around this by embedding the variant record
inside another record:

type Rec is record
Name : t_X520CommonName;
end record;
type Acc_Rec is access all Rec;

Now, if X has type Acc_Rec, you can pass X.Name to your procedure, and
it will be unconstrained (and therefore mutable).

This is a workaround that I've used extensively in my own code, by the
way.

-- Adam

From: vldmr on
On Sep 2, 10:33 am, Adam Beneschan <a...(a)irvine.com> wrote:

> However, you can get around this by embedding the variant record
> inside another record:
>
>    type Rec is record
>       Name : t_X520CommonName;
>    end record;
>    type Acc_Rec is access all Rec;
>
> Now, if X has type Acc_Rec, you can pass X.Name to your procedure, and
> it will be unconstrained (and therefore mutable).
>
> This is a workaround that I've used extensively in my own code, by the
> way.
>
>                                       -- Adam

Yup, that works. I can not say I quite understand why, so for sure I
would not be able to invent that by myself.

Thank you very much!

Vladimir