forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeclaration.dd
626 lines (508 loc) · 15.8 KB
/
declaration.dd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
Ddoc
$(SPEC_S Declarations,
$(GRAMMAR
$(GNAME Declaration):
$(V1 $(B typedef) $(I Decl)
) $(B alias) $(I Decl)
$(I Decl)
$(GNAME Decl):
$(GLINK StorageClasses) $(I Decl)
$(GLINK BasicType) $(GLINK Declarators) $(B ;)
$(GLINK BasicType) $(GLINK Declarator) $(GLINK2 function, FunctionBody)
$(GLINK AutoDeclaration)
$(GNAME Declarators):
$(I DeclaratorInitializer)
$(I DeclaratorInitializer) $(B ,) $(GLINK DeclaratorIdentifierList)
$(GNAME DeclaratorInitializer):
$(GLINK Declarator)
$(GLINK Declarator) $(B =) $(GLINK Initializer)
$(GNAME DeclaratorIdentifierList):
$(GLINK DeclaratorIdentifier)
$(GLINK DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList)
$(GNAME DeclaratorIdentifier):
$(I Identifier)
$(I Identifier) $(B =) $(GLINK Initializer)
$(GNAME BasicType):
$(GLINK BasicTypeX)
$(B .)$(GLINK IdentifierList)
$(GLINK IdentifierList)
$(GLINK Typeof)
$(GLINK Typeof) $(B .) $(GLINK IdentifierList)
$(V2 $(B const$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B immutable$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B shared$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
$(B inout$(LPAREN)) $(GLINK Type) $(B $(RPAREN))
)
$(GNAME BasicTypeX):
$(B bool)
$(B byte)
$(B ubyte)
$(B short)
$(B ushort)
$(B int)
$(B uint)
$(B long)
$(B ulong)
$(B char)
$(B wchar)
$(B dchar)
$(B float)
$(B double)
$(B real)
$(B ifloat)
$(B idouble)
$(B ireal)
$(B cfloat)
$(B cdouble)
$(B creal)
$(B void)
$(GNAME BasicType2):
$(B *)
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(VEXPRESSION) .. $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(B delegate) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(B function) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(GNAME Declarator):
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(I Identifier) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME DeclaratorSuffixes):
$(GLINK DeclaratorSuffix)
$(GLINK DeclaratorSuffix) $(I DeclaratorSuffixes)
$(GNAME DeclaratorSuffix):
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(GLINK2 template, TemplateParameterList)$(OPT) $(GLINK Parameters) $(V2 $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT))
$(GNAME IdentifierList):
$(I Identifier)
$(I Identifier) $(B .) $(I IdentifierList)
$(GLINK2 template, TemplateInstance)
$(GLINK2 template, TemplateInstance) $(B .) $(I IdentifierList)
$(GNAME StorageClasses):
$(GLINK StorageClass)
$(GLINK StorageClass) $(I StorageClasses)
$(GNAME StorageClass):
$(B abstract)
$(B auto)
$(B const)
$(B deprecated)
$(B extern)
$(B final)
$(V2 $(B immutable)
$(B inout)
$(B shared)
$(B nothrow)
$(B override)
$(B pure)
$(B __gshared)
$(GLINK Property)
) $(B scope)
$(B static)
$(B synchronized)
$(GNAME Property):
$(B @) $(I Identifier)
$(GNAME Type):
$(GLINK BasicType)
$(GLINK BasicType) $(GLINK Declarator2)
$(GNAME Declarator2):
$(GLINK BasicType2)$(OPT) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME Parameters):
$(B $(LPAREN)) $(GLINK ParameterList) $(B $(RPAREN))
$(B ( ))
$(GNAME ParameterList):
$(GLINK Parameter)
$(GLINK Parameter) $(B ,) $(I ParameterList)
$(B ...)
$(GNAME Parameter):
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) $(B ...)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) = $(GLINK DefaultInitializerExpression)
$(I InOut)$(OPT) $(GLINK Type)
$(I InOut)$(OPT) $(GLINK Type) $(B ...)
$(GNAME InOut):
$(I InOutX)
$(I InOut InOutX)
$(GNAME InOutX):
$(B auto)
$(B const)
$(B final)
$(V2 $(B immutable)
) $(B in)
$(B inout)
$(B lazy)
$(B out)
$(B ref)
$(B scope)
$(B shared)
$(V2
$(GNAME FunctionAttributes):
$(GLINK FunctionAttribute)
$(GLINK FunctionAttribute) $(I FunctionAttributes)
$(GNAME FunctionAttribute):
$(B nothrow)
$(B pure)
$(GLINK Property)
)
$(GNAME MemberFunctionAttributes):
$(GLINK MemberFunctionAttribute)
$(GLINK MemberFunctionAttribute) $(I MemberFunctionAttributes)
$(GNAME MemberFunctionAttribute):
$(B const)
$(B immutable)
$(B inout)
$(B shared)
$(GLINK FunctionAttribute)
$(GNAME DefaultInitializerExpression):
$(ASSIGNEXPRESSION)
$(V2 $(B __FILE__)
$(B __LINE__))
$(GNAME Initializer):
$(GLINK VoidInitializer)
$(GLINK NonVoidInitializer)
$(GNAME NonVoidInitializer):
$(ASSIGNEXPRESSION)
$(GLINK ArrayInitializer)
$(GLINK StructInitializer)
$(GNAME ArrayInitializer):
$(B [ ])
$(B [) $(GLINK ArrayMemberInitializations) $(B ])
$(GNAME ArrayMemberInitializations):
$(GLINK ArrayMemberInitialization)
$(GLINK ArrayMemberInitialization) $(B ,)
$(GLINK ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations)
$(GNAME ArrayMemberInitialization):
$(GLINK NonVoidInitializer)
$(ASSIGNEXPRESSION) $(B :) $(GLINK NonVoidInitializer)
$(GNAME StructInitializer):
$(B { })
$(B {) $(GLINK StructMemberInitializers) $(B })
$(GNAME StructMemberInitializers):
$(GLINK StructMemberInitializer)
$(GLINK StructMemberInitializer) $(B ,)
$(GLINK StructMemberInitializer) $(B ,) $(I StructMemberInitializers)
$(GNAME StructMemberInitializer):
$(GLINK NonVoidInitializer)
$(I Identifier) $(B :) $(GLINK NonVoidInitializer)
)
<h3>Declaration Syntax</h3>
$(P Declaration syntax generally reads right to left:)
--------------------
int x; // x is an int
int* x; // x is a pointer to int
int** x; // x is a pointer to a pointer to int
int[] x; // x is an array of ints
int*[] x; // x is an array of pointers to ints
int[]* x; // x is a pointer to an array of ints
--------------------
$(P Arrays read right to left as well:)
--------------------
int[3] x; // x is an array of 3 ints
int[3][5] x; // x is an array of 5 arrays of 3 ints
int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints
--------------------
$(P
Pointers to functions are declared using the $(B function) keyword:
)
--------------------
int $(B function)(char) x; // x is a pointer to
// a function taking a char argument
// and returning an int
int $(B function)(char)[] x; // x is an array of
// pointers to functions
// taking a char argument
// and returning an int
--------------------
$(P
$(V1 C-style array, function pointer and pointer to array declarations are possible as an alternative:)
$(V2 C-style array, function pointer and pointer to array declarations are deprecated:)
)
--------------------
int x[3]; // x is an array of 3 ints
int x[3][5]; // x is an array of 3 arrays of 5 ints
int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 ints
int (*x)(char); // x is a pointer to a function taking a char argument
// and returning an int
int (*[] x)(char); // x is an array of pointers to functions
// taking a char argument and returning an int
--------------------
$(P
In a declaration declaring multiple symbols, all the declarations
must be of the same type:
)
--------------------
int x,y; // x and y are ints
int* x,y; // x and y are pointers to ints
int x,*y; // error, multiple types
int[] x,y; // x and y are arrays of ints
int x[],y; // error, multiple types
--------------------
<h3><a name="AutoDeclaration">Implicit Type Inference</a></h3>
$(GRAMMAR
$(GNAME AutoDeclaration):
$(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;)
$(GNAME AutoDeclarationX):
$(I Identifier) $(B =) $(GLINK Initializer)
$(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer)
)
$(P If a declaration starts with a $(I StorageClass) and has
a $(I NonVoidInitializer) from which the type can be inferred,
the type on the declaration can be omitted.
)
----------
static x = 3; // x is type int
auto y = 4u; // y is type uint
$(V1 auto s = "string"; // s is type char[6])
$(V2 auto s = "string"; // s is type immutable(char)[])
class C { ... }
auto c = new C(); // c is a handle to an instance of class C
----------
$(P The $(I NonVoidInitializer) cannot contain forward references
(this restriction may be removed in the future).
The implicitly inferred type is statically bound
to the declaration at compile time, not run time.
)
$(V2
$(P An $(GLINK2 expression, ArrayLiteral)
is inferred to be a dynamic array
type rather than a static array:)
---
auto v = ["hello", "world"]; // type is string[], not string[2]
---
)
$(V1
<h3><a name="typedef">Type Defining</a></h3>
$(P
Strong types can be introduced with the typedef. Strong types are semantically a
distinct type to the type checking system, for function overloading, and for the debugger.
)
--------------------
typedef int myint;
void foo(int x) { . }
void foo(myint m) { . }
.
myint b;
foo(b); // calls foo(myint)
--------------------
Typedefs can specify a default initializer different from the
default initializer of the underlying type:
--------------------
typedef int myint = 7;
myint m; // initialized to 7
--------------------
)
<h3><a name="alias">Type Aliasing</a></h3>
$(P
It's sometimes convenient to use an alias for a type, such as a shorthand for typing
out a long, complex type like a pointer to a function. In D, this is done with the
alias declaration:
)
--------------------
$(B alias) abc.Foo.bar myint;
--------------------
$(P
Aliased types are semantically identical to the types they are aliased to. The
debugger cannot distinguish between them, and there is no difference as far as function
overloading is concerned. For example:
)
--------------------
$(B alias) int myint;
void foo(int x) { . }
void foo(myint m) { . } // error, multiply defined function foo
--------------------
$(V1
$(P
Type aliases are equivalent to the C typedef.
)
)
<h3>Alias Declarations</h3>
$(P
A symbol can be declared as an $(I alias) of another symbol.
For example:
)
--------------------
import string;
$(B alias) string.strlen mylen;
...
int len = mylen("hello"); // actually calls string.strlen()
--------------------
$(P
The following alias declarations are valid:
)
--------------------
template Foo2(T) { $(B alias) T t; }
$(B alias) Foo2!(int) t1;
$(B alias) Foo2!(int).t t2;
$(B alias) t1.t t3;
$(B alias) t2 t4;
t1.t v1; // v1 is type int
t2 v2; // v2 is type int
t3 v3; // v3 is type int
t4 v4; // v4 is type int
--------------------
$(P
Aliased symbols are useful as a shorthand for a long qualified
symbol name, or as a way to redirect references from one symbol
to another:
)
--------------------
version (Win32)
{
$(B alias) win32.foo myfoo;
}
version (linux)
{
$(B alias) linux.bar myfoo;
}
--------------------
$(P
Aliasing can be used to $(SINGLEQUOTE import) a symbol from an import into the
current scope:
)
--------------------
$(B alias) string.strlen strlen;
--------------------
$(P
Aliases can also $(SINGLEQUOTE import) a set of overloaded functions, that can
be overloaded with functions in the current scope:
)
--------------------
class A {
int foo(int a) { return 1; }
}
class B : A {
int foo( int a, uint b ) { return 2; }
}
class C : B {
int foo( int a ) { return 3; }
$(B alias) B.foo foo;
}
class D : C {
}
void test()
{
D b = new D();
int i;
i = b.foo(1, 2u); // calls B.foo
i = b.foo(1); // calls C.foo
}
--------------------
$(P
$(B Note:) Type aliases can sometimes look indistinguishable from
alias declarations:
)
--------------------
$(B alias) foo.bar abc; // is it a type or a symbol?
--------------------
$(P
The distinction is made in the semantic analysis pass.
)
$(P Aliases cannot be used for expressions:)
-----------
struct S { static int i; }
S s;
alias s.i a; // illegal, s.i is an expression
alias S.i b; // ok
b = 4; // sets S.i to 4
-----------
<h3><a name="extern">Extern Declarations</a></h3>
Variable declarations with the storage class $(B extern) are
not allocated storage within the module.
They must be defined in some other object file with a matching
name which is then linked in.
The primary usefulness of this is to connect with global
variable declarations in C files.
<h3><a name="typeof">typeof</a></h3>
$(GRAMMAR
$(GNAME Typeof):
$(B typeof $(LPAREN)) $(EXPRESSION) $(B $(RPAREN))
$(B typeof $(LPAREN)) $(B return) $(B $(RPAREN))
)
$(P
$(I Typeof) is a way to specify a type based on the type
of an expression. For example:
)
--------------------
void func(int i) {
$(B typeof)(i) j; // j is of type int
$(B typeof)(3 + 6.0) x; // x is of type double
$(B typeof)(1)* p; // p is of type pointer to int
int[$(B typeof)(p)] a; // a is of type int[int*]
writefln("%d", $(B typeof)('c').sizeof); // prints 1
double c = cast($(B typeof)(1.0))j; // cast j to double
}
--------------------
$(P
$(I Expression) is not evaluated, just the type of it is
generated:
)
--------------------
void func() {
int i = 1;
$(B typeof)(++i) j; // j is declared to be an int, i is not incremented
writefln("%d", i); // prints 1
}
--------------------
$(P
There are $(V1 two) $(V2 three) special cases:
$(OL
$(LI $(B typeof(this)) will generate the type of what $(B this)
would be in a non-static member function, even if not in a member
function.
)
$(LI Analogously, $(B typeof(super)) will generate the type of what
$(B super) would be in a non-static member function.
)
$(V2
$(LI $(B typeof(return)) will, when inside a function scope,
give the return type of that function.
)
)
)
)
--------------------
class A { }
class B : A {
$(B typeof(this)) x; // x is declared to be a B
$(B typeof(super)) y; // y is declared to be an A
}
struct C {
$(B typeof(this)) z; // z is declared to be a C*
$(B typeof(super)) q; // error, no super struct for C
}
$(B typeof(this)) r; // error, no enclosing struct or class
--------------------
$(P
Where $(I Typeof) is most useful is in writing generic
template code.
)
<h3>Void Initializations</h3>
$(GRAMMAR
$(GNAME VoidInitializer):
$(B void)
)
Normally, variables are initialized either with an explicit
$(I Initializer) or are set to the default value for the
type of the variable. If the $(I Initializer) is $(B void),
however, the variable is not initialized. If its value is
used before it is set, undefined program behavior will result.
-------------------------
void foo() {
int x = void;
writefln(x); // will print garbage
}
-------------------------
Therefore, one should only use $(B void) initializers as a
last resort when optimizing critical code.
)
Macros:
TITLE=Declarations
WIKI=Declaration
CATEGORY_SPEC=$0
OPT=<sub>opt</sub>
ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression)
EXPRESSION=$(GLINK2 expression, Expression)
VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION))
FOO=