Skip to content

Commit 947a8a1

Browse files
authored
[spec/declaration] Group Initialization sections together (#3779)
* [spec/declaration] Group Initialization sections together Add *Initialization* heading after *Declaration Syntax*. Move grammar here & add legacy anchor. Move void init section here. Change auto-declaration heading to H3. Move global init section here. No changes to content. * Describe initializers Link to .init docs. Link to static ctors. * normally a variable is initialized
1 parent 2dd8036 commit 947a8a1

File tree

1 file changed

+89
-83
lines changed

1 file changed

+89
-83
lines changed

spec/declaration.dd

Lines changed: 89 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -95,20 +95,6 @@ $(GNAME StorageClass):
9595
$(RELATIVE_LINK2 ref-storage, `ref`)
9696
)
9797

98-
$(H3 $(LNAME2 initializers, Initializers))
99-
100-
$(GRAMMAR
101-
$(GNAME Initializer):
102-
$(GLINK VoidInitializer)
103-
$(GLINK NonVoidInitializer)
104-
105-
$(GNAME NonVoidInitializer):
106-
$(GLINK2 expression, AssignExpression)$(LEGACY_LNAME2 ExpInitializer)
107-
$(GLINK2 expression, ArrayLiteral)$(LEGACY_LNAME2 ArrayInitializer)
108-
$(GLINK2 struct, StructInitializer)$(LEGACY_LNAME2 StructInitializer)
109-
)
110-
111-
$(P See also $(GLINK VoidInitializer).)
11298

11399
$(H2 $(LNAME2 declaration_syntax, Declaration Syntax))
114100

@@ -197,7 +183,82 @@ int x, *y; // x is an int, y is a pointer to int
197183
int x[], y; // x is an array/pointer, y is an int
198184
)
199185

200-
$(H2 $(LEGACY_LNAME2 AutoDeclaration, auto-declaration, Implicit Type Inference))
186+
$(H2 $(LEGACY_LNAME2 initializers, initialization, Initialization))
187+
188+
$(GRAMMAR
189+
$(GNAME Initializer):
190+
$(GLINK VoidInitializer)
191+
$(GLINK NonVoidInitializer)
192+
193+
$(GNAME NonVoidInitializer):
194+
$(GLINK2 expression, AssignExpression)$(LEGACY_LNAME2 ExpInitializer)
195+
$(GLINK2 expression, ArrayLiteral)$(LEGACY_LNAME2 ArrayInitializer)
196+
$(GLINK2 struct, StructInitializer)$(LEGACY_LNAME2 StructInitializer)
197+
)
198+
199+
$(P When no *Initializer* is given, a variable is set to the
200+
$(DDSUBLINK spec/property, init, default `.init` value) for
201+
its type.)
202+
203+
$(P A variable can be initialized with a $(I NonVoidInitializer).)
204+
205+
$(P See also: $(DDSUBLINK spec/arrays, array-initialization, Array Initialization).)
206+
207+
$(H3 $(LNAME2 void_init, Void Initialization))
208+
209+
$(GRAMMAR
210+
$(GNAME VoidInitializer):
211+
$(D void)
212+
)
213+
214+
$(P Normally a variable will be initialized.
215+
However, if a variable initializer is $(D void), the variable is *not* initialized.
216+
Void initializers for variables with a type that may contain
217+
$(DDSUBLINK spec/function, safe-values, unsafe values) (such as types with pointers)
218+
are not allowed in `@safe` code.
219+
)
220+
221+
$(IMPLEMENTATION_DEFINED If a void initialized variable's value is
222+
used before it is set, its value is implementation defined.
223+
224+
---
225+
void bad()
226+
{
227+
int x = void;
228+
writeln(x); // print implementation defined value
229+
}
230+
---
231+
)
232+
233+
$(UNDEFINED_BEHAVIOR If a void initialized variable's value is
234+
used before it is set, and the value is a reference, pointer or an instance
235+
of a struct with an invariant, the behavior is undefined.
236+
237+
---
238+
void muchWorse()
239+
{
240+
char[] p = void;
241+
writeln(p); // may result in apocalypse
242+
}
243+
---
244+
)
245+
246+
$(BEST_PRACTICE
247+
$(OL
248+
$(LI Void initializers are useful when a static array is on the stack,
249+
but may only be partially used, such as a temporary buffer.
250+
Void initializers will potentially speed up the code, but they introduce risk, since one must ensure
251+
that array elements are always set before read.)
252+
$(LI The same is true for structs.)
253+
$(LI Use of void initializers is rarely useful for individual local variables,
254+
as a modern optimizer will remove the dead store of its initialization if it is
255+
initialized later.)
256+
$(LI For hot code paths, it is worth profiling to see if the void initializer
257+
actually improves results.)
258+
)
259+
)
260+
261+
$(H3 $(LEGACY_LNAME2 AutoDeclaration, auto-declaration, Implicit Type Inference))
201262

