EDA.org Mantis
Mantis Bugtracker

Viewing Issue Simple Details Jump to Notes ] Wiki ] View Advanced ] Issue History ] Print ]
ID Category Severity Date Submitted Last Update
0002470 [SystemVerilog P1800] SV-EC minor 2008-08-29 01:10 2010-02-05 13:57
Reporter Daniel Mlynek View Status public  
Assigned To
Priority normal Resolution open  
Status new   Product Version P1800-2008/D6
Summary 0002470: The order of initialization of class properties initialized in the declaration vs. contructor calls should be clearly defined.
Description There are two problems - exact description is in mail addded as note but:
1st the order mentioned in title is not clear:
"Every class has a default (built-in) new method. The default constructor first calls its base class constructor (super.new() as described in 8.14) and then proceeds to initialize each member of the current object to its default (or uninitialized value)."
What is the default value - from the sentence it seams that this is a value from initalization at declaration while before LRM describes that default value is the value of uninitialized variable.

2nd. There should be some restriction on arguments for class constructor as Steven Sharp wrote:
">To make that code illegal, you would have to specify special scoping rules to the actual arguments of the super.new() call. You would have to regard the scope the same way as if you were inside a static method of the class: you have access to the locals of the new() method and to static properties, but not to nonstatic properties. Another way to do it would be to treat the value of 'this' as if it were null until after the super.new() call returned."

I've attached some test cases on that
Additional Information
Tags No tags attached.
Type Clarification
Attached Files zip file icon cases.zip [^] (2,042 bytes) 2008-08-29 01:10

- Relationships
related to 0002597closedgordonv Ballot comment #49 When do class property initializers execute in relation with the constructor call 
has duplicate 0002429new Behaviour of virtual function call from base class constructor - should be defined 
child of 0003102new Master issue for SV-EC Class issues 

-  Notes
User avatar (0007406)
Daniel Mlynek (reporter)
2008-08-29 01:12

--------------------------------------------------------------------------------
From: owner-sv-ec@server.eda.org [mailto:owner-sv-ec@server.eda.org] On Behalf Of Daniel Mlynek
Sent: 28 sierpnia 2008 17:09
To: sv-ec@server.eda-stds.org
Subject: [sv-ec] member initialization at declaration vs. constructor - order issue


I've hit another problem connected with order of execution of declaration initialization vs.. constructor (imho allowing declaration initialization for class members was good idea at all)
LRM doesn't define how it should be done. My guess is that:
1st initialization from declaration should be done in order from base class to child class
2nd constructor chain should be executed - as described in LRM from base to child

Rules for the order are clear for classes which do not inherit other class - LRM:
"Class properties that include an initialize in their declaration are initialized before the execution of the user defined class constructor. Thus, initializer values can be overridden by the class constructor."

But for classes inheriting some other class LRM says:
"Every class has a default (built-in) new method. The default constructor first calls its base class constructor (super.new() as described in 8.14) and then proceeds to initialize each member of the current object to its default (or uninitialized value)."
Most interesting is "proceeds to initialize each member of the current object to its default (or uninitialized value)." I thought that uninitialized value is same as default, anyway why constructor need to do some initialization if the value should be default (which means that value is hold in variable if no initialization or assignment was done ).
But one can understand this sentence differently - default value is a value from initialization at declaration - because it has to be assigned - if so then results for below code would be : 123 0 123 123

I totally don't understand what was the goal of adding this sentence to LRM.


CODE:
module top;
        class C;
                int i=123;
                function new(input int v);
                        $display("C %d", i);
                        $display("C %d", v);
                endfunction
        endclass

        class CC extends C;
                int j=i;
                function new;
                        super.new(j);
                        $display("CC %d",i);
                        $display("CC %d",j);
                endfunction
        endclass

        CC c = new;
endmodule

IMHO Expected results are:
123
123
123
123

What should be the results in your opinion?
Is the LRM description clear in this matter in your opinion?
Do you finding class member initialization at declaration useful feature - or are you regretting that someone have vote it in into the standard ?
User avatar (0007407)
Daniel Mlynek (reporter)
2008-08-29 01:12

