www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Definitive list of storage classes

reply Jonathan M Davis <jmdavisProg gmx.com> writes:
I'd like to know which modifiers are considered to be storage classes. The term 
seems to be used on a lot more than actually qualifies (including using the 
term for the type qualfiers: const, immutable, and shared), and even the 
documentation uses it on stuff that I wouldn't have thought would be considered 
storage classes, because they have no effect on how variables are stored or 
linked (e.g. synchronized).

Someone asked about it on stackoverflow, and my explanation is not as good as 
it should be simply because I can't find a definitive list anywhere:

http://stackoverflow.com/questions/10150510/what-are-the-storage-classes-in-d

- Jonathan M Davis
Apr 13 2012
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.1707.1334377994.4860.digitalmars-d puremagic.com...
 I'd like to know which modifiers are considered to be storage classes. The 
 term
 seems to be used on a lot more than actually qualifies (including using 
 the
 term for the type qualfiers: const, immutable, and shared), and even the
 documentation uses it on stuff that I wouldn't have thought would be 
 considered
 storage classes, because they have no effect on how variables are stored 
 or
 linked (e.g. synchronized).

 Someone asked about it on stackoverflow, and my explanation is not as good 
 as
 it should be simply because I can't find a definitive list anywhere:

 http://stackoverflow.com/questions/10150510/what-are-the-storage-classes-in-d

 - Jonathan M Davis
There's always the list in 'declaration.h'. If I had to guess I'd say 'storage class' meant something much more specific in C than it does in D, where it seems to mean properties of a declaration that do not affect the type.
Apr 14 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 15, 2012 01:49:09 Daniel Murphy wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote in message
 news:mailman.1707.1334377994.4860.digitalmars-d puremagic.com...
 
 I'd like to know which modifiers are considered to be storage classes. The
 term
 seems to be used on a lot more than actually qualifies (including using
 the
 term for the type qualfiers: const, immutable, and shared), and even the
 documentation uses it on stuff that I wouldn't have thought would be
 considered
 storage classes, because they have no effect on how variables are stored
 or
 linked (e.g. synchronized).
 
 Someone asked about it on stackoverflow, and my explanation is not as good
 as
 it should be simply because I can't find a definitive list anywhere:
 
 http://stackoverflow.com/questions/10150510/what-are-the-storage-classes-i
 n-d
 
 - Jonathan M Davis
There's always the list in 'declaration.h'.
That's clearly not the list, since it includes const, immutable, and shared, which are type qualifiers rather than storage classes. It also has stuff like init in it, which isn't even vaguely a storage class. All of the storage classes may be in that list, but I don't know how you'd figure out which ones they are from that list.
 If I had to guess I'd say 'storage class' meant something much more specific
 in C than it does in D, where it seems to mean properties of a declaration
 that do not affect the type.
Except that both Walter and Andrei seem to talk about type qualifiers/constructors and storage classes as if they meant essentially the same thing as in C/C++. For instance, talking about const as being a type qualifier rather than a storage class doesn't mean anything to a non-D audience unless it means essentially the same thing as in C. Also, the documentation lists synchronized as being a storage class whereas it affects no variables whatsoever and all of the descriptions of storage classes in TDPL act like storage classes are for variables only. But synchronized doesn't affect scoping, storage, or linking at all as a storage class in C would, so that would at least seem to indicate that something other than the C definition is being used. Regardless, if a storage class does not have a specific definition separate from D which can be applied to D, then D needs to give its own definition for what on earth the term means, and I don't find _anywhere_ that does that. Everywhere that mentions it seems to assume that you have some idea of what it means already. TDPL _does_ sort of try and define it, but not really. It pretty much just lists certain modifiers as being storage classes without giving a full list or explaining exactly what constitutes a storage class. The closest thing that it gives to a definition "Each function parameter (base and exponent in the example above) has, in addition to its type, an optional storage class that decides the way that arguments are passed to the function when invoked." would seem indicate that static (which it later says is a storage class) isn't a storage class at all, since storage classes would only apply to function parameters (which would also disqualify synchronized as a storage class, which would be at odds with the online docs). So, I'd like an official definition of storage class with a list of what qualifies as a one in D. But it wouldn't surprise me at all if Walter's the only one who can do that. - Jonathan M Davis
Apr 14 2012
next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Saturday, 14 April 2012 at 17:50:39 UTC, Jonathan M Davis 
wrote:
 That's clearly not the list, since it includes const, 
 immutable, and shared,
 which are type qualifiers rather than storage classes. It also 
 has stuff like
 init in it, which isn't even vaguely a storage class. All of 
 the storage
 classes may be in that list, but I don't know how you'd figure 
 out which ones
 they are from that list.
Obviously D has inherited the term "storage class" from C and C++, but then expanded use of the term to a point where it's not always meaningful any more. I agree that the term needs some work. `const`, `immutable` and `shared` actually can affect the storage of variables in specific situations (e.g. an immutable module variable declaration), but we know they are also type qualifiers, beyond any doubt. I don't think it would be a stretch to say they are both storage classes and type qualifiers, and this is in fact how the specification presents it. I personally think that it's meaningless to classify them as both and would prefer their storage class classification be dropped from the specification text.
 If I had to guess I'd say 'storage class' meant something much 
 more specific
 in C than it does in D, where it seems to mean properties of a 
 declaration
 that do not affect the type.