202263
$(GRAMMAR
203264
$(GNAME AutoDeclaration):
@@ -241,6 +302,19 @@ auto c = new C(); // c is a handle to an instance of class C
241302
auto v = ["resistance", "is", "useless"]; // type is string[], not string[3]
242303
---
243304

305+
$(H3 $(LNAME2 global_static_init, Global and Static Initializers))
306+
307+
$(P The $(GLINK Initializer) for a global or static variable must be
308+
evaluatable at compile time.
309+
Runtime initialization is done with $(DDSUBLINK spec/module, staticorder, static constructors).
310+
)
311+
312+
$(IMPLEMENTATION_DEFINED
313+
$(OL
314+
$(LI Whether some pointers can be initialized with the addresses of other
315+
functions or data.)
316+
))
317+
244318

245319
$(H2 $(LNAME2 alias, Alias Declarations))
246320

@@ -667,74 +741,6 @@ extern extern(C) int bar;
667741
connect with global variables declarations and functions in C or C++ files.)
668742
))
669743

670-
$(H2 $(LNAME2 void_init, Void Initializations))
671-
672-
$(GRAMMAR
673-
$(GNAME VoidInitializer):
674-
$(D void)
675-
)
676-
677-
$(P Normally, variables are initialized either with an explicit
678-
$(GLINK Initializer) or are set to the default value for the
679-
type of the variable. If the $(I Initializer) is $(D void),
680-
however, the variable is not initialized.
681-
Void initializers for variables with a type that may contain
682-
$(DDSUBLINK spec/function, safe-values, unsafe values) (such as types with pointers)
683-
are not allowed in `@safe` code.
684-
)
685-
686-
$(IMPLEMENTATION_DEFINED If a void initialized variable's value is
687-
used before it is set, its value is implementation defined.
688-
689-
---
690-
void bad()
691-
{
692-
int x = void;
693-
writeln(x); // print implementation defined value
694-
}
695-
---
696-
)
697-
698-
$(UNDEFINED_BEHAVIOR If a void initialized variable's value is
699-
used before it is set, and the value is a reference, pointer or an instance
700-
of a struct with an invariant, the behavior is undefined.
701-
702-
---
703-
void muchWorse()
704-
{
705-
char[] p = void;
706-
writeln(p); // may result in apocalypse
707-
}
708-
---
709-
)
710-
711-
$(BEST_PRACTICE
712-
$(OL
713-
$(LI Void initializers are useful when a static array is on the stack,
714-
but may only be partially used, such as a temporary buffer.
715-
Void initializers will potentially speed up the code, but they introduce risk, since one must ensure
716-
that array elements are always set before read.)
717-
$(LI The same is true for structs.)
718-
$(LI Use of void initializers is rarely useful for individual local variables,
719-
as a modern optimizer will remove the dead store of its initialization if it is
720-
initialized later.)
721-
$(LI For hot code paths, it is worth profiling to see if the void initializer
722-
actually improves results.)
723-
)
724-
)
725-
726-
$(H2 $(LNAME2 global_static_init, Global and Static Initializers))
727-
728-
$(P The $(GLINK Initializer) for a global or static variable must be
729-
evaluatable at compile time.
730-
Runtime initialization is done with static constructors.
731-
)
732-
733-
$(IMPLEMENTATION_DEFINED
734-
$(OL
735-
$(LI Whether some pointers can be initialized with the addresses of other
736-
functions or data.)
737-
))
738744

739745
$(H2 $(LNAME2 typequal_vs_storageclass, Type Qualifiers vs. Storage Classes))
740746

0 commit comments

Comments
 (0)