-----Original Message-----
From: owner-sv-ec@server.eda.org [mailto:owner-sv-ec@server.eda.org] On Behalf Of Steven Sharp
Sent: 29 sierpnia 2008 00:15
To: sv-ec@server.eda-stds.org; daniel.mlynek@aldec.com
Subject: Re: [sv-ec] member initialization at declaration vs. constructor - order issue


>From: "Daniel Mlynek" <daniel.mlynek@aldec.com>

>I've hit another problem connected with order of execution of
>declaration initialization vs.. constructor (imho allowing declaration
>initialization for class members was good idea at all) LRM doesn't
>define how it should be done. My guess is that:
>1st initialization from declaration should be done in order from base
>class to child class 2nd constructor chain should be executed - as
>described in LRM from base to child

The problem with this ordering is that an initializer on a declaration in the child class could reference a property in the base class that is initialized by the base class constructor. The child class should not be dependent on how the construction of the base class was done. Therefore the base class should be completely initialized before the initialization of the child class is started.


>But for classes inheriting some other class LRM says:
>"Every class has a default (built-in) new method. The default
>constructor first calls its base class constructor (super.new() as
>described in 8.14) and then proceeds to initialize each member of the
>current object to its default (or uninitialized value)."
>Most interesting is "proceeds to initialize each member of the current
>object to its default (or uninitialized value)." I thought that
>uninitialized value is same as default, anyway why constructor need to
>do some initialization if the value should be default (which means that
>value is hold in variable if no initialization or assignment was done ).
>But one can understand this sentence differently - default value is a
>value from initialization at declaration - because it has to be
>assigned

I believe this is how you must interpret the sentence, though I agree it is not entirely clear.

The order should be

1. Call the base class constructor.
2. Initialize each member to the default value specified in its declaration,
   if any, else to the default initialization value.
3. Execute the body of the constructor.

Though the LRM does not say so, it would also make sense to initialize the properties in the order they were declared, since the initializer of a property might refer to a property declared earlier.

This leaves only one small hole where you could refer to the value of a property before it is initialized. That is the one you use in your
example: the actual arguments to the super.new() call, if you specify it explicitly. In your example, you refer to a property of the local class, which is not initialized until after the super.new() call. You could also refer to a property of the base class, which might be initialized by the super.new() call itself. I think we just have to regard that as bad code.

To make that code illegal, you would have to specify special scoping rules to the actual arguments of the super.new() call. You would have to regard the scope the same way as if you were inside a static method of the class: you have access to the locals of the new() method and to static properties, but not to nonstatic properties. Another way to do it would be to treat the value of 'this' as if it were null until after the super.new() call returned.

>I totally don't understand what was the goal of adding this sentence to LRM.

I suspect it was intended to answer your question about the order. You just have to interpret "default" in that sentence as meaning the value on the declaration. That would explain why the sentence treats it as something different from the uninitialized value.
 

>What should be the results in your opinion?

123 undefined 123 123

Making sure that the base class is initialized before the derived class is more important than someone trying to pass an uninitialized property as an argument to the base constructor. Even with your suggested ordering, I could still reference an uninitialized value in the base class anyway.

With your suggested ordering, there would be a problem with

        class C;
                int i;
                function new(input int v);
                        i = v;
                        $display("C %d", i);
                        $display("C %d", v);
                endfunction
        endclass
 
        class CC extends C;
                int j=i;
                function new;
                        super.new(123);
                        $display("CC %d",i);
                        $display("CC %d",j);
                endfunction
        endclass

With your suggested ordering, the result of this would be

  123 123 123 undefined

With my suggested ordering, the result of this would be

  123 123 123 123

>Is the LRM description clear in this matter in your opinion?

It could use some improvement.


>Do you finding class member initialization at declaration useful
>feature - or are you regretting that someone have vote it in into the standard ?

It would certainly be simpler to have left it out and require users to insert assignments into the constructor instead (after any super.new() call). But as long as it is understood to be equivalent to that, it does not cause any real problems.


Steven Sharp
sharp@cadence.com
User avatar (0007409)
Daniel Mlynek (reporter)
2008-09-01 00:10

Similar problem :
class C;
    int i=123;
    function new();
        int j=i; //this initialization is perofrmed before I initalization at declaration?
        //super.new(j);//implicit or explicit What would be the value if j according to yours undertanding? 0 or 123?
