Skip to content

Commit 23e1d53

Browse files
llvm-beanzbogner
andauthored
[0005] Adding spec language for strict initializer lists (#522)
This adds a detailed design including draft language spec wording for the strict initializer lists proposal. Fixes #228 --------- Co-authored-by: Justin Bogner <[email protected]>
1 parent f5638cb commit 23e1d53

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

proposals/0005-strict-initializer-lists.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,125 @@ Fix-It will be backwards compatible to prior HLSL versions.
7171
New code that takes advantage of C & C++'s zero-initialization behavior, will
7272
not be backwards compatible to older HLSL versions.
7373
74+
## Detailed Design
75+
76+
HLSL 202y shall adopt specification language aligned with the [ISO C++
77+
specification (ISO/IEC
78+
14882:2011)](https://timsong-cpp.github.io/cppwp/n3337/dcl.init).
79+
80+
The language in the next subsection will replace the **Decl.Init.Agg** section
81+
of the HLSL specification.
82+
83+
### Specification Language
84+
85+
An _aggregate_ is a vector, matrix, array, or class which does not contain
86+
* user-declared or inherited constructors
87+
* non-public non-static data members, or
88+
* non-public base classes
89+
90+
For the purposes of aggregate initialization, anonymous bit-fields are not
91+
considered members of an object.
92+
93+
When initialized by an initializer list, the elements of the initializer list
94+
are initializers for the members of the aggregate in subscript or member order.
95+
Each member is copy-initialized from the corresponding initializer-clause. If
96+
the initializer-clause is an expression which requires a narrowing conversion to
97+
convert to the subobject type, the program is ill-formed.
98+
99+
An aggregate that is a class can also be initialized by a single expression not
100+
enclosed in braces.
101+
102+
An array of unknown size may be initialized by a brace enclosed
103+
initializer-list. For arrays of unknown size the initializer list shall contain
104+
`n` initializers where `n > 0` and will produce a one-dimensional array containing `n`
105+
elements.
106+
107+
If an initializer-list contains more initializer-clauses than the number of
108+
subobjects being initialized, the program is ill-formed.
109+
110+
If an initializer-list contains fewer initializer-clauses than the number of
111+
subobjects being initialized, each member not explicitly initialized shall be
112+
initialized as if by an empty initializer list.
113+
114+
If an aggregate class contains a subobject member that has no non-static data
115+
members, the initializer-clause for the empty subobject shall not be
116+
omitted from an initializer list for the containing class unless the
117+
initializer-caluses for all following members of the class are also omitted.
118+
119+
```hlsl
120+
struct Empty {};
121+
122+
struct Space {
123+
int Stars;
124+
Empty E;
125+
double Size;
126+
};
127+
128+
Space A = {}; // Zero-initializes all members.
129+
Space B = {1}; // Initializes Stars to 1 then zero-initializes remaining
130+
// fields.
131+
Space C = {1, 4}; // Ill-formed, cannot initialize Empty from 4, and cannot
132+
// omit the empty initializer.
133+
Space D = {1, {}, 4}; // Initializes Stars to 1 and Size to 4.
134+
```
135+
136+
137+
An initializer-list that is part of a braced-init-list may elide braces for
138+
initializing subobjects. If braces are elided, a number of initializer-clauses
139+
equal to the subobject's number of elements initializes the subobject. If braces
140+
are present, it forms a braced-init-list which initializes the subobject
141+
following the rules of this section.
142+
143+
A multi-dimensional array may be initialized using a single braced-initializer
144+
list or with nested initializer lists. When initializing with a single
145+
braced-initializer the order of initialization matches the memory layout.
146+
147+
```hlsl
148+
int x[2][2] = {1, 2, 3, 4}; // [0][0] = 1, [0][1] = 2,
149+
// [1][0] = 3,[1][1] = 4
150+
int y[3][2] = {{1,2}, {3}, {4}}; // [0][0] = 1, [0][1] = 2,
151+
// [1][0] = 3, [1][1] = 0,
152+
// [2][0] = 4, [2][1] = 0
153+
```
154+
155+
Element initialization behaves as if an assignment-expression is evaluated
156+
from the initializer-clause to the initialized member. All implicit conversions
157+
are applied as appropriate to convert the initializer to the member type. If the
158+
assignment-expression is ill-formed and the element is a subobject, brace
159+
elision is assumed and an assignment-expression is evaluated as if initializing
160+
the first element of the subobject. If both assignment-expressions are
161+
ill-formed the program is ill-formed.
162+
163+
```hlsl
164+
RWBuffer Buf;
165+
166+
struct ResourceRef {
167+
RWBuffer B;
168+
int Offset;
169+
};
170+
171+
struct A {
172+
int X;
173+
RWBuffer B;
174+
};
175+
176+
struct B {
177+
A S;
178+
int Y;
179+
};
180+
181+
A T = 1; // This is ill-formed, cannot initialize A from int.
182+
183+
B U = {1,B,3}; // This is fine, brace elision is assumed because A cannot be
184+
// initialized from int
185+
B V = {1,2,3}; // This is ill-formed, cannot initialize RWBuffer from int.
186+
187+
```
188+
189+
When a union is initialized with an initializer-list, the initializer-list will
190+
contain only one initializer-clause which will initialize the first non-static
191+
data member of the union.
192+
74193
## Unanswered Questions
75194

76195
### Should we support initialization constructors (i.e. `uint4 i4{}`)?

0 commit comments

Comments
 (0)