Except that both Walter and Andrei seem to talk about type qualifiers/constructors and storage classes as if they meant essentially the same thing as in C/C++.
If Walter and/or Andrei have made an executive decision about what is and what isn't a storage class, I suggest they submit a pull request to dlang.org clarifying its new meaning. I have a feeling not a lot of thought has gone into this issue though, and Walter denying that immutable is a storage class (in his Lang.NEXT talk) probably means one of two things, 1) immutable is not a storage class in the context he presented, or 2) he was wrong and it is both a storage class and a type qualifier/constructor (per the specification).
 TDPL _does_ sort of try and define it, but not really. It 
 pretty much
 just lists certain modifiers as being storage classes without 
 giving a full
 list or explaining exactly what constitutes a storage class. 
 The closest thing
 that it gives to a definition

 "Each function parameter (base and exponent in the example 
 above) has, in
 addition to its type, an optional storage class that decides 
 the way that
 arguments are passed to the function when invoked."

 would seem indicate that static (which it later says is a 
 storage class) isn't
 a storage class at all, since storage classes would only apply 
 to function
 parameters (which would also disqualify synchronized as a 
 storage class, which
 would be at odds with the online docs).
He is referring to the *parameter storage classes*, and he's actually wrong on one point: a parameter can have multiple parameter storage classes as long as they are compatible. List from the specification on functions: "Parameter storage classes are in, out, ref, lazy, const, immutable, shared, inout or scope." One point of interest is that you can define a function like: void foo(const scope int a); With the `const` before the `scope` like that. This has to be taken into consideration if the definition of a storage class is to be revisited.
 So, I'd like an official definition of storage class with a 
 list of what qualifies
 as a one in D. But it wouldn't surprise me at all if Walter's 
 the only one who
 can do that.
Anyone making such a list would probably be making rather arbitrary on-the-spot decisions if we don't provide a solid definition of what a storage class is in D. As long as we have a good definition, anyone could fix the lists.
Apr 14 2012
prev sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 14 April 2012 at 17:50:39 UTC, Jonathan M Davis 
wrote:
 On Sunday, April 15, 2012 01:49:09 Daniel Murphy wrote:
 There's always the list in 'declaration.h'.
That's clearly not the list, since it includes const, immutable, and shared, which are type qualifiers rather than storage classes. It also has stuff like init in it, which isn't even vaguely a storage class. All of the storage classes may be in that list, but I don't know how you'd figure out which ones they are from that list.
As I understand it, const, immutable, and shared are both type qualifiers and storage classes. In C++, const is also both a storage class and type qualifier, which causes confusion. // At global scope immutable int x = 1; int y = 2; Here x and y are stored very differently. y is thread local whereas x is a program-wide read-only global. It's a similar situation with const and shared.
Apr 15 2012
parent reply kdevel <kdevel vogtner.de> writes:
On Sunday, 15 April 2012 at 09:59:54 UTC, Peter Alexander wrote:

[...]

 As I understand it, const, immutable, and shared are both type 
 qualifiers and storage classes. In C++, const is also both a 
 storage class and type qualifier, which causes confusion.

 // At global scope
 immutable int x = 1;
 int y = 2;

 Here x and y are stored very differently. y is thread local 
 whereas x is a program-wide read-only global. It's a similar 
 situation with const and shared.
A few days ago I ran into the following problem: ```mod.d module mod; immutable int x = 1; const int y = 1; int z = 1; ``` ```main.d import std.stdio; import mod; void main () { writeln (x); writeln (y); writeln (z); } ``` $ dmd -c mod.d main.d $ dmd main.o mod.o $ ./main 1 1 1 This is expected. Now I changed mod.d, recompiled only it and relinked: ```mod.d (2nd version) module mod; immutable int x = 2; const int y = 2; int z = 2; ``` $ dmd -c mod.d $ dmd main.o mod.o $ ./main 1 1 2 Here I'd expect three 2s. But this behavior I only achieve if I create separate initializations: ```mod.d (3rd version) module mod; immutable int x; const int y; int z = 2; shared static this () { x = 2; y = 2; } ``` Unfortunately I could not find a reasonable recap on this issue. In [1] const and immutable are intruduced as "attributes" but there is no explanation of their meanings. In [2] const and immutable become "type qualifiers" and likewise "storage classes". [1] https://dlang.org/spec/attribute.html#const [2] https://dlang.org/spec/const3.html
Jan 29 2021
parent reply MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Friday, 29 January 2021 at 21:32:19 UTC, kdevel wrote:
 Unfortunately I could not find a reasonable recap on this 
 issue. In [1]
The problem is that dmd treats const/immutable variables kinda like enums when they have an initializer. The final AST never accesses x, y but uses their initializers instead: immutable immutable(int) x = 2; const const(int) y = 2; int z = 2; void main() { writeln(2); writeln(2); writeln(z); return 0; }
Jan 29 2021
parent ag0aep6g <anonymous example.com> writes:
On 30.01.21 02:46, MoonlightSentinel wrote:
 The problem is that dmd treats const/immutable variables kinda like 
 enums when they have an initializer. The final AST never accesses x, y 
 but uses their initializers instead:
Throw `__ctfe` into the mix and it gets even more fun: void main() { const bool x = __ctfe; version (none) static const bool y = __ctfe; /* Error: variable `__ctfe` cannot be read at compile time */ else static const bool y = x; /* no error */ static assert(x == y); /* passes */ assert(x == y); /* fails */ }
Jan 29 2021