User avatar (0007410)
Daniel Mlynek (reporter)
2008-09-01 00:10

-----Original Message-----
From: owner-sv-ec@server.eda.org [mailto:owner-sv-ec@server.eda.org] On Behalf Of Arturo Salz
Sent: 29 sierpnia 2008 20:29
To: Gordon Vreugdenhil; Rich, Dave
Cc: Daniel Mlynek; Steven Sharp; sv-ec@server.eda-stds.org
Subject: RE: [sv-ec] member initialization at declaration vs. constructor - order issue

I agree that we don't have a consensus yet on some of this. But I'd like to answer Daniel's original question regarding the intent of property declaration initializers and their relationship with constructor functions. The intent was as Steven wrote, with one slight difference:

A call to a class constructor should do the following, in this order:

1. Allocate memory for the object (the entire object) 2. Initialize each member (of the entire object) to the default value specified in its declaration, if any, else to the default initialization value.
3. Call the class constructor
3.a If the class is not a base class then the first thing the constructor executes is the base class constructor (lets put aside the ambiguity related to "first") - and so on recursively until reaching the base class.
4. Execute the body of the constructor.

This is the intent for allowing constructor methods to override the property declaration initializers.

Note that step 3.a above could also be implemented by initializing each member to its default initialization value first and then initializing members with the value specified as a default initialization.

To explain this, consider the following example:

class B;
  int a = 5;

  function new( int x );
    a = x;
  endfunction
endclass

class C extends B;
  int i = 123;
  int j;

  function new();
    super.new( j );
    j = i;
  endfunction
endclass

C q = new;

Right before B::new begins execution, the class properties should be:
 a = 5
 i = 123
 j = 0
After execution of B::new, the values are:
 a = 0
 i = 123
 j = 0
Once execution of C::new, the values are:
 a = 0
 i = 123
 j = 123

I hope this helps.

I agree with Steven's remark that it makes sense to initialize properties in the order they were declared - and base class to derived class. But the LRM does not state this explicitly.

    Arturo
User avatar (0007457)
Daniel Mlynek (reporter)
2008-09-03 07:41

My proposal bases on all voices is to add in chapter 8.7 Constructors detailed description of how object should be constructed smth like below in place of acapits describing default initialization:

Object construction order is defined in follow steps:
1.Memory allocation for all dynamic object properties (local and inherited).
2.Call the object constructor. (explicit or implicit)
3.Initialize constructor ports (if exists).
4.Create and initialize constructor local automatic variables (if exists).
5.Call to base class constructor - super.new – explicit or implicit one (if class has base class)
6.Initialize local object properties to their default values defined at declaration (defined in initialization at declaration).
7.Execute body of constructor
NOTE: Reference to local or inherited dynamic variable prior return from base class constructor (reference in constructor local automatic variables initialization or in super.new call as argument )should trigger at least warning (or error)
User avatar (0009245)
Steven Sharp (developer)
2010-02-05 13:57

Shalom has added the connection between this item and 0002597, which resolves the first issue raised here. The resolution matched the interpretation described in note 7407 above.

- Issue History
Date Modified Username Field Change
2008-08-29 01:10 Daniel Mlynek New Issue
2008-08-29 01:10 Daniel Mlynek File Added: cases.zip
2008-08-29 01:10 Daniel Mlynek Type => Clarification
2008-08-29 01:12 Daniel Mlynek Note Added: 0007406
2008-08-29 01:12 Daniel Mlynek Note Added: 0007407
2008-08-29 01:19 shalom Issue Monitored: shalom
2008-09-01 00:10 Daniel Mlynek Note Added: 0007409
2008-09-01 00:10 Daniel Mlynek Note Added: 0007410
2008-09-03 07:41 Daniel Mlynek Note Added: 0007457
2010-02-05 01:35 shalom Relationship added related to 0002597
2010-02-05 13:57 Steven Sharp Note Added: 0009245
2010-04-26 12:31 Thomas R Alsop Relationship added has duplicate 0002429
2010-05-24 12:27 shalom Relationship added child of 0003102


Mantis 1.1.7[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker