source: code/trunk/vendor/modernc.org/cc/v3/check.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 145.7 KB
Line 
1// Copyright 2019 The CC Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package cc // import "modernc.org/cc/v3"
6
7import (
8 "fmt"
9 "go/token"
10 "math"
11 "math/big"
12 "math/bits"
13 "path/filepath"
14 "strconv"
15 "strings"
16
17 "modernc.org/mathutil"
18 "modernc.org/strutil"
19)
20
21const longDoublePrec = 256
22
23type mode = int
24
25var (
26 idBuiltinConstantPImpl = dict.sid("__builtin_constant_p_impl")
27 idClosure = dict.sid("0closure") // Must be invalid indentifier.
28 idWcharT = dict.sid("wchar_t")
29 idWinWchar = dict.sid("WCHAR")
30
31 _ fmt.State
32)
33
34const (
35 // [2], 6.6 Constant expressions, 6
36 //
37 // An integer constant expression shall have integer type and shall
38 // only have operands that are integer constants, enumeration
39 // constants, character constants, sizeof expressions whose results are
40 // integer constants, _Alignof expressions, and floating constants that
41 // are the immediate operands of casts. Cast operators in an integer
42 // constant expression shall only convert arithmetic types to integer
43 // types, except as part of an operand to the sizeof or _Alignof
44 // operator.
45 mIntConstExpr = 1 << iota
46
47 mIntConstExprFloat // As mIntConstExpr plus accept floating point constants.
48 mIntConstExprAnyCast // As mIntConstExpr plus accept any cast.
49)
50
51// Parameter represents a function parameter.
52type Parameter struct {
53 d *Declarator
54 typ Type
55}
56
57// NewParameter returns a newly created parameter
58func NewParameter(d *Declarator, t Type) *Parameter {
59 return &Parameter{d, t}
60}
61
62func (p *Parameter) Declarator() *Declarator { return p.d }
63func (p *Parameter) Name() StringID { return p.d.Name() }
64func (p *Parameter) Type() Type { return p.typ }
65
66func (n *TranslationUnit) check(ctx *context) {
67 for n := n; n != nil; n = n.TranslationUnit {
68 n.ExternalDeclaration.check(ctx)
69 }
70 for ; n != nil; n = n.TranslationUnit {
71 n.ExternalDeclaration.checkFnBodies(ctx)
72 }
73}
74
75func (n *ExternalDeclaration) checkFnBodies(ctx *context) {
76 if n == nil {
77 return
78 }
79
80 switch n.Case {
81 case ExternalDeclarationFuncDef: // FunctionDefinition
82 n.FunctionDefinition.checkBody(ctx)
83 }
84}
85
86// https://gcc.gnu.org/onlinedocs/gcc/Inline.html
87//
88// If you specify both inline and extern in the function definition, then the
89// definition is used only for inlining. In no case is the function compiled on
90// its own, not even if you refer to its address explicitly. Such an address
91// becomes an external reference, as if you had only declared the function, and
92// had not defined it.
93//
94// This combination of inline and extern has almost the effect of a macro. The
95// way to use it is to put a function definition in a header file with these
96// keywords, and put another copy of the definition (lacking inline and extern)
97// in a library file. The definition in the header file causes most calls to
98// the function to be inlined. If any uses of the function remain, they refer
99// to the single copy in the library.
100func (n *Declarator) isExternInline() bool {
101 return n.IsExtern() && n.Type() != nil && n.Type().Inline()
102}
103
104// DeclarationSpecifiers Declarator DeclarationList CompoundStatement
105func (n *FunctionDefinition) checkBody(ctx *context) {
106 if n == nil {
107 return
108 }
109
110 if n.checked {
111 return
112 }
113
114 n.checked = true
115 if n.Declarator.isExternInline() && !ctx.cfg.CheckExternInlineFnBodies {
116 return
117 }
118
119 ctx.checkFn = n
120 rd := ctx.readDelta
121 ctx.readDelta = 1
122 n.CompoundStatement.check(ctx)
123 ctx.checkFn = nil
124 for k, v := range n.ComputedGotos {
125 if _, ok := n.Labels[k]; !ok {
126 ctx.errNode(v, "label %s undefined", k)
127 }
128 }
129 for k, v := range n.Gotos {
130 if _, ok := n.Labels[k]; !ok {
131 ctx.errNode(v, "label %s undefined", k)
132 }
133 }
134 for _, n := range n.InitDeclarators {
135 d := n.Declarator
136 if d.Type().IsIncomplete() && d.Linkage != External {
137 ctx.errNode(d, "declarator has incomplete type")
138 }
139 if ctx.cfg.RejectUninitializedDeclarators && d.Linkage == None && d.Write == 0 && !d.AddressTaken && d.Read != 0 {
140 switch d.Type().Kind() {
141 case Array, Struct, Union, Invalid:
142 // nop
143 default:
144 ctx.errNode(d, "%s may be used uninitialized in this function", d.Name())
145 }
146 }
147 }
148 for _, n := range n.CompositeLiterals {
149 switch t := n.Operand.Type(); t.Kind() {
150 case Invalid:
151 ctx.errNode(n, "composite literal has invalid type")
152 default:
153 if t.IsIncomplete() {
154 ctx.errNode(n, "composite literal has incomplete type")
155 }
156 }
157 }
158 ctx.readDelta = rd
159}
160
161func (n *ExternalDeclaration) check(ctx *context) {
162 if n == nil {
163 return
164 }
165
166 switch n.Case {
167 case ExternalDeclarationFuncDef: // FunctionDefinition
168 n.FunctionDefinition.checkDeclarator(ctx)
169 case ExternalDeclarationDecl: // Declaration
170 n.Declaration.check(ctx, true)
171 case ExternalDeclarationAsm: // AsmFunctionDefinition
172 n.AsmFunctionDefinition.check(ctx)
173 case ExternalDeclarationAsmStmt: // AsmStatement
174 n.AsmStatement.check(ctx)
175 case ExternalDeclarationEmpty: // ';'
176 // nop
177 case ExternalDeclarationPragma: // PragmaSTDC
178 n.PragmaSTDC.check(ctx)
179 default:
180 panic(todo(""))
181 }
182}
183
184func (n *PragmaSTDC) check(ctx *context) {
185 // nop
186}
187
188func (n *AsmFunctionDefinition) check(ctx *context) {
189 if n == nil {
190 return
191 }
192
193 typ, inline, noret := n.DeclarationSpecifiers.check(ctx, false)
194 typ.setFnSpecs(inline, noret)
195 n.Declarator.check(ctx, n.DeclarationSpecifiers, typ, true)
196 n.AsmStatement.check(ctx)
197}
198
199func (n *AsmStatement) check(ctx *context) {
200 if n == nil {
201 return
202 }
203
204 n.Asm.check(ctx)
205 n.AttributeSpecifierList.check(ctx, nil)
206}
207
208func (n *Declaration) check(ctx *context, tld bool) {
209 if n == nil {
210 return
211 }
212
213 typ, _, _ := n.DeclarationSpecifiers.check(ctx, false)
214 n.InitDeclaratorList.check(ctx, n.DeclarationSpecifiers, typ, tld)
215}
216
217func (n *InitDeclaratorList) check(ctx *context, td typeDescriptor, typ Type, tld bool) {
218 for ; n != nil; n = n.InitDeclaratorList {
219 n.AttributeSpecifierList.check(ctx, typ.baseP())
220 n.InitDeclarator.check(ctx, td, typ, tld)
221 }
222}
223
224func (n *InitDeclarator) check(ctx *context, td typeDescriptor, typ Type, tld bool) {
225 if n == nil {
226 return
227 }
228
229 if f := ctx.checkFn; f != nil {
230 f.InitDeclarators = append(f.InitDeclarators, n)
231 }
232 if attr := n.AttributeSpecifierList.check(ctx, typ.baseP()); len(attr) != 0 {
233 typ = &attributedType{typ, attr}
234 }
235 switch n.Case {
236 case InitDeclaratorDecl: // Declarator AttributeSpecifierList
237 n.Declarator.check(ctx, td, typ, tld)
238 case InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer
239 typ := n.Declarator.check(ctx, td, typ, tld)
240 n.Declarator.hasInitializer = true
241 n.Declarator.Write++
242 n.Initializer.check(ctx, &n.Initializer.list, typ, n.Declarator.StorageClass, nil, 0, nil, nil, false)
243 n.Initializer.setConstZero()
244 n.initializer = &InitializerValue{typ: typ, initializer: n.Initializer}
245 if ctx.cfg.TrackAssignments {
246 setLHS(map[*Declarator]struct{}{n.Declarator: {}}, n.Initializer)
247 }
248 default:
249 panic(todo(""))
250 }
251}
252
253func (n *Initializer) setConstZero() {
254 switch n.Case {
255 case InitializerExpr: // AssignmentExpression
256 if op := n.AssignmentExpression.Operand; op != nil {
257 n.isConst = op.IsConst()
258 n.isZero = op.IsZero()
259 }
260 case InitializerInitList: // '{' InitializerList ',' '}'
261 li := n.InitializerList
262 li.setConstZero()
263 n.isConst = li.IsConst()
264 n.isZero = li.IsZero()
265 default:
266 panic(todo("%v:", n.Position()))
267 }
268}
269
270func (n *InitializerList) setConstZero() {
271 if n == nil {
272 return
273 }
274
275 n0 := n
276 n0.isConst = true
277 n0.isZero = true
278 for ; n != nil; n = n.InitializerList {
279 in := n.Initializer
280 in.setConstZero()
281 n0.isConst = n0.isConst && in.isConst
282 n0.isZero = n0.isZero && in.isZero
283 }
284}
285
286// [0], 6.7.8 Initialization
287func (n *Initializer) check(ctx *context, list *[]*Initializer, t Type, sc StorageClass, fld Field, off uintptr, il *InitializerList, designatorList *DesignatorList, inList bool) *InitializerList {
288 // trc("==== %v: case %v, t %v, off %v, designatorList != nil %v, inList %v", n.Position(), n.Case, t.Alias(), off, designatorList != nil, inList)
289 // if fld != nil {
290 // trc("\tfld %q", fld.Name())
291 // }
292
293 // 3 - The type of the entity to be initialized shall be an array of
294 // unknown size or an object type that is not a variable length array
295 // type.
296 if t.Kind() == Array && t.IsVLA() {
297 ctx.errNode(n, "cannot initialize a variable length array: %v", t)
298 if il != nil {
299 return il.InitializerList
300 }
301
302 return nil
303 }
304
305 defer func(d int) { ctx.readDelta = d }(ctx.readDelta)
306
307 ctx.readDelta = 1
308 n.typ = t
309 single := n.single()
310 var op Operand
311 if single != nil {
312 op = single.AssignmentExpression.check(ctx, false)
313 single.typ = t
314 single.Field = fld
315 single.Offset = off
316 }
317
318 // 11: The initializer for a scalar shall be a single expression, optionally
319 // enclosed in braces. The initial value of the object is that of the
320 // expression (after conversion); the same type constraints and conversions as
321 // for simple assignment apply, taking the type of the scalar to be the
322 // unqualified version of its declared type.
323 if t.IsScalarType() && single != nil {
324 if designatorList != nil {
325 panic(todo("", n.Position()))
326 }
327
328 //TODO check compatible
329 *list = append(*list, single)
330 switch {
331 case t.Kind() == op.Type().Kind():
332 single.AssignmentExpression.InitializerOperand = op
333 default:
334 single.AssignmentExpression.InitializerOperand = op.convertTo(ctx, n, t)
335 }
336 if il != nil {
337 return il.InitializerList
338 }
339
340 return nil
341 }
342
343 // 12: The rest of this subclause deals with initializers for objects that have
344 // aggregate or union type.
345
346 k := t.Kind()
347
348 // 13: The initializer for a structure or union object that has automatic
349 // storage duration shall be either an initializer list as described below, or
350 // a single expression that has compatible structure or union type. In the
351 // latter case, the initial value of the object, including unnamed members, is
352 // that of the expression.
353 if n.Case == InitializerExpr && sc == Automatic && (k == Struct || k == Union || k == Vector) && t.IsCompatible(op.Type()) {
354 if designatorList != nil {
355 panic(todo("", n.Position()))
356 }
357
358 *list = append(*list, single)
359 if il != nil {
360 return il.InitializerList
361 }
362
363 return nil
364 }
365
366 if k == Array && single != nil {
367 et := t.Elem()
368 switch {
369 case isCharType(et):
370 // 14: An array of character type may be initialized by a character string
371 // literal, optionally enclosed in braces. Successive characters of the
372 // character string literal (including the terminating null character if there
373 // is room or if the array is of unknown size) initialize the elements of the
374 // array.
375 if x, ok := op.Value().(StringValue); ok {
376 if designatorList != nil {
377 panic(todo("", n.Position()))
378 }
379
380 *list = append(*list, single)
381 str := StringID(x).String()
382 if t.IsIncomplete() {
383 t.setLen(uintptr(len(str)) + 1)
384 }
385 if il != nil {
386 return il.InitializerList
387 }
388
389 return nil
390 }
391 case isWCharType(et):
392 // 15: An array with element type compatible with wchar_t may be initialized by
393 // a wide string literal, optionally enclosed in braces. Successive wide
394 // characters of the wide string literal (including the terminating null wide
395 // character if there is room or if the array is of unknown size) initialize
396 // the elements of the array.
397 if x, ok := op.Value().(WideStringValue); ok {
398 if designatorList != nil {
399 panic(todo("", n.Position()))
400 }
401
402 *list = append(*list, single)
403 str := []rune(StringID(x).String())
404 if t.IsIncomplete() {
405 t.setLen(uintptr(len(str)) + 1)
406 }
407 if il != nil {
408 panic(todo(""))
409 }
410
411 return nil
412 }
413 }
414 }
415
416 // 16: Otherwise, the initializer for an object that has aggregate or union
417 // type shall be a brace-enclosed list of initializers for the elements or
418 // named members.
419 if n.Case == InitializerExpr {
420 if il != nil {
421 switch t.Kind() {
422 case Array:
423 return il.checkArray(ctx, list, t, sc, off, designatorList, inList)
424 case Struct:
425 return il.checkStruct(ctx, list, t, sc, off, designatorList, inList)
426 case Union:
427 return il.checkUnion(ctx, list, t, sc, off, designatorList, inList)
428 case Vector:
429 return il.InitializerList //TODO
430 default:
431 panic(todo("", n.Position(), t, t.Kind()))
432 }
433 }
434
435 var l *InitializerList
436 Inspect(n.AssignmentExpression, func(m Node, b bool) bool {
437 if x, ok := m.(*PostfixExpression); ok && x.Case == PostfixExpressionComplit {
438 if !b {
439 return true
440 }
441
442 if l == nil {
443 l = x.InitializerList
444 return true
445 }
446
447 l = nil
448 return false
449 }
450 return true
451 })
452 if l != nil {
453 l.check(ctx, list, t, sc, off, designatorList, inList)
454 return nil
455 }
456
457 ctx.errNode(n, "initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members: %v", t)
458 return nil
459 }
460
461 n.InitializerList.check(ctx, list, t, sc, off, designatorList, inList)
462 if il != nil {
463 return il.InitializerList
464 }
465
466 return nil
467}
468
469func (n *InitializerList) checkArray(ctx *context, list *[]*Initializer, t Type, sc StorageClass, off uintptr, designatorList *DesignatorList, inList bool) *InitializerList {
470 elem := t.Elem()
471 esz := elem.Size()
472 length := t.Len()
473 var i, maxI uintptr
474 nestedDesignator := designatorList != nil
475 retOnDesignator := false
476loop:
477 for n != nil {
478 switch {
479 case retOnDesignator && n.Designation != nil:
480 return n
481 case designatorList == nil && !inList && n.Designation != nil:
482 designatorList = n.Designation.DesignatorList
483 fallthrough
484 case designatorList != nil:
485 d := designatorList.Designator
486 designatorList = designatorList.DesignatorList
487 switch d.Case {
488 case DesignatorIndex: // '[' ConstantExpression ']'
489 switch x := d.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false).Value().(type) {
490 case Int64Value:
491 i = uintptr(x)
492 case Uint64Value:
493 i = uintptr(x)
494 default:
495 panic(todo("%v: %T", n.Position(), x))
496 }
497 if !inList && i > maxI {
498 maxI = i
499 }
500 case DesignatorField: // '.' IDENTIFIER
501 panic(todo("", n.Position(), d.Position()))
502 case DesignatorField2: // IDENTIFIER ':'
503 panic(todo("", n.Position(), d.Position()))
504 default:
505 panic(todo(""))
506 }
507
508 n = n.Initializer.check(ctx, list, elem, sc, nil, off+i*esz, n, designatorList, designatorList != nil)
509 designatorList = nil
510 if nestedDesignator {
511 retOnDesignator = true
512 }
513 i++
514 default:
515 if !t.IsIncomplete() && i >= length {
516 break loop
517 }
518
519 if i > maxI {
520 maxI = i
521 }
522 n = n.Initializer.check(ctx, list, elem, sc, nil, off+i*esz, n, nil, inList)
523 i++
524 }
525 }
526 if t.IsIncomplete() {
527 t.setLen(maxI + 1)
528 }
529 return n
530}
531
532func (n *InitializerList) checkStruct(ctx *context, list *[]*Initializer, t Type, sc StorageClass, off uintptr, designatorList *DesignatorList, inList bool) *InitializerList {
533 // trc("==== (A) %v: t %v, off %v, dl %v, inList %v", n.Position(), t, off, designatorList != nil, inList)
534 // defer trc("==== (Z) %v: t %v, off %v, dl %v, inList %v", n.Position(), t, off, designatorList != nil, inList)
535 t = t.underlyingType()
536 // trc("%v: %v, off %v", n.Position(), t, off) //TODO-
537 nf := t.NumField()
538 i := []int{0}
539 var f Field
540 nestedDesignator := designatorList != nil
541 retOnDesignator := false
542 for n != nil {
543 switch {
544 case retOnDesignator && n.Designation != nil:
545 return n
546 case designatorList == nil && !inList && n.Designation != nil:
547 designatorList = n.Designation.DesignatorList
548 fallthrough
549 case designatorList != nil:
550 d := designatorList.Designator
551 designatorList = designatorList.DesignatorList
552 var nm StringID
553 switch d.Case {
554 case DesignatorIndex: // '[' ConstantExpression ']'
555 panic(todo("", n.Position(), d.Position()))
556 case DesignatorField: // '.' IDENTIFIER
557 nm = d.Token2.Value
558 case DesignatorField2: // IDENTIFIER ':'
559 nm = d.Token.Value
560 default:
561 panic(todo(""))
562 }
563
564 f, xa, ok := t.FieldByName2(nm)
565 if !ok {
566 panic(todo("%v: t %v %q", d.Position(), t, nm))
567 }
568
569 t0 := t
570 switch {
571 case len(xa) != 1:
572 var f2 Field
573 var off2 uintptr
574 for len(xa) != 1 {
575 f2 = t.FieldByIndex(xa[:1])
576 off2 += f2.Offset()
577 t = f2.Type()
578 xa = xa[1:]
579 }
580 n = n.Initializer.check(ctx, list, t, sc, f, off+off2, n, designatorList, designatorList != nil)
581 if t.Kind() == Union {
582 t = t0
583 }
584 default:
585 n = n.Initializer.check(ctx, list, f.Type(), sc, f, off+f.Offset(), n, designatorList, designatorList != nil)
586 }
587 designatorList = nil
588 if nestedDesignator {
589 retOnDesignator = true
590 }
591 i[0] = xa[0] + 1
592 default:
593 // [0], 6.7.8 Initialization
594 //
595 // 9 - Except where explicitly stated otherwise, for the
596 // purposes of this subclause unnamed members of objects of
597 // structure and union type do not participate in
598 // initialization. Unnamed members of structure objects have
599 // indeterminate value even after initialization.
600 for ; ; i[0]++ {
601 if i[0] >= nf {
602 return n
603 }
604
605 f = t.FieldByIndex(i)
606 if f.Name() != 0 || !f.Type().IsBitFieldType() {
607 n = n.Initializer.check(ctx, list, f.Type(), sc, f, off+f.Offset(), n, nil, inList)
608 i[0]++
609 break
610 }
611 }
612 }
613 }
614 return n
615}
616
617func spos(n Node) string {
618 p := n.Position()
619 p.Filename = filepath.Base(p.Filename)
620 return p.String()
621}
622
623func (n *InitializerList) checkUnion(ctx *context, list *[]*Initializer, t Type, sc StorageClass, off uintptr, designatorList *DesignatorList, inList bool) *InitializerList {
624 // trc("==== %v: t %v, off %v, dl %v, inList %v", n.Position(), t, off, designatorList != nil, inList)
625 t = t.underlyingType()
626 // trc("%v: %v, off %v", n.Position(), t, off) //TODO-
627 nf := t.NumField()
628 i := []int{0}
629 for pass := 0; n != nil; pass++ {
630 switch {
631 case designatorList == nil && !inList && n.Designation != nil:
632 designatorList = n.Designation.DesignatorList
633 fallthrough
634 case designatorList != nil:
635 d := designatorList.Designator
636 designatorList = designatorList.DesignatorList
637 var nm StringID
638 switch d.Case {
639 case DesignatorIndex: // '[' ConstantExpression ']'
640 panic(todo("", n.Position(), d.Position()))
641 case DesignatorField: // '.' IDENTIFIER
642 nm = d.Token2.Value
643 case DesignatorField2: // IDENTIFIER ':'
644 nm = d.Token.Value
645 default:
646 panic(todo(""))
647 }
648
649 f, xa, ok := t.FieldByName2(nm)
650 if !ok {
651 panic(todo("", d.Position()))
652 }
653
654 if !inList && pass == 0 {
655 n.Initializer.field0 = f
656 }
657 switch {
658 case len(xa) != 1:
659 var f2 Field
660 var off2 uintptr
661 for len(xa) != 1 {
662 f2 = t.FieldByIndex(xa[:1])
663 off2 += f2.Offset()
664 t = f2.Type()
665 xa = xa[1:]
666 }
667 next := n.Initializer.check(ctx, list, t, sc, f, off+off2+f.Offset(), n, designatorList, designatorList != nil)
668 if designatorList != nil && designatorList.DesignatorList != nil {
669 panic(todo("", n.Position(), d.Position()))
670 }
671
672 return next
673 default:
674 next := n.Initializer.check(ctx, list, f.Type(), sc, f, off+f.Offset(), n, designatorList, designatorList != nil)
675 if designatorList != nil && designatorList.DesignatorList != nil {
676 panic(todo("", n.Position(), d.Position()))
677 }
678
679 return next
680 }
681 default:
682 // [0], 6.7.8 Initialization
683 //
684 // 9 - Except where explicitly stated otherwise, for the
685 // purposes of this subclause unnamed members of objects of
686 // structure and union type do not participate in
687 // initialization. Unnamed members of structure objects have
688 // indeterminate value even after initialization.
689 for ; ; i[0]++ {
690 if i[0] >= nf {
691 panic(todo(""))
692 }
693
694 f := t.FieldByIndex(i)
695 if f.Name() != 0 || !f.Type().IsBitFieldType() {
696 next := n.Initializer.check(ctx, list, f.Type(), sc, f, off+f.Offset(), n, nil, inList)
697 return next
698 }
699 }
700 panic(todo("", n.Position()))
701 }
702 }
703 return nil
704}
705
706// Accept a single initializer, optionally enclosed in braces, but nested
707// braces. Implements eg. [0]6.7.8.11.
708//
709// 42 // ok
710// {42} // ok
711// {{42}} // not ok
712func (n *Initializer) single() *Initializer {
713 switch n.Case {
714 case InitializerExpr: // AssignmentExpression
715 return n
716 case InitializerInitList: // '{' InitializerList ',' '}'
717 if n.InitializerList == nil { //
718 return nil
719 }
720
721 if n.InitializerList.InitializerList == nil {
722 if in := n.InitializerList.Initializer; in.Case == InitializerExpr {
723 return in
724 }
725 }
726 }
727 return nil
728}
729
730// [0], 6.7.8 Initialization
731func (n *InitializerList) check(ctx *context, list *[]*Initializer, t Type, sc StorageClass, off uintptr, designatorList *DesignatorList, inList bool) {
732 switch t.Kind() {
733 case Array, Vector:
734 if n == nil { // {}
735 if t.IsIncomplete() {
736 t.setLen(0)
737 }
738 return
739 }
740
741 n.checkArray(ctx, list, t, sc, off, designatorList, inList)
742 case Struct:
743 if n == nil { // {}
744 return
745 }
746
747 n.checkStruct(ctx, list, t, sc, off, designatorList, inList)
748 case Union:
749 if n == nil { // {}
750 return
751 }
752
753 n.checkUnion(ctx, list, t, sc, off, designatorList, inList)
754 default:
755 if n == nil || t == nil || t.Kind() == Invalid {
756 return
757 }
758
759 n.Initializer.check(ctx, list, t, sc, nil, off, nil, designatorList, inList)
760 }
761}
762
763func setLHS(lhs map[*Declarator]struct{}, rhs Node) {
764 inCall := 0
765 Inspect(rhs, func(n Node, enter bool) bool {
766 switch x := n.(type) {
767 case *PostfixExpression:
768 switch x.Case {
769 case PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
770 switch {
771 case enter:
772 inCall++
773 if d := x.Declarator(); d != nil {
774 for v := range lhs {
775 d.setLHS(v)
776 }
777 }
778 default:
779 inCall--
780 }
781 }
782 case *PrimaryExpression:
783 if inCall != 0 || !enter {
784 break
785 }
786
787 if d := x.Declarator(); d != nil {
788 for v := range lhs {
789 d.setLHS(v)
790 }
791 }
792 }
793 return true
794 })
795}
796
797func (n *AssignmentExpression) check(ctx *context, isAsmArg bool) Operand {
798 if n == nil {
799 return noOperand
800 }
801
802 if n.Operand != nil {
803 return n.Operand
804 }
805
806 if ctx.cfg.TrackAssignments && n.AssignmentExpression != nil {
807 defer func() {
808 lhs := map[*Declarator]struct{}{}
809 Inspect(n.UnaryExpression, func(n Node, enter bool) bool {
810 if !enter {
811 return true
812 }
813
814 if x, ok := n.(*PrimaryExpression); ok {
815 lhs[x.Declarator()] = struct{}{}
816 }
817 return true
818 })
819 setLHS(lhs, n.AssignmentExpression)
820 }()
821 }
822
823 //TODO check for "modifiable lvalue" in left operand
824 n.Operand = noOperand
825 switch n.Case {
826 case AssignmentExpressionCond: // ConditionalExpression
827 n.Operand = n.ConditionalExpression.check(ctx, isAsmArg)
828 n.IsSideEffectsFree = n.ConditionalExpression.IsSideEffectsFree
829 case AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
830 l := n.UnaryExpression.check(ctx, isAsmArg)
831 if d := n.UnaryExpression.Declarator(); d != nil {
832 d.Read -= ctx.readDelta
833 }
834 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
835 d.Write++
836 if l.Type().Kind() == Array && !d.IsParameter && l.Type().String() != "va_list" {
837 ctx.errNode(n.UnaryExpression, "assignment to expression with array type")
838 break
839 }
840 }
841
842 if !l.IsLValue() {
843 //TODO ctx.errNode(n.UnaryExpression, "expected lvalue")
844 break
845 }
846
847 r := n.AssignmentExpression.check(ctx, isAsmArg)
848 _ = r //TODO check assignability
849 n.Operand = l.(*lvalue).Operand
850 case AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
851 l := n.UnaryExpression.check(ctx, isAsmArg)
852 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
853 d.SubjectOfAsgnOp = true
854 d.Read += ctx.readDelta
855 d.Write++
856 }
857 if !l.IsLValue() {
858 //TODO panic(n.Position().String()) // report error
859 break
860 }
861
862 r := n.AssignmentExpression.check(ctx, isAsmArg)
863 //TODO check assignability
864 if l.Type().IsArithmeticType() {
865 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
866 n.promote = op.Type()
867 }
868 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
869 case AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
870 l := n.UnaryExpression.check(ctx, isAsmArg)
871 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
872 d.SubjectOfAsgnOp = true
873 d.Read += ctx.readDelta
874 d.Write++
875 }
876 if !l.IsLValue() {
877 //TODO panic(n.Position().String()) // report error
878 break
879 }
880
881 r := n.AssignmentExpression.check(ctx, isAsmArg)
882 //TODO check assignability
883 if l.Type().IsArithmeticType() {
884 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
885 n.promote = op.Type()
886 }
887 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
888 case AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
889 l := n.UnaryExpression.check(ctx, isAsmArg)
890 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
891 d.SubjectOfAsgnOp = true
892 d.Read += ctx.readDelta
893 d.Write++
894 }
895 if !l.IsLValue() {
896 //TODO panic(n.Position().String()) // report error
897 break
898 }
899
900 r := n.AssignmentExpression.check(ctx, isAsmArg)
901 //TODO check assignability
902 if l.Type().IsArithmeticType() {
903 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
904 n.promote = op.Type()
905 }
906 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
907 case AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
908 l := n.UnaryExpression.check(ctx, isAsmArg)
909 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
910 d.SubjectOfAsgnOp = true
911 d.Read += ctx.readDelta
912 d.Write++
913 }
914 if !l.IsLValue() {
915 //TODO panic(n.Position().String()) // report error
916 break
917 }
918
919 r := n.AssignmentExpression.check(ctx, isAsmArg)
920 //TODO check assignability
921 n.promote = n.UnaryExpression.Operand.Type()
922 if l.Type().IsArithmeticType() {
923 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
924 n.promote = op.Type()
925 }
926 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
927 case AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
928 l := n.UnaryExpression.check(ctx, isAsmArg)
929 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
930 d.SubjectOfAsgnOp = true
931 d.Read += ctx.readDelta
932 d.Write++
933 }
934 if !l.IsLValue() {
935 //TODO panic(n.Position().String()) // report error
936 break
937 }
938
939 r := n.AssignmentExpression.check(ctx, isAsmArg)
940 //TODO check assignability
941 n.promote = n.UnaryExpression.Operand.Type()
942 if l.Type().IsArithmeticType() {
943 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
944 n.promote = op.Type()
945 }
946 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
947 case AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
948 l := n.UnaryExpression.check(ctx, isAsmArg)
949 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
950 d.SubjectOfAsgnOp = true
951 d.Read += ctx.readDelta
952 d.Write++
953 }
954 if !l.IsLValue() {
955 //TODO panic(n.Position().String()) // report error
956 break
957 }
958
959 r := n.AssignmentExpression.check(ctx, isAsmArg)
960 //TODO check assignability
961 if !l.Type().IsIntegerType() || !r.Type().IsIntegerType() {
962 //TODO report error
963 break
964 }
965
966 n.promote = r.integerPromotion(ctx, n).Type()
967 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: l.Type()}).integerPromotion(ctx, n)
968 case AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
969 l := n.UnaryExpression.check(ctx, isAsmArg)
970 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
971 d.SubjectOfAsgnOp = true
972 d.Read += ctx.readDelta
973 d.Write++
974 }
975 if !l.IsLValue() {
976 //TODO panic(n.Position().String()) // report error
977 break
978 }
979
980 r := n.AssignmentExpression.check(ctx, isAsmArg)
981 //TODO check assignability
982 if !l.Type().IsIntegerType() || !r.Type().IsIntegerType() {
983 //TODO report error
984 break
985 }
986
987 n.promote = r.integerPromotion(ctx, n).Type()
988 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: l.Type()}).integerPromotion(ctx, n)
989 case AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
990 l := n.UnaryExpression.check(ctx, isAsmArg)
991 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
992 d.SubjectOfAsgnOp = true
993 d.Read += ctx.readDelta
994 d.Write++
995 }
996 if !l.IsLValue() {
997 //TODO panic(n.Position().String()) // report error
998 break
999 }
1000
1001 r := n.AssignmentExpression.check(ctx, isAsmArg)
1002 //TODO check assignability
1003 if !l.Type().IsIntegerType() || !r.Type().IsIntegerType() {
1004 //TODO report error
1005 break
1006 }
1007
1008 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
1009 n.promote = op.Type()
1010 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
1011 case AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
1012 l := n.UnaryExpression.check(ctx, isAsmArg)
1013 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
1014 d.SubjectOfAsgnOp = true
1015 d.Read += ctx.readDelta
1016 d.Write++
1017 }
1018 if !l.IsLValue() {
1019 //TODO panic(n.Position().String()) // report error
1020 break
1021 }
1022
1023 r := n.AssignmentExpression.check(ctx, isAsmArg)
1024 //TODO check assignability
1025 if !l.Type().IsIntegerType() || !r.Type().IsIntegerType() {
1026 //TODO report error
1027 break
1028 }
1029
1030 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
1031 n.promote = op.Type()
1032 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
1033 case AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
1034 l := n.UnaryExpression.check(ctx, isAsmArg)
1035 if d := n.UnaryExpression.Operand.Declarator(); d != nil {
1036 d.SubjectOfAsgnOp = true
1037 d.Read += ctx.readDelta
1038 d.Write++
1039 }
1040 if !l.IsLValue() {
1041 //TODO panic(n.Position().String()) // report error
1042 break
1043 }
1044
1045 r := n.AssignmentExpression.check(ctx, isAsmArg)
1046 //TODO check assignability
1047 if !l.Type().IsIntegerType() || !r.Type().IsIntegerType() {
1048 //TODO report error
1049 break
1050 }
1051
1052 op, _ := usualArithmeticConversions(ctx, n, l, r, true)
1053 n.promote = op.Type()
1054 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: l.Type()}
1055 default:
1056 panic(todo(""))
1057 }
1058 return n.Operand
1059}
1060
1061func (n *UnaryExpression) check(ctx *context, isAsmArg bool) Operand {
1062 if n == nil {
1063 return noOperand
1064 }
1065
1066 n.Operand = noOperand //TODO-
1067 switch n.Case {
1068 case UnaryExpressionPostfix: // PostfixExpression
1069 n.Operand = n.PostfixExpression.check(ctx, false, isAsmArg)
1070 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
1071 case UnaryExpressionInc: // "++" UnaryExpression
1072 op := n.UnaryExpression.check(ctx, isAsmArg)
1073 if d := op.Declarator(); d != nil {
1074 d.SubjectOfIncDec = true
1075 d.Read += ctx.readDelta
1076 d.Write++
1077 }
1078 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
1079 case UnaryExpressionDec: // "--" UnaryExpression
1080 op := n.UnaryExpression.check(ctx, isAsmArg)
1081 if d := op.Declarator(); d != nil {
1082 d.SubjectOfIncDec = true
1083 d.Read += ctx.readDelta
1084 d.Write++
1085 }
1086 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
1087 case UnaryExpressionAddrof: // '&' CastExpression
1088 ctx.not(n, mIntConstExpr)
1089 op := n.CastExpression.addrOf(ctx)
1090 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1091 if op.Type().IsBitFieldType() {
1092 //TODO report error
1093 break
1094 }
1095
1096 d := n.CastExpression.Declarator()
1097 if d != nil {
1098 setAddressTaken(n, d, "'&' CastExpression")
1099 if d.td.register() {
1100 //TODO report error
1101 }
1102 }
1103
1104 // [0], 6.5.3.2
1105 //
1106 // The operand of the unary & operator shall be either a
1107 // function designator, the result of a [] or unary * operator,
1108 // or an lvalue that designates an object that is not a
1109 // bit-field and is not declared with the register
1110 // storage-class specifier.
1111 //TODO
1112 if x, ok := op.(*funcDesignator); ok {
1113 n.Operand = x
1114 break
1115 }
1116
1117 n.Operand = op
1118 case UnaryExpressionDeref: // '*' CastExpression
1119 ctx.not(n, mIntConstExpr)
1120 op := n.CastExpression.check(ctx, isAsmArg)
1121 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1122 if x, ok := op.(*funcDesignator); ok {
1123 n.Operand = x
1124 break
1125 }
1126
1127 if op.Type().Kind() == Function {
1128 n.Operand = op
1129 break
1130 }
1131
1132 if op.Type().Decay().Kind() != Ptr {
1133 //TODO report error
1134 break
1135 }
1136
1137 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: op.Type().Elem()}}
1138 case UnaryExpressionPlus: // '+' CastExpression
1139 op := n.CastExpression.check(ctx, isAsmArg)
1140 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1141 if op == nil {
1142 //TODO report error
1143 break
1144 }
1145 if !op.Type().IsArithmeticType() {
1146 //TODO report error
1147 break
1148 }
1149
1150 if op.Type().IsIntegerType() {
1151 op = op.integerPromotion(ctx, n)
1152 }
1153 n.Operand = op
1154 case UnaryExpressionMinus: // '-' CastExpression
1155 op := n.CastExpression.check(ctx, isAsmArg)
1156 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1157 if op == nil {
1158 //TODO report error
1159 break
1160 }
1161 if op.Type().Kind() == Vector {
1162 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
1163 break
1164 }
1165
1166 if !op.Type().IsArithmeticType() {
1167 //TODO report error
1168 break
1169 }
1170
1171 if op.Type().IsIntegerType() {
1172 op = op.integerPromotion(ctx, n)
1173 }
1174 if v := op.Value(); v != nil {
1175 op = (&operand{abi: &ctx.cfg.ABI, typ: op.Type(), value: v.neg()}).normalize(ctx, n)
1176 }
1177 n.Operand = op
1178 case UnaryExpressionCpl: // '~' CastExpression
1179 op := n.CastExpression.check(ctx, isAsmArg)
1180 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1181 if op.Type().Kind() == Vector {
1182 if !op.Type().Elem().IsIntegerType() {
1183 ctx.errNode(n, "operand must be integer")
1184 }
1185 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
1186 break
1187 }
1188
1189 if op.Type().IsComplexType() {
1190 n.Operand = op
1191 break
1192 }
1193
1194 if !op.Type().IsIntegerType() {
1195 ctx.errNode(n, "operand must be integer")
1196 break
1197 }
1198
1199 op = op.integerPromotion(ctx, n)
1200 if v := op.Value(); v != nil {
1201 op = (&operand{abi: &ctx.cfg.ABI, typ: op.Type(), value: v.cpl()}).normalize(ctx, n)
1202 }
1203 n.Operand = op
1204 case UnaryExpressionNot: // '!' CastExpression
1205 op := n.CastExpression.check(ctx, isAsmArg)
1206 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1207 op2 := &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int)}
1208 switch {
1209 case op.IsZero():
1210 op2.value = Int64Value(1)
1211 case op.IsNonZero():
1212 op2.value = Int64Value(0)
1213 }
1214 n.Operand = op2
1215 case UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
1216 n.IsSideEffectsFree = true
1217 rd := ctx.readDelta
1218 // [0]6.5.3.4, 2: If the type of the operand is a variable length array type,
1219 // the operand is evaluated; otherwise, the operand is not evaluated and the
1220 // result is an integer constant.
1221 switch op := n.UnaryExpression.Operand; {
1222 case op != nil && op.Type() != nil && op.Type().IsVLA():
1223 ctx.readDelta = 1
1224 default:
1225 ctx.readDelta = 0
1226 }
1227 ctx.push(ctx.mode &^ mIntConstExpr)
1228 op := n.UnaryExpression.check(ctx, isAsmArg)
1229 ctx.pop()
1230 ctx.readDelta = rd
1231 if op.Type().IsIncomplete() {
1232 break
1233 }
1234
1235 sz := op.Type().Size()
1236 if d := n.UnaryExpression.Declarator(); d != nil && d.IsParameter {
1237 sz = op.Type().Decay().Size()
1238 }
1239 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ULongLong), value: Uint64Value(sz)}).convertTo(ctx, n, sizeT(ctx, n.lexicalScope, n.Token))
1240 case UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
1241 n.IsSideEffectsFree = true
1242 rd := ctx.readDelta
1243 ctx.readDelta = 0
1244 ctx.push(ctx.mode)
1245 if ctx.mode&mIntConstExpr != 0 {
1246 ctx.mode |= mIntConstExprAnyCast
1247 }
1248 t := n.TypeName.check(ctx, false, false, nil)
1249 ctx.pop()
1250 ctx.readDelta = rd
1251 if t.IsIncomplete() {
1252 break
1253 }
1254
1255 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ULongLong), value: Uint64Value(t.Size())}).convertTo(ctx, n, sizeT(ctx, n.lexicalScope, n.Token))
1256 case UnaryExpressionLabelAddr: // "&&" IDENTIFIER
1257 abi := &ctx.cfg.ABI
1258 n.Operand = &operand{abi: abi, typ: abi.Ptr(n, abi.Type(Void))}
1259 n.IsSideEffectsFree = true
1260 ctx.not(n, mIntConstExpr)
1261 f := ctx.checkFn
1262 if f == nil {
1263 //TODO report error
1264 break
1265 }
1266
1267 if f.ComputedGotos == nil {
1268 f.ComputedGotos = map[StringID]*UnaryExpression{}
1269 }
1270 f.ComputedGotos[n.Token2.Value] = n
1271 case UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
1272 n.IsSideEffectsFree = true
1273 ctx.push(ctx.mode &^ mIntConstExpr)
1274 op := n.UnaryExpression.check(ctx, isAsmArg)
1275 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ULongLong), value: Uint64Value(op.Type().Align())}).convertTo(ctx, n, sizeT(ctx, n.lexicalScope, n.Token))
1276 ctx.pop()
1277 case UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
1278 n.IsSideEffectsFree = true
1279 ctx.push(ctx.mode)
1280 if ctx.mode&mIntConstExpr != 0 {
1281 ctx.mode |= mIntConstExprAnyCast
1282 }
1283 t := n.TypeName.check(ctx, false, false, nil)
1284 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ULongLong), value: Uint64Value(t.Align())}).convertTo(ctx, n, sizeT(ctx, n.lexicalScope, n.Token))
1285 ctx.pop()
1286 case UnaryExpressionImag: // "__imag__" UnaryExpression
1287 ctx.not(n, mIntConstExpr)
1288 n.UnaryExpression.check(ctx, isAsmArg)
1289 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
1290 n.Operand = complexPart(ctx, n.UnaryExpression.Operand)
1291 case UnaryExpressionReal: // "__real__" UnaryExpression
1292 ctx.not(n, mIntConstExpr)
1293 n.UnaryExpression.check(ctx, isAsmArg)
1294 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
1295 n.Operand = complexPart(ctx, n.UnaryExpression.Operand)
1296 default:
1297 panic(todo(""))
1298 }
1299 return n.Operand
1300}
1301
1302func complexPart(ctx *context, op Operand) Operand {
1303 var k Kind
1304 switch op.Type().Kind() {
1305 case ComplexChar:
1306 k = Char
1307 case ComplexDouble:
1308 k = Double
1309 case ComplexFloat:
1310 k = Float
1311 case ComplexInt:
1312 k = Int
1313 case ComplexLong:
1314 k = Long
1315 case ComplexLongDouble:
1316 k = LongDouble
1317 case ComplexLongLong:
1318 k = LongLong
1319 case ComplexShort:
1320 k = Short
1321 case ComplexUInt:
1322 k = UInt
1323 case ComplexULong:
1324 k = ULong
1325 case ComplexULongLong:
1326 k = ULongLong
1327 case ComplexUShort:
1328 k = UShort
1329 default:
1330 //TODO report err
1331 return noOperand
1332 }
1333
1334 abi := &ctx.cfg.ABI
1335 typ := abi.Type(k)
1336 return &operand{abi: abi, typ: typ}
1337}
1338
1339func sizeT(ctx *context, s Scope, tok Token) Type {
1340 if t := ctx.sizeT; t != nil {
1341 return t
1342 }
1343
1344 t := ctx.stddef(idSizeT, s, tok)
1345 if t.Kind() != Invalid {
1346 ctx.sizeT = t
1347 }
1348 return t
1349}
1350
1351func (n *CastExpression) addrOf(ctx *context) Operand {
1352 if n == nil {
1353 return noOperand
1354 }
1355
1356 n.Operand = noOperand //TODO-
1357 switch n.Case {
1358 case CastExpressionUnary: // UnaryExpression
1359 n.Operand = n.UnaryExpression.addrOf(ctx)
1360 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
1361 case CastExpressionCast: // '(' TypeName ')' CastExpression
1362 panic(n.Position().String())
1363 default:
1364 panic(todo(""))
1365 }
1366 return n.Operand
1367}
1368
1369func (n *UnaryExpression) addrOf(ctx *context) Operand {
1370 if n == nil {
1371 return noOperand
1372 }
1373
1374 n.Operand = noOperand //TODO-
1375 switch n.Case {
1376 case UnaryExpressionPostfix: // PostfixExpression
1377 n.Operand = n.PostfixExpression.addrOf(ctx)
1378 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
1379 case UnaryExpressionInc: // "++" UnaryExpression
1380 panic(n.Position().String())
1381 case UnaryExpressionDec: // "--" UnaryExpression
1382 panic(n.Position().String())
1383 case UnaryExpressionAddrof: // '&' CastExpression
1384 panic(n.Position().String())
1385 case UnaryExpressionDeref: // '*' CastExpression
1386 n.Operand = n.CastExpression.check(ctx, false)
1387 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1388 case UnaryExpressionPlus: // '+' CastExpression
1389 panic(n.Position().String())
1390 case UnaryExpressionMinus: // '-' CastExpression
1391 panic(n.Position().String())
1392 case UnaryExpressionCpl: // '~' CastExpression
1393 panic(n.Position().String())
1394 case UnaryExpressionNot: // '!' CastExpression
1395 panic(n.Position().String())
1396 case UnaryExpressionSizeofExpr: // "sizeof" UnaryExpression
1397 panic(n.Position().String())
1398 case UnaryExpressionSizeofType: // "sizeof" '(' TypeName ')'
1399 panic(n.Position().String())
1400 case UnaryExpressionLabelAddr: // "&&" IDENTIFIER
1401 panic(n.Position().String())
1402 case UnaryExpressionAlignofExpr: // "_Alignof" UnaryExpression
1403 panic(n.Position().String())
1404 case UnaryExpressionAlignofType: // "_Alignof" '(' TypeName ')'
1405 panic(n.Position().String())
1406 case UnaryExpressionImag: // "__imag__" UnaryExpression
1407 n.Operand = n.UnaryExpression.addrOf(ctx)
1408 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
1409 case UnaryExpressionReal: // "__real__" UnaryExpression
1410 n.Operand = n.UnaryExpression.addrOf(ctx)
1411 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
1412 default:
1413 panic(todo(""))
1414 }
1415 return n.Operand
1416}
1417
1418func (n *PostfixExpression) addrOf(ctx *context) Operand {
1419 if n == nil {
1420 return noOperand
1421 }
1422
1423 n.Operand = noOperand //TODO-
1424 switch n.Case {
1425 case PostfixExpressionPrimary: // PrimaryExpression
1426 n.Operand = n.PrimaryExpression.addrOf(ctx)
1427 n.IsSideEffectsFree = n.PrimaryExpression.IsSideEffectsFree
1428 case PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
1429 pe := n.PostfixExpression.check(ctx, false, false)
1430 if d := n.PostfixExpression.Declarator(); d != nil && d.Type().Kind() != Ptr {
1431 setAddressTaken(n, d, "PostfixExpression '[' Expression ']'")
1432 d.Read += ctx.readDelta
1433 }
1434 e := n.Expression.check(ctx, false)
1435 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree && n.Expression.IsSideEffectsFree
1436 t := pe.Type().Decay()
1437 if t.Kind() == Invalid {
1438 break
1439 }
1440
1441 if t.Kind() == Ptr {
1442 if t := e.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
1443 ctx.errNode(n.Expression, "index must be integer type, have %v", e.Type())
1444 break
1445 }
1446
1447 n.Operand = n.indexAddr(ctx, &n.Token, pe, e)
1448 break
1449 }
1450
1451 if pe.Type().Kind() == Vector {
1452 if t := e.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
1453 ctx.errNode(n.Expression, "index must be integer type, have %v", e.Type())
1454 break
1455 }
1456
1457 n.Operand = n.index(ctx, pe, e)
1458 break
1459 }
1460
1461 t = e.Type().Decay()
1462 if t.Kind() == Invalid {
1463 break
1464 }
1465
1466 if t.Kind() == Ptr {
1467 if t := pe.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
1468 ctx.errNode(n.Expression, "index must be integer type, have %v", pe.Type())
1469 break
1470 }
1471
1472 n.Operand = n.indexAddr(ctx, &n.Token, e, pe)
1473 break
1474 }
1475
1476 ctx.errNode(n, "invalid index expression %v[%v]", pe.Type(), e.Type())
1477 case PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
1478 panic(n.Position().String())
1479 case PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
1480 op := n.PostfixExpression.addrOf(ctx)
1481 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
1482 if d := n.PostfixExpression.Declarator(); d != nil {
1483 setAddressTaken(n, d, "PostfixExpression '.' IDENTIFIER")
1484 d.Read += ctx.readDelta
1485 }
1486 st := op.Type().Elem()
1487 if k := st.Kind(); k == Invalid || k != Struct && k != Union {
1488 //TODO report error
1489 break
1490 }
1491
1492 f, ok := st.FieldByName(n.Token2.Value)
1493 if !ok {
1494 ctx.errNode(&n.Token2, "unknown or ambiguous field: %s", n.Token2.Value)
1495 break
1496 }
1497
1498 n.Field = f
1499 ft := f.Type()
1500 if f.IsBitField() {
1501 //TODO report error
1502 break
1503 }
1504
1505 ot := ctx.cfg.ABI.Ptr(n, ft)
1506 switch {
1507 case op.IsConst():
1508 switch x := op.Value().(type) {
1509 case Uint64Value:
1510 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ot, value: x + Uint64Value(f.Offset())}
1511 return n.Operand
1512 case nil:
1513 // nop
1514 default:
1515 //TODO panic(todo(" %v: %T", n.Position(), x))
1516 }
1517
1518 fallthrough
1519 default:
1520 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ot, offset: op.Offset() + f.Offset()}, declarator: op.Declarator()}
1521 }
1522 case PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
1523 op := n.PostfixExpression.check(ctx, false, false)
1524 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
1525 if d := n.PostfixExpression.Declarator(); d != nil {
1526 d.Read += ctx.readDelta
1527 }
1528 t := op.Type()
1529 if k := t.Decay().Kind(); k == Invalid || k != Ptr {
1530 //TODO report error
1531 break
1532 }
1533
1534 st := t.Elem()
1535 if k := st.Kind(); k == Invalid || k != Struct && k != Union {
1536 //TODO report error
1537 break
1538 }
1539
1540 f, ok := st.FieldByName(n.Token2.Value)
1541 if !ok {
1542 //TODO report error
1543 break
1544 }
1545
1546 n.Field = f
1547 ft := f.Type()
1548 if f.IsBitField() {
1549 //TODO report error
1550 break
1551 }
1552
1553 ot := ctx.cfg.ABI.Ptr(n, ft)
1554 switch {
1555 case op.IsConst():
1556 switch x := op.Value().(type) {
1557 case Uint64Value:
1558 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ot, value: x + Uint64Value(f.Offset())}
1559 return n.Operand
1560 case nil:
1561 // nop
1562 default:
1563 panic(todo(" %T", x))
1564 }
1565
1566 fallthrough
1567 default:
1568 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ot, offset: op.Offset() + f.Offset()}, declarator: op.Declarator()}
1569 }
1570 case PostfixExpressionInc: // PostfixExpression "++"
1571 panic(n.Position().String())
1572 case PostfixExpressionDec: // PostfixExpression "--"
1573 panic(n.Position().String())
1574 case PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
1575 //TODO IsSideEffectsFree
1576 if f := ctx.checkFn; f != nil {
1577 f.CompositeLiterals = append(f.CompositeLiterals, n)
1578 }
1579 t := n.TypeName.check(ctx, false, false, nil)
1580 var v *InitializerValue
1581 if n.InitializerList != nil {
1582 n.InitializerList.isConst = true
1583 n.InitializerList.check(ctx, &n.InitializerList.list, t, Automatic, 0, nil, false)
1584 n.InitializerList.setConstZero()
1585 v = &InitializerValue{typ: ctx.cfg.ABI.Ptr(n, t), initializer: n.InitializerList}
1586 }
1587 n.Operand = &lvalue{Operand: (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, t), value: v}).normalize(ctx, n)}
1588 case PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
1589 panic(n.Position().String())
1590 default:
1591 panic(todo(""))
1592 }
1593 return n.Operand
1594}
1595
1596func (n *PostfixExpression) indexAddr(ctx *context, nd Node, pe, e Operand) Operand {
1597 var x uintptr
1598 hasx := false
1599 switch v := e.Value().(type) {
1600 case Int64Value:
1601 x = uintptr(v)
1602 hasx = true
1603 case Uint64Value:
1604 x = uintptr(v)
1605 hasx = true
1606 }
1607 off := x * pe.Type().Elem().Size()
1608 switch y := pe.Value().(type) {
1609 case StringValue, WideStringValue:
1610 if hasx {
1611 return &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, pe.Type().Elem()), value: pe.Value(), offset: off}}
1612 }
1613 case Uint64Value:
1614 if hasx {
1615 return &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, pe.Type().Elem()), value: y + Uint64Value(off)}}
1616 }
1617 }
1618
1619 if d := pe.Declarator(); d != nil && hasx {
1620 r := &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, pe.Type().Elem()), offset: pe.Offset() + off}, declarator: d}
1621 return r
1622 }
1623
1624 return &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, pe.Type().Elem())}}
1625}
1626
1627func (n *PrimaryExpression) addrOf(ctx *context) Operand {
1628 if n == nil {
1629 return noOperand
1630 }
1631
1632 n.Operand = noOperand //TODO-
1633 switch n.Case {
1634 case PrimaryExpressionIdent: // IDENTIFIER
1635 n.IsSideEffectsFree = true
1636 n.check(ctx, false, false)
1637 if d := n.Operand.Declarator(); d != nil {
1638 switch d.Type().Kind() {
1639 case Function:
1640 // nop //TODO ?
1641 default:
1642 setAddressTaken(n, d, "&IDENTIFIER")
1643 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, d.Type())}, declarator: d}
1644 }
1645 return n.Operand
1646 }
1647 if ctx.cfg.RejectLateBinding && !ctx.cfg.ignoreUndefinedIdentifiers {
1648 ctx.errNode(n, "front-end: undefined: %s", n.Token.Value)
1649 return noOperand
1650 }
1651
1652 //TODO
1653 case PrimaryExpressionInt: // INTCONST
1654 panic(n.Position().String())
1655 case PrimaryExpressionFloat: // FLOATCONST
1656 panic(n.Position().String())
1657 case PrimaryExpressionEnum: // ENUMCONST
1658 panic(n.Position().String())
1659 case PrimaryExpressionChar: // CHARCONST
1660 panic(n.Position().String())
1661 case PrimaryExpressionLChar: // LONGCHARCONST
1662 panic(n.Position().String())
1663 case PrimaryExpressionString: // STRINGLITERAL
1664 panic(n.Position().String())
1665 case PrimaryExpressionLString: // LONGSTRINGLITERAL
1666 panic(n.Position().String())
1667 case PrimaryExpressionExpr: // '(' Expression ')'
1668 n.Operand = n.Expression.addrOf(ctx)
1669 n.IsSideEffectsFree = n.Expression.IsSideEffectsFree
1670 case PrimaryExpressionStmt: // '(' CompoundStatement ')'
1671 panic(n.Position().String())
1672 default:
1673 panic(todo(""))
1674 }
1675 return n.Operand
1676}
1677
1678func (n *Expression) addrOf(ctx *context) Operand {
1679 if n == nil {
1680 return noOperand
1681 }
1682 n.Operand = noOperand //TODO-
1683 switch n.Case {
1684 case ExpressionAssign: // AssignmentExpression
1685 n.Operand = n.AssignmentExpression.addrOf(ctx)
1686 n.IsSideEffectsFree = n.AssignmentExpression.IsSideEffectsFree
1687 case ExpressionComma: // Expression ',' AssignmentExpression
1688 panic(n.Position().String())
1689 default:
1690 panic(todo(""))
1691 }
1692 return n.Operand
1693}
1694
1695func (n *AssignmentExpression) addrOf(ctx *context) Operand {
1696 if n == nil {
1697 return noOperand
1698 }
1699 n.Operand = noOperand //TODO-
1700 switch n.Case {
1701 case AssignmentExpressionCond: // ConditionalExpression
1702 n.Operand = n.ConditionalExpression.addrOf(ctx)
1703 n.IsSideEffectsFree = n.ConditionalExpression.IsSideEffectsFree
1704 case AssignmentExpressionAssign: // UnaryExpression '=' AssignmentExpression
1705 panic(n.Position().String())
1706 case AssignmentExpressionMul: // UnaryExpression "*=" AssignmentExpression
1707 panic(n.Position().String())
1708 case AssignmentExpressionDiv: // UnaryExpression "/=" AssignmentExpression
1709 panic(n.Position().String())
1710 case AssignmentExpressionMod: // UnaryExpression "%=" AssignmentExpression
1711 panic(n.Position().String())
1712 case AssignmentExpressionAdd: // UnaryExpression "+=" AssignmentExpression
1713 panic(n.Position().String())
1714 case AssignmentExpressionSub: // UnaryExpression "-=" AssignmentExpression
1715 panic(n.Position().String())
1716 case AssignmentExpressionLsh: // UnaryExpression "<<=" AssignmentExpression
1717 panic(n.Position().String())
1718 case AssignmentExpressionRsh: // UnaryExpression ">>=" AssignmentExpression
1719 panic(n.Position().String())
1720 case AssignmentExpressionAnd: // UnaryExpression "&=" AssignmentExpression
1721 panic(n.Position().String())
1722 case AssignmentExpressionXor: // UnaryExpression "^=" AssignmentExpression
1723 panic(n.Position().String())
1724 case AssignmentExpressionOr: // UnaryExpression "|=" AssignmentExpression
1725 panic(n.Position().String())
1726 default:
1727 panic(todo(""))
1728 }
1729 return n.Operand
1730}
1731
1732func (n *ConditionalExpression) addrOf(ctx *context) Operand {
1733 if n == nil {
1734 return noOperand
1735 }
1736 n.Operand = noOperand //TODO-
1737 switch n.Case {
1738 case ConditionalExpressionLOr: // LogicalOrExpression
1739 n.Operand = n.LogicalOrExpression.addrOf(ctx)
1740 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree
1741 case ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
1742 panic(n.Position().String())
1743 default:
1744 panic(todo(""))
1745 }
1746 return n.Operand
1747}
1748
1749func (n *LogicalOrExpression) addrOf(ctx *context) Operand {
1750 if n == nil {
1751 return noOperand
1752 }
1753
1754 n.Operand = noOperand //TODO-
1755 switch n.Case {
1756 case LogicalOrExpressionLAnd: // LogicalAndExpression
1757 n.Operand = n.LogicalAndExpression.addrOf(ctx)
1758 n.IsSideEffectsFree = n.LogicalAndExpression.IsSideEffectsFree
1759 case LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
1760 panic(n.Position().String())
1761 default:
1762 panic(todo(""))
1763 }
1764 return n.Operand
1765}
1766
1767func (n *LogicalAndExpression) addrOf(ctx *context) Operand {
1768 if n == nil {
1769 return noOperand
1770 }
1771
1772 n.Operand = noOperand //TODO-
1773 switch n.Case {
1774 case LogicalAndExpressionOr: // InclusiveOrExpression
1775 n.Operand = n.InclusiveOrExpression.addrOf(ctx)
1776 n.IsSideEffectsFree = n.InclusiveOrExpression.IsSideEffectsFree
1777 case LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
1778 panic(n.Position().String())
1779 default:
1780 panic(todo(""))
1781 }
1782 return n.Operand
1783}
1784
1785func (n *InclusiveOrExpression) addrOf(ctx *context) Operand {
1786 if n == nil {
1787 return noOperand
1788 }
1789
1790 n.Operand = noOperand //TODO-
1791 switch n.Case {
1792 case InclusiveOrExpressionXor: // ExclusiveOrExpression
1793 n.Operand = n.ExclusiveOrExpression.addrOf(ctx)
1794 n.IsSideEffectsFree = n.ExclusiveOrExpression.IsSideEffectsFree
1795 case InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
1796 panic(n.Position().String())
1797 default:
1798 panic(todo(""))
1799 }
1800 return n.Operand
1801}
1802
1803func (n *ExclusiveOrExpression) addrOf(ctx *context) Operand {
1804 if n == nil {
1805 return noOperand
1806 }
1807
1808 n.Operand = noOperand //TODO-
1809 switch n.Case {
1810 case ExclusiveOrExpressionAnd: // AndExpression
1811 n.Operand = n.AndExpression.addrOf(ctx)
1812 n.IsSideEffectsFree = n.AndExpression.IsSideEffectsFree
1813 case ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
1814 panic(n.Position().String())
1815 default:
1816 panic(todo(""))
1817 }
1818 return n.Operand
1819}
1820
1821func (n *AndExpression) addrOf(ctx *context) Operand {
1822 if n == nil {
1823 return noOperand
1824 }
1825
1826 n.Operand = noOperand //TODO-
1827 switch n.Case {
1828 case AndExpressionEq: // EqualityExpression
1829 n.Operand = n.EqualityExpression.addrOf(ctx)
1830 n.IsSideEffectsFree = n.EqualityExpression.IsSideEffectsFree
1831 case AndExpressionAnd: // AndExpression '&' EqualityExpression
1832 panic(n.Position().String())
1833 default:
1834 panic(todo(""))
1835 }
1836 return n.Operand
1837}
1838
1839func (n *EqualityExpression) addrOf(ctx *context) Operand {
1840 if n == nil {
1841 return noOperand
1842 }
1843
1844 n.Operand = noOperand //TODO-
1845 switch n.Case {
1846 case EqualityExpressionRel: // RelationalExpression
1847 n.Operand = n.RelationalExpression.addrOf(ctx)
1848 n.IsSideEffectsFree = n.RelationalExpression.IsSideEffectsFree
1849 case EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
1850 panic(n.Position().String())
1851 case EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
1852 panic(n.Position().String())
1853 default:
1854 panic(todo(""))
1855 }
1856 return n.Operand
1857}
1858
1859func (n *RelationalExpression) addrOf(ctx *context) Operand {
1860 if n == nil {
1861 return noOperand
1862 }
1863
1864 n.Operand = noOperand //TODO-
1865 switch n.Case {
1866 case RelationalExpressionShift: // ShiftExpression
1867 n.Operand = n.ShiftExpression.addrOf(ctx)
1868 n.IsSideEffectsFree = n.ShiftExpression.IsSideEffectsFree
1869 case RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
1870 panic(n.Position().String())
1871 case RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
1872 panic(n.Position().String())
1873 case RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
1874 panic(n.Position().String())
1875 case RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
1876 panic(n.Position().String())
1877 default:
1878 panic(todo(""))
1879 }
1880 return n.Operand
1881}
1882
1883func (n *ShiftExpression) addrOf(ctx *context) Operand {
1884 if n == nil {
1885 return noOperand
1886 }
1887
1888 n.Operand = noOperand //TODO-
1889 switch n.Case {
1890 case ShiftExpressionAdd: // AdditiveExpression
1891 n.Operand = n.AdditiveExpression.addrOf(ctx)
1892 n.IsSideEffectsFree = n.AdditiveExpression.IsSideEffectsFree
1893 case ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
1894 panic(n.Position().String())
1895 case ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
1896 panic(n.Position().String())
1897 default:
1898 panic(todo(""))
1899 }
1900 return n.Operand
1901}
1902
1903func (n *AdditiveExpression) addrOf(ctx *context) Operand {
1904 if n == nil {
1905 return noOperand
1906 }
1907
1908 n.Operand = noOperand //TODO-
1909 switch n.Case {
1910 case AdditiveExpressionMul: // MultiplicativeExpression
1911 n.Operand = n.MultiplicativeExpression.addrOf(ctx)
1912 n.IsSideEffectsFree = n.MultiplicativeExpression.IsSideEffectsFree
1913 case AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
1914 panic(n.Position().String())
1915 case AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
1916 panic(n.Position().String())
1917 default:
1918 panic(todo(""))
1919 }
1920 return n.Operand
1921}
1922
1923func (n *MultiplicativeExpression) addrOf(ctx *context) Operand {
1924 if n == nil {
1925 return noOperand
1926 }
1927
1928 n.Operand = noOperand //TODO-
1929 switch n.Case {
1930 case MultiplicativeExpressionCast: // CastExpression
1931 n.Operand = n.CastExpression.addrOf(ctx)
1932 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
1933 case MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
1934 panic(n.Position().String())
1935 case MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
1936 panic(n.Position().String())
1937 case MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
1938 panic(n.Position().String())
1939 default:
1940 panic(todo(""))
1941 }
1942 return n.Operand
1943}
1944
1945func (n *TypeName) check(ctx *context, inUnion, isPacked bool, list *[]*TypeSpecifier) Type {
1946 if n == nil {
1947 return noType
1948 }
1949
1950 n.typ = n.SpecifierQualifierList.check(ctx, inUnion, isPacked, list)
1951 if n.AbstractDeclarator != nil {
1952 n.typ = n.AbstractDeclarator.check(ctx, n.typ)
1953 }
1954 for list := n.SpecifierQualifierList; list != nil; list = list.SpecifierQualifierList {
1955 if expr, ok := list.AttributeSpecifier.Has(idVectorSize, idVectorSize2); ok {
1956 n.vectorize(ctx, expr)
1957 break
1958 }
1959 }
1960 return n.typ
1961}
1962
1963func (n *TypeName) vectorize(ctx *context, expr *ExpressionList) {
1964 dst := &n.typ
1965 elem := n.typ
1966 switch n.typ.Kind() {
1967 case Function:
1968 dst = &n.typ.(*functionType).result
1969 elem = n.typ.Result()
1970 }
1971
1972 sz := expr.vectorSize(ctx)
1973 if sz == 0 {
1974 sz = elem.Size()
1975 }
1976 if sz%elem.Size() != 0 {
1977 ctx.errNode(expr, "vector size must be a multiple of the base size")
1978 }
1979 b := n.typ.base()
1980 b.size = sz
1981 b.kind = byte(Vector)
1982 *dst = &vectorType{
1983 typeBase: b,
1984 elem: elem,
1985 length: sz / elem.Size(),
1986 }
1987}
1988
1989func (n *AbstractDeclarator) check(ctx *context, typ Type) Type {
1990 if n == nil {
1991 return typ
1992 }
1993
1994 n.typ = noType //TODO-
1995 switch n.Case {
1996 case AbstractDeclaratorPtr: // Pointer
1997 n.typ = n.Pointer.check(ctx, typ)
1998 case AbstractDeclaratorDecl: // Pointer DirectAbstractDeclarator
1999 typ = n.Pointer.check(ctx, typ)
2000 n.typ = n.DirectAbstractDeclarator.check(ctx, typ)
2001 default:
2002 panic(todo(""))
2003 }
2004 return n.typ
2005}
2006
2007func (n *DirectAbstractDeclarator) check(ctx *context, typ Type) Type {
2008 if n == nil {
2009 return typ
2010 }
2011
2012 switch n.Case {
2013 case DirectAbstractDeclaratorDecl: // '(' AbstractDeclarator ')'
2014 if n.AbstractDeclarator == nil {
2015 // [0], 6.7.6, 128)
2016 //
2017 // As indicated by the syntax, empty parentheses in a
2018 // type name are interpreted as ‘‘function with no
2019 // parameter specification’’, rather than redundant
2020 // parentheses around the omitted identifier.
2021 panic(todo("")) //TODO
2022 }
2023
2024 return n.AbstractDeclarator.check(ctx, typ)
2025 case DirectAbstractDeclaratorArr: // DirectAbstractDeclarator '[' TypeQualifiers AssignmentExpression ']'
2026 return n.DirectAbstractDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, true, false))
2027 case DirectAbstractDeclaratorStaticArr: // DirectAbstractDeclarator '[' "static" TypeQualifiers AssignmentExpression ']'
2028 return n.DirectAbstractDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, false, false))
2029 case DirectAbstractDeclaratorArrStatic: // DirectAbstractDeclarator '[' TypeQualifiers "static" AssignmentExpression ']'
2030 return n.DirectAbstractDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, false, false))
2031 case DirectAbstractDeclaratorArrStar: // DirectAbstractDeclarator '[' '*' ']'
2032 return n.DirectAbstractDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, nil, true, true))
2033 case DirectAbstractDeclaratorFunc: // DirectAbstractDeclarator '(' ParameterTypeList ')'
2034 ft := &functionType{typeBase: typeBase{kind: byte(Function)}, result: typ}
2035 n.ParameterTypeList.check(ctx, ft)
2036 return n.DirectAbstractDeclarator.check(ctx, ft)
2037 }
2038
2039 panic(internalErrorf("%v: %v", n.Position(), n.Case))
2040}
2041
2042func (n *ParameterTypeList) check(ctx *context, ft *functionType) {
2043 if n == nil {
2044 return
2045 }
2046
2047 switch n.Case {
2048 case ParameterTypeListList: // ParameterList
2049 n.ParameterList.check(ctx, ft)
2050 case ParameterTypeListVar: // ParameterList ',' "..."
2051 ft.variadic = true
2052 n.ParameterList.check(ctx, ft)
2053 default:
2054 panic(todo(""))
2055 }
2056}
2057
2058func (n *ParameterList) check(ctx *context, ft *functionType) {
2059 for ; n != nil; n = n.ParameterList {
2060 p := n.ParameterDeclaration.check(ctx, ft)
2061 ft.params = append(ft.params, p)
2062 }
2063}
2064
2065func (n *ParameterDeclaration) check(ctx *context, ft *functionType) *Parameter {
2066 if n == nil {
2067 return nil
2068 }
2069
2070 switch n.Case {
2071 case ParameterDeclarationDecl: // DeclarationSpecifiers Declarator AttributeSpecifierList
2072 typ, _, _ := n.DeclarationSpecifiers.check(ctx, false)
2073 n.Declarator.IsParameter = true
2074 if n.typ = n.Declarator.check(ctx, n.DeclarationSpecifiers, typ, false); n.typ.Kind() == Void {
2075 panic(n.Position().String())
2076 }
2077 if n.AttributeSpecifierList != nil {
2078 //TODO panic(n.Position().String())
2079 }
2080 n.AttributeSpecifierList.check(ctx, n.typ.baseP())
2081 return &Parameter{d: n.Declarator, typ: n.typ}
2082 case ParameterDeclarationAbstract: // DeclarationSpecifiers AbstractDeclarator
2083 n.typ, _, _ = n.DeclarationSpecifiers.check(ctx, false)
2084 if n.AbstractDeclarator != nil {
2085 n.typ = n.AbstractDeclarator.check(ctx, n.typ)
2086 }
2087 return &Parameter{typ: n.typ}
2088 default:
2089 panic(todo(""))
2090 }
2091}
2092
2093func (n *Pointer) check(ctx *context, typ Type) (t Type) {
2094 if n == nil || typ == nil {
2095 return typ
2096 }
2097
2098 switch n.Case {
2099 case PointerTypeQual: // '*' TypeQualifiers
2100 n.TypeQualifiers.check(ctx, &n.typeQualifiers)
2101 case PointerPtr: // '*' TypeQualifiers Pointer
2102 n.TypeQualifiers.check(ctx, &n.typeQualifiers)
2103 typ = n.Pointer.check(ctx, typ)
2104 case PointerBlock: // '^' TypeQualifiers
2105 n.TypeQualifiers.check(ctx, &n.typeQualifiers)
2106 default:
2107 panic(todo(""))
2108 }
2109 r := ctx.cfg.ABI.Ptr(n, typ).(*pointerType)
2110 if n.typeQualifiers != nil {
2111 r.typeQualifiers = n.typeQualifiers.check(ctx, (*DeclarationSpecifiers)(nil), false)
2112 }
2113 return r
2114}
2115
2116func (n *TypeQualifiers) check(ctx *context, typ **typeBase) {
2117 for ; n != nil; n = n.TypeQualifiers {
2118 switch n.Case {
2119 case TypeQualifiersTypeQual: // TypeQualifier
2120 if *typ == nil {
2121 *typ = &typeBase{}
2122 }
2123 n.TypeQualifier.check(ctx, *typ)
2124 case TypeQualifiersAttribute: // AttributeSpecifier
2125 if *typ == nil {
2126 *typ = &typeBase{}
2127 }
2128 n.AttributeSpecifier.check(ctx, *typ)
2129 default:
2130 panic(todo(""))
2131 }
2132 }
2133}
2134
2135func (n *TypeQualifier) check(ctx *context, typ *typeBase) {
2136 if n == nil {
2137 return
2138 }
2139
2140 switch n.Case {
2141 case TypeQualifierConst: // "const"
2142 typ.flags |= fConst
2143 case TypeQualifierRestrict: // "restrict"
2144 typ.flags |= fRestrict
2145 case TypeQualifierVolatile: // "volatile"
2146 typ.flags |= fVolatile
2147 case TypeQualifierAtomic: // "_Atomic"
2148 typ.flags |= fAtomic
2149 default:
2150 panic(todo(""))
2151 }
2152}
2153
2154func (n *SpecifierQualifierList) check(ctx *context, inUnion, isPacked bool, list *[]*TypeSpecifier) Type {
2155 n0 := n
2156 typ := &typeBase{}
2157 for ; n != nil; n = n.SpecifierQualifierList {
2158 switch n.Case {
2159 case SpecifierQualifierListTypeSpec: // TypeSpecifier SpecifierQualifierList
2160 n.TypeSpecifier.check(ctx, typ, inUnion)
2161 if list != nil && n.TypeSpecifier.Case != TypeSpecifierAtomic {
2162 *list = append(*list, n.TypeSpecifier)
2163 }
2164 case SpecifierQualifierListTypeQual: // TypeQualifier SpecifierQualifierList
2165 n.TypeQualifier.check(ctx, typ)
2166 case SpecifierQualifierListAlignSpec: // AlignmentSpecifier SpecifierQualifierList
2167 n.AlignmentSpecifier.check(ctx)
2168 case SpecifierQualifierListAttribute: // AttributeSpecifier SpecifierQualifierList
2169 n.AttributeSpecifier.check(ctx, typ)
2170 default:
2171 panic(todo(""))
2172 }
2173 }
2174 return typ.check(ctx, n0, true)
2175}
2176
2177func (n *TypeSpecifier) check(ctx *context, typ *typeBase, inUnion bool) {
2178 if n == nil {
2179 return
2180 }
2181
2182 switch n.Case {
2183 case
2184 TypeSpecifierVoid, // "void"
2185 TypeSpecifierChar, // "char"
2186 TypeSpecifierShort, // "short"
2187 TypeSpecifierInt, // "int"
2188 TypeSpecifierInt8, // "__int8"
2189 TypeSpecifierInt16, // "__int16"
2190 TypeSpecifierInt32, // "__int32"
2191 TypeSpecifierInt64, // "__int64"
2192 TypeSpecifierInt128, // "__int128"
2193 TypeSpecifierLong, // "long"
2194 TypeSpecifierFloat, // "float"
2195 TypeSpecifierFloat16, // "__fp16"
2196 TypeSpecifierDecimal32, // "_Decimal32"
2197 TypeSpecifierDecimal64, // "_Decimal64"
2198 TypeSpecifierDecimal128, // "_Decimal128"
2199 TypeSpecifierFloat32, // "_Float32"
2200 TypeSpecifierFloat32x, // "_Float32x"
2201 TypeSpecifierFloat64, // "_Float64"
2202 TypeSpecifierFloat64x, // "_Float64x"
2203 TypeSpecifierFloat128, // "_Float128"
2204 TypeSpecifierFloat80, // "__float80"
2205 TypeSpecifierDouble, // "double"
2206 TypeSpecifierSigned, // "signed"
2207 TypeSpecifierUnsigned, // "unsigned"
2208 TypeSpecifierBool, // "_Bool"
2209 TypeSpecifierComplex: // "_Complex"
2210 // nop
2211 case TypeSpecifierStructOrUnion: // StructOrUnionSpecifier
2212 n.StructOrUnionSpecifier.check(ctx, typ, inUnion)
2213 case TypeSpecifierEnum: // EnumSpecifier
2214 n.EnumSpecifier.check(ctx)
2215 case TypeSpecifierTypedefName: // TYPEDEFNAME
2216 // nop
2217 case TypeSpecifierTypeofExpr: // "typeof" '(' Expression ')'
2218 op := n.Expression.check(ctx, false)
2219 n.typ = op.Type()
2220 case TypeSpecifierTypeofType: // "typeof" '(' TypeName ')'
2221 n.typ = n.TypeName.check(ctx, false, false, nil)
2222 case TypeSpecifierAtomic: // AtomicTypeSpecifier
2223 t := n.AtomicTypeSpecifier.check(ctx)
2224 typ.kind = t.base().kind
2225 typ.flags |= fAtomic
2226 n.typ = typ
2227 case
2228 TypeSpecifierFract, // "_Fract"
2229 TypeSpecifierSat, // "_Sat"
2230 TypeSpecifierAccum: // "_Accum"
2231 // nop
2232 default:
2233 panic(todo(""))
2234 }
2235}
2236
2237func (n *AtomicTypeSpecifier) check(ctx *context) Type {
2238 if n == nil {
2239 return nil
2240 }
2241
2242 return n.TypeName.check(ctx, false, false, &n.list)
2243}
2244
2245func (n *EnumSpecifier) check(ctx *context) {
2246 if n == nil {
2247 return
2248 }
2249
2250 switch n.Case {
2251 case EnumSpecifierDef: // "enum" AttributeSpecifierList IDENTIFIER '{' EnumeratorList ',' '}'
2252 n.AttributeSpecifierList.check(ctx, nil)
2253 min, max := n.EnumeratorList.check(ctx)
2254 var tmin, tmax Type
2255 switch min := min.(type) {
2256 case Int64Value:
2257 switch {
2258 case min >= 0 && ctx.cfg.UnsignedEnums:
2259 tmin = n.requireUint(ctx, uint64(min))
2260 switch max := max.(type) {
2261 case Int64Value:
2262 tmax = n.requireUint(ctx, uint64(max))
2263 case Uint64Value:
2264 tmax = n.requireUint(ctx, uint64(max))
2265 case nil:
2266 panic(todo("%v:", n.Position()))
2267 }
2268 default:
2269 tmin = n.requireInt(ctx, int64(min))
2270 switch max := max.(type) {
2271 case Int64Value:
2272 tmax = n.requireInt(ctx, int64(max))
2273 case Uint64Value:
2274 tmax = n.requireInt(ctx, int64(max))
2275 case nil:
2276 panic(todo("%v:", n.Position()))
2277 }
2278 }
2279 case Uint64Value:
2280 tmin = n.requireUint(ctx, uint64(min))
2281 switch max := max.(type) {
2282 case Int64Value:
2283 if max < 0 {
2284 panic(todo("%v: min %v max %v", n.Position(), min, max))
2285 }
2286
2287 tmax = n.requireUint(ctx, uint64(max))
2288 case Uint64Value:
2289 tmax = n.requireUint(ctx, uint64(max))
2290 case nil:
2291 _ = max
2292 panic(todo("%v:", n.Position()))
2293 }
2294 case nil:
2295 panic(todo("%v: %v %T", n.Position(), n.Case, min))
2296 }
2297 switch {
2298 case tmin.Size() > tmax.Size():
2299 n.typ = tmin
2300 default:
2301 n.typ = tmax
2302 }
2303 if !n.typ.IsIntegerType() || n.typ.Size() == 0 { //TODO-
2304 panic(todo(""))
2305 }
2306
2307 reg := n.lexicalScope.Parent() == nil
2308 for list := n.EnumeratorList; list != nil; list = list.EnumeratorList {
2309 en := list.Enumerator
2310 en.Operand = en.Operand.convertTo(ctx, en, n.typ)
2311 if reg {
2312 ctx.enums[en.Token.Value] = en.Operand
2313 }
2314 }
2315 case EnumSpecifierTag: // "enum" AttributeSpecifierList IDENTIFIER
2316 n.typ = &taggedType{
2317 resolutionScope: n.lexicalScope,
2318 tag: n.Token2.Value,
2319 typeBase: &typeBase{kind: byte(Enum)},
2320 }
2321 default:
2322 panic(todo(""))
2323 }
2324}
2325
2326func (n *EnumSpecifier) requireInt(ctx *context, m int64) (r Type) {
2327 var w int
2328 switch {
2329 case m < 0:
2330 w = mathutil.BitLenUint64(uint64(-m))
2331 default:
2332 w = mathutil.BitLenUint64(uint64(m)) + 1
2333 }
2334 w = mathutil.Max(w, 32)
2335 abi := ctx.cfg.ABI
2336 for k0, v := range intConvRank {
2337 k := Kind(k0)
2338 if k == Bool || k == Enum || v == 0 || !abi.isSignedInteger(k) {
2339 continue
2340 }
2341
2342 t := abi.Types[k]
2343 if int(t.Size)*8 < w {
2344 continue
2345 }
2346
2347 if r == nil || t.Size < r.Size() {
2348 r = abi.Type(k)
2349 }
2350 }
2351 if r == nil || r.Size() == 0 { //TODO-
2352 panic(todo(""))
2353 }
2354 return r
2355}
2356
2357func (n *EnumSpecifier) requireUint(ctx *context, m uint64) (r Type) {
2358 w := mathutil.BitLenUint64(m)
2359 w = mathutil.Max(w, 32)
2360 abi := ctx.cfg.ABI
2361 for k0, v := range intConvRank {
2362 k := Kind(k0)
2363 if k == Bool || k == Enum || v == 0 || abi.isSignedInteger(k) {
2364 continue
2365 }
2366
2367 t := abi.Types[k]
2368 if int(t.Size)*8 < w {
2369 continue
2370 }
2371
2372 if r == nil || t.Size < r.Size() {
2373 r = abi.Type(k)
2374 }
2375 }
2376 if r == nil || r.Size() == 0 { //TODO-
2377 panic(todo(""))
2378 }
2379 return r
2380}
2381
2382func (n *EnumeratorList) check(ctx *context) (min, max Value) {
2383 var iota Value
2384 for ; n != nil; n = n.EnumeratorList {
2385 iota, min, max = n.Enumerator.check(ctx, iota, min, max)
2386 }
2387 return min, max
2388}
2389
2390func (n *Enumerator) check(ctx *context, iota, min, max Value) (Value, Value, Value) {
2391 if n == nil {
2392 return nil, nil, nil
2393 }
2394
2395 if iota == nil {
2396 iota = Int64Value(0)
2397 }
2398 switch n.Case {
2399 case EnumeratorIdent: // IDENTIFIER AttributeSpecifierList
2400 n.AttributeSpecifierList.check(ctx, nil)
2401 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: iota}).normalize(ctx, n)
2402 case EnumeratorExpr: // IDENTIFIER AttributeSpecifierList '=' ConstantExpression
2403 n.AttributeSpecifierList.check(ctx, nil)
2404 n.Operand = n.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false)
2405 iota = n.Operand.Value()
2406 default:
2407 panic(todo(""))
2408 }
2409 switch x := iota.(type) {
2410 case Int64Value:
2411 switch m := min.(type) {
2412 case Int64Value:
2413 if x < m {
2414 min = x
2415 }
2416 case Uint64Value:
2417 if x < 0 || Uint64Value(x) < m {
2418 min = x
2419 }
2420 case nil:
2421 min = x
2422 }
2423 switch m := max.(type) {
2424 case Int64Value:
2425 if x > m {
2426 max = x
2427 }
2428 case Uint64Value:
2429 if x >= 0 && Uint64Value(x) > m {
2430 max = x
2431 }
2432 case nil:
2433 max = x
2434 }
2435 x++
2436 iota = x
2437 case Uint64Value:
2438 switch m := min.(type) {
2439 case Int64Value:
2440 if m < 0 {
2441 break
2442 }
2443
2444 if x < Uint64Value(m) {
2445 min = x
2446 }
2447 case Uint64Value:
2448 if x < m {
2449 min = x
2450 }
2451 case nil:
2452 min = x
2453 }
2454 switch m := max.(type) {
2455 case Int64Value:
2456 if m < 0 {
2457 max = x
2458 break
2459 }
2460
2461 if x > Uint64Value(m) {
2462 max = x
2463 }
2464
2465 case Uint64Value:
2466 if x > m {
2467 max = x
2468 }
2469 case nil:
2470 max = x
2471 }
2472 x++
2473 iota = x
2474 case nil:
2475 //TODO report type
2476 }
2477
2478 return iota, min, max
2479}
2480
2481func (n *ConstantExpression) check(ctx *context, mode mode, isAsmArg bool) Operand {
2482 if n == nil {
2483 return noOperand
2484 }
2485
2486 ctx.push(mode)
2487 n.Operand = n.ConditionalExpression.check(ctx, isAsmArg)
2488 ctx.pop()
2489 return n.Operand
2490}
2491
2492func (n *StructOrUnionSpecifier) check(ctx *context, typ *typeBase, inUnion bool) Type {
2493 if n == nil {
2494 return noType
2495 }
2496
2497 switch n.Case {
2498 case StructOrUnionSpecifierDef: // StructOrUnion AttributeSpecifierList IDENTIFIER '{' StructDeclarationList '}'
2499 typ.kind = byte(n.StructOrUnion.check(ctx))
2500 attr := n.AttributeSpecifierList.check(ctx, typ)
2501 fields := n.StructDeclarationList.check(ctx, inUnion || typ.Kind() == Union, typ.IsPacked())
2502 m := make(map[StringID]*field, len(fields))
2503 x := 0
2504 for _, v := range fields {
2505 if v.name != 0 {
2506 v.x = x
2507 v.xs = []int{x}
2508 x++
2509 m[v.name] = v
2510 }
2511 }
2512 t := (&structType{
2513 attr: attr,
2514 fields: fields,
2515 m: m,
2516 tag: n.Token.Value,
2517 typeBase: typ,
2518 }).check(ctx, n)
2519 if typ.Kind() == Union {
2520 var k Kind
2521 for _, v := range fields {
2522 if k == Invalid {
2523 k = v.typ.Kind()
2524 continue
2525 }
2526
2527 if v.typ.Kind() != k {
2528 k = Invalid
2529 break
2530 }
2531 }
2532 t.common = k
2533 }
2534 n.typ = t
2535 if nm := n.Token.Value; nm != 0 && n.lexicalScope.Parent() == nil {
2536 ctx.structTypes[nm] = t
2537 }
2538 case StructOrUnionSpecifierTag: // StructOrUnion AttributeSpecifierList IDENTIFIER
2539 typ.kind = byte(n.StructOrUnion.check(ctx))
2540 attr := n.AttributeSpecifierList.check(ctx, typ.baseP())
2541 n.typ = &taggedType{
2542 resolutionScope: n.lexicalScope,
2543 tag: n.Token.Value,
2544 typeBase: typ,
2545 }
2546 if attr != nil {
2547 n.typ = &attributedType{n.typ, attr}
2548 }
2549 default:
2550 panic(todo(""))
2551 }
2552 return n.typ
2553}
2554
2555func (n *StructDeclarationList) check(ctx *context, inUnion, isPacked bool) (s []*field) {
2556 for ; n != nil; n = n.StructDeclarationList {
2557 s = append(s, n.StructDeclaration.check(ctx, inUnion, isPacked)...)
2558 }
2559 return s
2560}
2561
2562func (n *StructDeclaration) check(ctx *context, inUnion, isPacked bool) (s []*field) {
2563 if n == nil || n.Empty {
2564 return nil
2565 }
2566
2567 typ := n.SpecifierQualifierList.check(ctx, inUnion, isPacked, nil)
2568 if n.StructDeclaratorList != nil {
2569 return n.StructDeclaratorList.check(ctx, n.SpecifierQualifierList, typ, inUnion, isPacked)
2570 }
2571
2572 return []*field{{typ: typ, inUnion: inUnion}}
2573}
2574
2575func (n *StructDeclaratorList) check(ctx *context, td typeDescriptor, typ Type, inUnion, isPacked bool) (s []*field) {
2576 for ; n != nil; n = n.StructDeclaratorList {
2577 s = append(s, n.StructDeclarator.check(ctx, td, typ, inUnion, isPacked))
2578 }
2579 return s
2580}
2581
2582func (n *StructDeclarator) check(ctx *context, td typeDescriptor, typ Type, inUnion, isPacked bool) *field {
2583 if n == nil {
2584 return nil
2585 }
2586
2587 if isPacked {
2588 typ.baseP().flags |= fPacked
2589 }
2590 if n.Declarator != nil {
2591 typ = n.Declarator.check(ctx, td, typ, false)
2592 }
2593 if attr := n.AttributeSpecifierList.check(ctx, typ.baseP()); len(attr) != 0 {
2594 typ = &attributedType{typ, attr}
2595 }
2596 sf := &field{
2597 typ: typ,
2598 d: n,
2599 inUnion: inUnion,
2600 }
2601 switch n.Case {
2602 case StructDeclaratorDecl: // Declarator
2603 sf.name = n.Declarator.Name()
2604 case StructDeclaratorBitField: // Declarator ':' ConstantExpression AttributeSpecifierList
2605 sf.isBitField = true
2606 sf.typ = &bitFieldType{Type: typ, field: sf}
2607 sf.name = n.Declarator.Name()
2608 if op := n.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false); op.Type().IsIntegerType() {
2609 switch x := op.Value().(type) {
2610 case Int64Value:
2611 if x < 0 || x > 64 {
2612 panic("TODO")
2613 }
2614 sf.bitFieldWidth = byte(x)
2615 case Uint64Value:
2616 if x > 64 {
2617 panic("TODO")
2618 }
2619 sf.bitFieldWidth = byte(x)
2620 default:
2621 //dbg("%T", x)
2622 panic(PrettyString(op))
2623 }
2624 } else {
2625 //dbg("", n.ConstantExpression)
2626 panic(n.Declarator.Position())
2627 }
2628 n.AttributeSpecifierList.check(ctx, sf.typ.baseP())
2629 default:
2630 panic(todo(""))
2631 }
2632 return sf
2633}
2634
2635func (n *StructOrUnion) check(ctx *context) Kind {
2636 if n == nil {
2637 return Invalid
2638 }
2639
2640 switch n.Case {
2641 case StructOrUnionStruct: // "struct"
2642 return Struct
2643 case StructOrUnionUnion: // "union"
2644 return Union
2645 default:
2646 panic(todo(""))
2647 }
2648}
2649
2650func (n *CastExpression) check(ctx *context, isAsmArg bool) Operand {
2651 if n == nil {
2652 return noOperand
2653 }
2654
2655 n.Operand = noOperand //TODO-
2656 switch n.Case {
2657 case CastExpressionUnary: // UnaryExpression
2658 n.Operand = n.UnaryExpression.check(ctx, isAsmArg)
2659 n.IsSideEffectsFree = n.UnaryExpression.IsSideEffectsFree
2660 case CastExpressionCast: // '(' TypeName ')' CastExpression
2661 t := n.TypeName.check(ctx, false, false, nil)
2662 ctx.push(ctx.mode)
2663 if m := ctx.mode; m&mIntConstExpr != 0 && m&mIntConstExprAnyCast == 0 {
2664 if t := n.TypeName.Type(); t != nil && t.Kind() != Int {
2665 ctx.mode &^= mIntConstExpr
2666 }
2667 ctx.mode |= mIntConstExprFloat
2668 }
2669 op := n.CastExpression.check(ctx, isAsmArg)
2670 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
2671 ctx.pop()
2672 n.Operand = op.convertTo(ctx, n, t)
2673 default:
2674 panic(todo(""))
2675 }
2676 return n.Operand
2677}
2678
2679func (n *PostfixExpression) check(ctx *context, implicitFunc, isAsmArg bool) Operand {
2680 if n == nil {
2681 return noOperand
2682 }
2683
2684 n.Operand = noOperand //TODO-
2685out:
2686 switch n.Case {
2687 case PostfixExpressionPrimary: // PrimaryExpression
2688 n.Operand = n.PrimaryExpression.check(ctx, implicitFunc, isAsmArg)
2689 n.IsSideEffectsFree = n.PrimaryExpression.IsSideEffectsFree
2690 case PostfixExpressionIndex: // PostfixExpression '[' Expression ']'
2691 pe := n.PostfixExpression.check(ctx, false, isAsmArg)
2692 if d := pe.Declarator(); d != nil {
2693 d.Read += ctx.readDelta
2694 }
2695 e := n.Expression.check(ctx, isAsmArg)
2696 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree && n.Expression.IsSideEffectsFree
2697 t := pe.Type().Decay()
2698 if t.Kind() == Invalid {
2699 break
2700 }
2701
2702 if t.Kind() == Ptr {
2703 if t := e.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
2704 ctx.errNode(n.Expression, "index must be integer type, have %v", e.Type())
2705 break
2706 }
2707
2708 n.Operand = n.index(ctx, pe, e)
2709 break
2710 }
2711
2712 if pe.Type().Kind() == Vector {
2713 if t := e.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
2714 ctx.errNode(n.Expression, "index must be integer type, have %v", e.Type())
2715 break
2716 }
2717
2718 n.Operand = n.index(ctx, pe, e)
2719 break
2720 }
2721
2722 t = e.Type().Decay()
2723 if t.Kind() == Invalid {
2724 break
2725 }
2726
2727 if t.Kind() == Ptr {
2728 if t := pe.Type(); t.Kind() != Invalid && !t.IsIntegerType() {
2729 ctx.errNode(n.Expression, "index must be integer type, have %v", pe.Type())
2730 break
2731 }
2732
2733 n.Operand = n.index(ctx, e, pe)
2734 break
2735 }
2736
2737 ctx.errNode(n, "invalid index expression %v[%v]", pe.Type(), e.Type())
2738 case PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
2739 op := n.PostfixExpression.check(ctx, true, isAsmArg)
2740 Inspect(n.PostfixExpression, func(n Node, enter bool) bool {
2741 if !enter {
2742 return true
2743 }
2744
2745 if x, ok := n.(*PrimaryExpression); ok {
2746 if d := x.Declarator(); d != nil {
2747 d.called = true
2748 }
2749 }
2750 return true
2751 })
2752 args := n.ArgumentExpressionList.check(ctx, n.PostfixExpression.Declarator(), isAsmArg)
2753 switch op.Declarator().Name() {
2754 case idBuiltinConstantPImpl:
2755 if len(args) < 2 {
2756 panic(todo(""))
2757 }
2758
2759 var v Int64Value
2760 if args[1].Value() != nil {
2761 v = 1
2762 }
2763 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: v}
2764 default:
2765 switch n.PostfixExpression.Operand.Value().(type) {
2766 case StringValue, WideStringValue:
2767 if isAsmArg {
2768 // asm("foo": "bar" (a))
2769 // ^
2770 break out
2771 }
2772 }
2773
2774 n.Operand = n.checkCall(ctx, n, op.Type(), args, n.ArgumentExpressionList)
2775 }
2776 case PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
2777 op := n.PostfixExpression.check(ctx, false, isAsmArg)
2778 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
2779 if d := op.Declarator(); d != nil {
2780 d.Read += ctx.readDelta
2781 }
2782 st := op.Type()
2783 st0 := st.underlyingType()
2784 if k := st.Kind(); k == Invalid || k != Struct && k != Union {
2785 ctx.errNode(n.PostfixExpression, "select expression of wrong type: %s (%s)", st, st0)
2786 break
2787 }
2788
2789 f, ok := st.FieldByName(n.Token2.Value)
2790 if !ok {
2791 ctx.errNode(n.PostfixExpression, "unknown or ambiguous field %q of type %s (%s)", n.Token2.Value, st, st0)
2792 break
2793 }
2794
2795 n.Field = f
2796 ft := f.Type()
2797 if f.IsBitField() {
2798 ft = &bitFieldType{Type: ft, field: f.(*field)}
2799 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ft}}
2800 break
2801 }
2802
2803 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ft, offset: op.Offset() + f.Offset()}}
2804 case PostfixExpressionPSelect: // PostfixExpression "->" IDENTIFIER
2805 op := n.PostfixExpression.check(ctx, false, isAsmArg)
2806 n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
2807 if d := op.Declarator(); d != nil {
2808 d.Read += ctx.readDelta
2809 }
2810 t := op.Type()
2811 if k := t.Decay().Kind(); k == Invalid || k != Ptr {
2812 //TODO report error
2813 break
2814 }
2815
2816 st := t.Elem()
2817 if k := st.Kind(); k == Invalid || k != Struct && k != Union {
2818 //TODO report error
2819 break
2820 }
2821
2822 f, ok := st.FieldByName(n.Token2.Value)
2823 if !ok {
2824 //TODO report error
2825 break
2826 }
2827
2828 n.Field = f
2829 ft := f.Type()
2830 if f.IsBitField() {
2831 ft = &bitFieldType{Type: ft, field: f.(*field)}
2832 }
2833 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ft}}
2834 case PostfixExpressionInc: // PostfixExpression "++"
2835 op := n.PostfixExpression.check(ctx, false, isAsmArg)
2836 if d := op.Declarator(); d != nil {
2837 d.SubjectOfIncDec = true
2838 d.Read += ctx.readDelta
2839 d.Write++
2840 }
2841 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
2842 case PostfixExpressionDec: // PostfixExpression "--"
2843 op := n.PostfixExpression.check(ctx, false, isAsmArg)
2844 if d := op.Declarator(); d != nil {
2845 d.SubjectOfIncDec = true
2846 d.Read += ctx.readDelta
2847 d.Write++
2848 }
2849 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: op.Type()}
2850 case PostfixExpressionComplit: // '(' TypeName ')' '{' InitializerList ',' '}'
2851 //TODO IsSideEffectsFree
2852 if f := ctx.checkFn; f != nil {
2853 f.CompositeLiterals = append(f.CompositeLiterals, n)
2854 }
2855 t := n.TypeName.check(ctx, false, false, nil)
2856 var v *InitializerValue
2857 if n.InitializerList != nil {
2858 n.InitializerList.check(ctx, &n.InitializerList.list, t, Automatic, 0, nil, false)
2859 n.InitializerList.setConstZero()
2860 v = &InitializerValue{typ: t, initializer: n.InitializerList}
2861 }
2862 n.Operand = &lvalue{Operand: (&operand{abi: &ctx.cfg.ABI, typ: t, value: v}).normalize(ctx, n)}
2863 case PostfixExpressionTypeCmp: // "__builtin_types_compatible_p" '(' TypeName ',' TypeName ')'
2864 n.IsSideEffectsFree = true
2865 t1 := n.TypeName.check(ctx, false, false, nil)
2866 t2 := n.TypeName2.check(ctx, false, false, nil)
2867 v := 0
2868 switch {
2869 case t1.IsArithmeticType() && t2.IsArithmeticType():
2870 if t1.Kind() == t2.Kind() {
2871 v = 1
2872 }
2873 default:
2874 ctx.errNode(n, "ICE: __builtin_types_compatible_p(%v, %v)", t1, t2)
2875 }
2876 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: Int64Value(v)}
2877 case PostfixExpressionChooseExpr: // "__builtin_choose_expr" '(' ConstantExpression ',' AssignmentExpression ',' AssignmentExpression ')'
2878 n.Operand = noOperand
2879 expr1 := n.AssignmentExpression.check(ctx, isAsmArg)
2880 if expr1 == nil {
2881 ctx.errNode(n, "first argument of __builtin_choose_expr must be a constant expression")
2882 break
2883 }
2884
2885 if !expr1.IsConst() {
2886 ctx.errNode(n, "first argument of __builtin_choose_expr must be a constant expression: %v %v", expr1.Value(), expr1.Type())
2887 break
2888 }
2889
2890 switch {
2891 case expr1.IsNonZero():
2892 n.Operand = n.AssignmentExpression2.check(ctx, isAsmArg)
2893 n.IsSideEffectsFree = n.AssignmentExpression2.IsSideEffectsFree
2894 default:
2895 n.Operand = n.AssignmentExpression3.check(ctx, isAsmArg)
2896 n.IsSideEffectsFree = n.AssignmentExpression3.IsSideEffectsFree
2897 }
2898 default:
2899 panic(todo(""))
2900 }
2901 return n.Operand
2902}
2903
2904func (n *PostfixExpression) index(ctx *context, pe, e Operand) Operand {
2905 var x uintptr
2906 hasx := false
2907 switch v := e.Value().(type) {
2908 case Int64Value:
2909 x = uintptr(v)
2910 hasx = true
2911 case Uint64Value:
2912 x = uintptr(v)
2913 hasx = true
2914 }
2915 off := x * pe.Type().Elem().Size()
2916 switch v := pe.Value().(type) {
2917 case StringValue:
2918 if hasx {
2919 s := StringID(v).String()
2920 var v byte
2921 switch {
2922 case x > uintptr(len(s)):
2923 //TODO report err
2924 return noOperand
2925 case x < uintptr(len(s)):
2926 v = s[x]
2927 }
2928
2929 return (&operand{abi: &ctx.cfg.ABI, typ: pe.Type().Elem(), value: Int64Value(v)}).normalize(ctx, n)
2930 }
2931 case WideStringValue:
2932 if hasx {
2933 s := []rune(StringID(v).String())
2934 var v rune
2935 switch {
2936 case x > uintptr(len(s)):
2937 //TODO report err
2938 return noOperand
2939 case x < uintptr(len(s)):
2940 v = s[x]
2941 }
2942
2943 return (&operand{abi: &ctx.cfg.ABI, typ: pe.Type().Elem(), value: Int64Value(v)}).normalize(ctx, n)
2944 }
2945 }
2946
2947 if d := pe.Declarator(); d != nil && hasx {
2948 return &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: pe.Type().Elem(), offset: pe.Offset() + off}, declarator: d}
2949 }
2950
2951 return &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: pe.Type().Elem()}}
2952}
2953
2954func (n *PostfixExpression) checkCall(ctx *context, nd Node, f Type, args []Operand, argList *ArgumentExpressionList) (r Operand) {
2955 r = noOperand
2956 switch f.Kind() {
2957 case Invalid:
2958 return noOperand
2959 case Function:
2960 // ok
2961 case Ptr:
2962 if e := f.Elem(); e.Kind() == Function {
2963 f = e
2964 break
2965 }
2966
2967 ctx.errNode(nd, "expected function pointer type: %v, %v", f, f.Kind())
2968 return r
2969 default:
2970 ctx.errNode(nd, "expected function type: %v, %v", f, f.Kind())
2971 return r
2972 }
2973
2974 r = &operand{abi: &ctx.cfg.ABI, typ: f.Result()}
2975 params := f.Parameters()
2976 if len(params) == 1 && params[0].Type().Kind() == Void {
2977 params = nil
2978 if len(args) != 0 {
2979 //TODO report error
2980 return r
2981 }
2982 }
2983
2984 for i, arg := range args {
2985 var t Type
2986 switch {
2987 case i < len(params):
2988 //TODO check assignability
2989 t = params[i].Type().Decay()
2990 default:
2991 t = defaultArgumentPromotion(ctx, nd, arg).Type()
2992 }
2993 argList.AssignmentExpression.promote = t
2994 argList = argList.ArgumentExpressionList
2995 }
2996 return r
2997}
2998
2999func defaultArgumentPromotion(ctx *context, n Node, op Operand) Operand {
3000 t := op.Type().Decay()
3001 if arithmeticTypes[t.Kind()] {
3002 if t.IsIntegerType() {
3003 return op.integerPromotion(ctx, n)
3004 }
3005
3006 switch t.Kind() {
3007 case Float:
3008 return op.convertTo(ctx, n, ctx.cfg.ABI.Type(Double))
3009 }
3010 }
3011 return op
3012}
3013
3014func (n *ArgumentExpressionList) check(ctx *context, f *Declarator, isAsmArg bool) (r []Operand) {
3015 for ; n != nil; n = n.ArgumentExpressionList {
3016 op := n.AssignmentExpression.check(ctx, isAsmArg)
3017 if op.Type() == nil {
3018 ctx.errNode(n, "operand has usupported, invalid or incomplete type")
3019 op = noOperand
3020 } else if op.Type().IsComplexType() {
3021 ctx.checkFn.CallSiteComplexExpr = append(ctx.checkFn.CallSiteComplexExpr, n.AssignmentExpression)
3022 }
3023 r = append(r, op)
3024 if !ctx.cfg.TrackAssignments {
3025 continue
3026 }
3027
3028 Inspect(n.AssignmentExpression, func(n Node, enter bool) bool {
3029 if !enter {
3030 return true
3031 }
3032
3033 if x, ok := n.(*PrimaryExpression); ok {
3034 x.Declarator().setLHS(f)
3035 }
3036 return true
3037 })
3038 }
3039 return r
3040}
3041
3042func (n *Expression) check(ctx *context, isAsmArg bool) Operand {
3043 if n == nil {
3044 return noOperand
3045 }
3046
3047 n.Operand = noOperand //TODO-
3048 switch n.Case {
3049 case ExpressionAssign: // AssignmentExpression
3050 n.Operand = n.AssignmentExpression.check(ctx, isAsmArg)
3051 n.IsSideEffectsFree = n.AssignmentExpression.IsSideEffectsFree
3052 case ExpressionComma: // Expression ',' AssignmentExpression
3053 op := n.Expression.check(ctx, isAsmArg)
3054 n.Operand = n.AssignmentExpression.check(ctx, isAsmArg)
3055 if !op.IsConst() && n.Operand.IsConst() {
3056 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: n.Operand.Type()}
3057 }
3058 n.IsSideEffectsFree = n.Expression.IsSideEffectsFree && n.AssignmentExpression.IsSideEffectsFree
3059 default:
3060 panic(todo(""))
3061 }
3062 return n.Operand
3063}
3064
3065func (n *PrimaryExpression) check(ctx *context, implicitFunc, isAsmArg bool) Operand {
3066 if n == nil {
3067 return noOperand
3068 }
3069
3070 n.Operand = noOperand //TODO-
3071 switch n.Case {
3072 case PrimaryExpressionIdent: // IDENTIFIER
3073 n.IsSideEffectsFree = true
3074 return n.checkIdentifier(ctx, implicitFunc)
3075 case PrimaryExpressionInt: // INTCONST
3076 n.IsSideEffectsFree = true
3077 n.Operand = n.intConst(ctx)
3078 case PrimaryExpressionFloat: // FLOATCONST
3079 n.IsSideEffectsFree = true
3080 if ctx.mode&mIntConstExpr != 0 && ctx.mode&mIntConstExprFloat == 0 {
3081 ctx.errNode(n, "invalid integer constant expression")
3082 break
3083 }
3084
3085 n.Operand = n.floatConst(ctx)
3086 case PrimaryExpressionEnum: // ENUMCONST
3087 n.IsSideEffectsFree = true
3088 if e := n.resolvedIn.enumerator(n.Token.Value, n.Token); e != nil {
3089 op := e.Operand.(*operand)
3090 op.typ = ctx.cfg.ABI.Type(Int) // [0] 6.4.4.3/2
3091 n.Operand = op
3092 break
3093 }
3094
3095 //TODO report err
3096 case PrimaryExpressionChar: // CHARCONST
3097 n.IsSideEffectsFree = true
3098 s := []rune(n.Token.Value.String())
3099 var v Value
3100 switch {
3101 case s[0] <= 255:
3102 // If an integer character constant contains a single character or escape
3103 // sequence, its value is the one that results when an object with type char
3104 // whose value is that of the single character or escape sequence is converted
3105 // to type int.
3106 switch {
3107 case ctx.cfg.ABI.SignedChar:
3108 v = Int64Value(int8(s[0]))
3109 default:
3110 v = Int64Value(s[0])
3111 }
3112 default:
3113 v = Int64Value(s[0])
3114 }
3115 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: v}).normalize(ctx, n)
3116 case PrimaryExpressionLChar: // LONGCHARCONST
3117 n.IsSideEffectsFree = true
3118 s := []rune(n.Token.Value.String())
3119 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: wcharT(ctx, n.lexicalScope, n.Token), value: Int64Value(s[0])}).normalize(ctx, n)
3120 case PrimaryExpressionString: // STRINGLITERAL
3121 n.IsSideEffectsFree = true
3122 ctx.not(n, mIntConstExpr)
3123 typ := ctx.cfg.ABI.Type(Char)
3124 b := typ.base()
3125 b.align = byte(typ.Align())
3126 b.fieldAlign = byte(typ.FieldAlign())
3127 b.kind = byte(Array)
3128 sz := uintptr(len(n.Token.Value.String())) + 1 //TODO set sz in cpp
3129 arr := &arrayType{typeBase: b, decay: ctx.cfg.ABI.Ptr(n, typ), elem: typ, length: sz}
3130 arr.setLen(sz)
3131 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: arr, value: StringValue(n.Token.Value)}).normalize(ctx, n)
3132 case PrimaryExpressionLString: // LONGSTRINGLITERAL
3133 n.IsSideEffectsFree = true
3134 ctx.not(n, mIntConstExpr)
3135 typ := wcharT(ctx, n.lexicalScope, n.Token)
3136 b := typ.base()
3137 b.align = byte(typ.Align())
3138 b.fieldAlign = byte(typ.FieldAlign())
3139 b.kind = byte(Array)
3140 sz := uintptr(len([]rune(n.Token.Value.String()))) + 1 //TODO set sz in cpp
3141 arr := &arrayType{typeBase: b, decay: ctx.cfg.ABI.Ptr(n, typ), elem: typ, length: sz}
3142 arr.setLen(sz)
3143 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: arr, value: WideStringValue(n.Token.Value)}).normalize(ctx, n)
3144 case PrimaryExpressionExpr: // '(' Expression ')'
3145 n.Operand = n.Expression.check(ctx, isAsmArg)
3146 n.IsSideEffectsFree = n.Expression.IsSideEffectsFree
3147 case PrimaryExpressionStmt: // '(' CompoundStatement ')'
3148 //TODO IsSideEffectsFree
3149 ctx.not(n, mIntConstExpr)
3150 n.Operand = n.CompoundStatement.check(ctx)
3151 if n.Operand == noOperand {
3152 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Void)}
3153 }
3154 default:
3155 panic(todo(""))
3156 }
3157 return n.Operand
3158}
3159
3160func wcharT(ctx *context, s Scope, tok Token) Type {
3161 if t := ctx.wcharT; t != nil {
3162 return t
3163 }
3164
3165 t := ctx.stddef(idWCharT, s, tok)
3166 if t.Kind() != Invalid {
3167 ctx.wcharT = t
3168 }
3169 return t
3170}
3171
3172func (n *PrimaryExpression) checkIdentifier(ctx *context, implicitFunc bool) Operand {
3173 ctx.not(n, mIntConstExpr)
3174 var d *Declarator
3175 nm := n.Token.Value
3176 if n.resolvedIn == nil {
3177 if ctx.cfg.RejectLateBinding && !ctx.cfg.ignoreUndefinedIdentifiers {
3178 ctx.errNode(n, "front-end: undefined: %s", n.Token.Value)
3179 return noOperand
3180 }
3181
3182 out:
3183 for s := n.lexicalScope; s != nil; s = s.Parent() {
3184 for _, v := range s[nm] {
3185 switch x := v.(type) {
3186 case *Enumerator:
3187 break out
3188 case *Declarator:
3189 if x.IsTypedefName {
3190 d = nil
3191 break out
3192 }
3193
3194 n.resolvedIn = s
3195 n.resolvedTo = x
3196 d = x
3197 t := d.Type()
3198 if t != nil && t.Kind() == Function {
3199 if d.fnDef {
3200 break out
3201 }
3202
3203 continue
3204 }
3205
3206 if t != nil && !t.IsIncomplete() {
3207 break out
3208 }
3209 case *EnumSpecifier, *StructOrUnionSpecifier, *StructDeclarator, *LabeledStatement:
3210 // nop
3211 default:
3212 panic(todo(""))
3213 }
3214 }
3215 }
3216 }
3217 if d == nil && n.resolvedIn != nil {
3218 d = n.resolvedIn.declarator(n.Token.Value, n.Token)
3219 }
3220 if d == nil && !ctx.cfg.DisableBuiltinResolution {
3221 d = builtin(ctx, nm)
3222 }
3223 if d == nil {
3224 _, ok := gccKeywords[nm]
3225 if !ok && implicitFunc {
3226 d := &Declarator{
3227 DirectDeclarator: &DirectDeclarator{
3228 lexicalScope: ctx.ast.Scope,
3229 Case: DirectDeclaratorFuncIdent,
3230 DirectDeclarator: &DirectDeclarator{
3231 lexicalScope: ctx.ast.Scope,
3232 Case: DirectDeclaratorIdent,
3233 Token: Token{Value: nm},
3234 },
3235 },
3236 implicit: true,
3237 }
3238 ed := &ExternalDeclaration{
3239 Case: ExternalDeclarationDecl,
3240 Declaration: &Declaration{
3241 DeclarationSpecifiers: &DeclarationSpecifiers{
3242 Case: DeclarationSpecifiersTypeSpec,
3243 TypeSpecifier: &TypeSpecifier{
3244 Case: TypeSpecifierInt,
3245 },
3246 },
3247 InitDeclaratorList: &InitDeclaratorList{
3248 InitDeclarator: &InitDeclarator{
3249 Case: InitDeclaratorDecl,
3250 Declarator: d,
3251 },
3252 },
3253 },
3254 }
3255 ed.check(ctx)
3256 n.Operand = &funcDesignator{Operand: &operand{abi: &ctx.cfg.ABI, typ: d.Type()}, declarator: d}
3257 return n.Operand
3258 }
3259
3260 if !ctx.cfg.ignoreUndefinedIdentifiers {
3261 ctx.errNode(n, "front-end: undefined: %s", n.Token.Value)
3262 }
3263 return noOperand
3264 }
3265 if d == nil {
3266 if !ctx.cfg.ignoreUndefinedIdentifiers {
3267 ctx.errNode(n, "front-end: undefined: %s", n.Token.Value)
3268 }
3269 return noOperand
3270 }
3271
3272 switch d.Linkage {
3273 case Internal:
3274 if d.IsStatic() {
3275 break
3276 }
3277
3278 fallthrough
3279 case External:
3280 s := n.resolvedIn
3281 if s.Parent() == nil {
3282 break
3283 }
3284
3285 for s.Parent() != nil {
3286 s = s.Parent()
3287 }
3288
3289 if d2 := s.declarator(n.Token.Value, Token{}); d2 != nil {
3290 d = d2
3291 }
3292 }
3293
3294 if d.Type() == nil {
3295 ctx.errNode(d, "unresolved type of: %s", n.Token.Value)
3296 return noOperand
3297 }
3298
3299 d.Read += ctx.readDelta
3300 switch t := d.Type(); t.Kind() {
3301 case Function:
3302 n.Operand = &funcDesignator{Operand: &operand{abi: &ctx.cfg.ABI, typ: t}, declarator: d}
3303 default:
3304 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: t}, declarator: d}
3305 }
3306 if !ctx.capture {
3307 return n.Operand
3308 }
3309
3310 for s := n.lexicalScope; s != nil; s = s.Parent() {
3311 if _, ok := s[nm]; ok {
3312 return n.Operand // d in fn scope
3313 }
3314
3315 if _, ok := s[idClosure]; ok { // d in outer scope
3316 if ctx.closure == nil {
3317 ctx.closure = map[StringID]struct{}{} //TODO capture the PrimaryExpression, not the declarator name
3318 }
3319 ctx.closure[nm] = struct{}{}
3320 return n.Operand
3321 }
3322 }
3323 panic(todo(""))
3324}
3325
3326func builtin(ctx *context, nm StringID) *Declarator {
3327 id := dict.sid("__builtin_" + nm.String())
3328 a := ctx.ast.Scope[id]
3329 if len(a) == 0 {
3330 return nil
3331 }
3332
3333 switch x := a[0].(type) {
3334 case *Declarator:
3335 if x.fnDef || x.IsFunctionPrototype() {
3336 return x
3337 }
3338 }
3339 return nil
3340}
3341
3342func (n *PrimaryExpression) floatConst(ctx *context) Operand {
3343 s0 := n.Token.String()
3344 s := s0
3345 var cplx, suff string
3346loop2:
3347 for i := len(s) - 1; i > 0; i-- {
3348 switch s0[i] {
3349 case 'l', 'L':
3350 s = s[:i]
3351 if ctx.cfg.LongDoubleIsDouble {
3352 break
3353 }
3354
3355 suff += "l"
3356 case 'f', 'F':
3357 s = s[:i]
3358 suff += "f"
3359 case 'i', 'I', 'j', 'J':
3360 s = s[:i]
3361 cplx += "i"
3362 default:
3363 break loop2
3364 }
3365 }
3366
3367 if len(suff) > 1 || len(cplx) > 1 {
3368 ctx.errNode(n, "invalid number format")
3369 return noOperand
3370 }
3371
3372 var v float64
3373 var err error
3374 prec := uint(64)
3375 if suff == "l" {
3376 prec = longDoublePrec
3377 }
3378 var bf *big.Float
3379 switch {
3380 case suff == "l" || strings.Contains(s, "p") || strings.Contains(s, "P"):
3381 bf, _, err = big.ParseFloat(strings.ToLower(s), 0, prec, big.ToNearestEven)
3382 if err == nil {
3383 v, _ = bf.Float64()
3384 }
3385 default:
3386 v, err = strconv.ParseFloat(s, 64)
3387 }
3388 if err != nil {
3389 switch {
3390 case !strings.HasPrefix(s, "-") && strings.Contains(err.Error(), "value out of range"):
3391 // linux_386/usr/include/math.h
3392 //
3393 // /* Value returned on overflow. With IEEE 754 floating point, this is
3394 // +Infinity, otherwise the largest representable positive value. */
3395 // #if __GNUC_PREREQ (3, 3)
3396 // # define HUGE_VAL (__builtin_huge_val ())
3397 // #else
3398 // /* This may provoke compiler warnings, and may not be rounded to
3399 // +Infinity in all IEEE 754 rounding modes, but is the best that can
3400 // be done in ISO C while remaining a constant expression. 10,000 is
3401 // greater than the maximum (decimal) exponent for all supported
3402 // floating-point formats and widths. */
3403 // # define HUGE_VAL 1e10000
3404 // #endif
3405 v = math.Inf(1)
3406 default:
3407 ctx.errNode(n, "%v", err)
3408 return noOperand
3409 }
3410 }
3411
3412 // [0]6.4.4.2
3413 switch suff {
3414 case "":
3415 switch {
3416 case cplx != "":
3417 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ComplexDouble), value: Complex128Value(complex(0, v))}).normalize(ctx, n)
3418 default:
3419 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Double), value: Float64Value(v)}).normalize(ctx, n)
3420 }
3421 case "f":
3422 switch {
3423 case cplx != "":
3424 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ComplexFloat), value: Complex64Value(complex(0, float32(v)))}).normalize(ctx, n)
3425 default:
3426 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Float), value: Float32Value(float32(v))}).normalize(ctx, n)
3427 }
3428 case "l":
3429 switch {
3430 case cplx != "":
3431 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(ComplexLongDouble), value: Complex256Value{&Float128Value{N: big.NewFloat(0)}, &Float128Value{N: bf}}}).normalize(ctx, n)
3432 default:
3433 return (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(LongDouble), value: &Float128Value{N: bf}}).normalize(ctx, n)
3434 }
3435 default:
3436 //dbg("%q %q %q %q %v", s0, s, suff, cplx, err)
3437 panic("TODO")
3438 }
3439}
3440
3441func (n *PrimaryExpression) intConst(ctx *context) Operand {
3442 var val uint64
3443 s0 := n.Token.String()
3444 s := strings.TrimRight(s0, "uUlL")
3445 var decadic bool
3446 switch {
3447 case strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X"):
3448 var err error
3449 if val, err = strconv.ParseUint(s[2:], 16, 64); err != nil {
3450 ctx.errNode(n, "%v", err)
3451 return nil
3452 }
3453 case strings.HasPrefix(s, "0b") || strings.HasPrefix(s, "0B"):
3454 var err error
3455 if val, err = strconv.ParseUint(s[2:], 2, 64); err != nil {
3456 ctx.errNode(n, "%v", err)
3457 return nil
3458 }
3459 case strings.HasPrefix(s, "0"):
3460 var err error
3461 if val, err = strconv.ParseUint(s, 8, 64); err != nil {
3462 ctx.errNode(n, "%v", err)
3463 return nil
3464 }
3465 default:
3466 decadic = true
3467 var err error
3468 if val, err = strconv.ParseUint(s, 10, 64); err != nil {
3469 ctx.errNode(n, "%v", err)
3470 return nil
3471 }
3472 }
3473
3474 suffix := s0[len(s):]
3475 switch suffix = strings.ToLower(suffix); suffix {
3476 case "":
3477 if decadic {
3478 return intConst(ctx, n, s0, val, Int, Long, LongLong)
3479 }
3480
3481 return intConst(ctx, n, s0, val, Int, UInt, Long, ULong, LongLong, ULongLong)
3482 case "u":
3483 return intConst(ctx, n, s0, val, UInt, ULong, ULongLong)
3484 case "l":
3485 if decadic {
3486 return intConst(ctx, n, s0, val, Long, LongLong)
3487 }
3488
3489 return intConst(ctx, n, s0, val, Long, ULong, LongLong, ULongLong)
3490 case "lu", "ul":
3491 return intConst(ctx, n, s0, val, ULong, ULongLong)
3492 case "ll":
3493 if decadic {
3494 return intConst(ctx, n, s0, val, LongLong)
3495 }
3496
3497 return intConst(ctx, n, s0, val, LongLong, ULongLong)
3498 case "llu", "ull":
3499 return intConst(ctx, n, s0, val, ULongLong)
3500 default:
3501 ctx.errNode(n, "invalid suffix: %v", s0)
3502 return nil
3503 }
3504}
3505
3506func intConst(ctx *context, n Node, s string, val uint64, list ...Kind) Operand {
3507 abi := ctx.cfg.ABI
3508 b := bits.Len64(val)
3509 for _, k := range list {
3510 sign := 0
3511 if abi.isSignedInteger(k) {
3512 sign = 1
3513 }
3514 if abi.size(k)*8 >= b+sign {
3515 switch {
3516 case sign == 0:
3517 return (&operand{abi: &ctx.cfg.ABI, typ: abi.Type(k), value: Uint64Value(val)}).normalize(ctx, n)
3518 default:
3519 return (&operand{abi: &ctx.cfg.ABI, typ: abi.Type(k), value: Int64Value(val)}).normalize(ctx, n)
3520 }
3521 }
3522 }
3523
3524 ctx.errNode(n, "invalid integer constant %v", s)
3525 return nil
3526}
3527
3528func (n *ConditionalExpression) check(ctx *context, isAsmArg bool) Operand {
3529 if n == nil {
3530 return noOperand
3531 }
3532
3533 n.Operand = noOperand //TODO-
3534 switch n.Case {
3535 case ConditionalExpressionLOr: // LogicalOrExpression
3536 n.Operand = n.LogicalOrExpression.check(ctx, isAsmArg)
3537 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree
3538 case ConditionalExpressionCond: // LogicalOrExpression '?' Expression ':' ConditionalExpression
3539 op := n.LogicalOrExpression.check(ctx, isAsmArg)
3540 // The first operand shall have scalar type.
3541 if !op.Type().Decay().IsScalarType() {
3542 //TODO report error
3543 break
3544 }
3545
3546 a := n.Expression.check(ctx, isAsmArg)
3547 b := n.ConditionalExpression.check(ctx, isAsmArg)
3548 at := a.Type().Decay()
3549 bt := b.Type().Decay()
3550
3551 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree && (n.Expression == nil || n.Expression.IsSideEffectsFree) && n.ConditionalExpression.IsSideEffectsFree
3552 var val Value
3553 if op.Value() != nil {
3554 switch {
3555 case op.IsZero():
3556 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree && n.ConditionalExpression.IsSideEffectsFree
3557 default:
3558 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree && n.Expression.IsSideEffectsFree
3559 }
3560 if a.Value() != nil && b.Value() != nil { //TODO not needed both non nil
3561 switch {
3562 case op.IsZero():
3563 val = b.Value()
3564 default:
3565 val = a.Value()
3566 }
3567 }
3568 }
3569
3570 if a.Type().Kind() == Invalid && b.Type().Kind() == Invalid {
3571 return noOperand
3572 }
3573
3574 // One of the following shall hold for the second and third
3575 // operands:
3576 //TODO — both operands have the same structure or union type;
3577 //TODO — one operand is a pointer to an object or incomplete type and the other is a pointer to a
3578 //TODO qualified or unqualified version of void.
3579 switch {
3580 // — both operands have arithmetic type;
3581 case a.Type().IsArithmeticType() && b.Type().IsArithmeticType():
3582 // If both the second and third operands have
3583 // arithmetic type, the result type that would be
3584 // determined by the usual arithmetic conversions, were
3585 // they applied to those two operands,
3586 // is the type of the result.
3587 op, _ := usualArithmeticConversions(ctx, n, a, b, true)
3588 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: op.Type(), value: val}).normalize(ctx, n)
3589 // — both operands have void type;
3590 case a.Type().Kind() == Void && b.Type().Kind() == Void:
3591 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: val}).normalize(ctx, n)
3592 // — one operand is a pointer and the other is a null pointer constant;
3593 case (a.Type().Kind() == Ptr || a.Type().Kind() == Function) && b.IsZero():
3594 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: val}).normalize(ctx, n)
3595 case (b.Type().Kind() == Ptr || b.Type().Kind() == Function) && a.IsZero():
3596 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: b.Type(), value: val}).normalize(ctx, n)
3597 // — both operands are pointers to qualified or unqualified versions of compatible types;
3598 case at.Kind() == Ptr && bt.Kind() == Ptr:
3599 //TODO check compatible
3600 //TODO if !at.isCompatibleIgnoreQualifiers(bt) {
3601 //TODO trc("%v: XXXX %v ? %v", n.Token2.Position(), at, bt)
3602 //TODO ctx.assignmentCompatibilityErrorCond(&n.Token2, at, bt)
3603 //TODO }
3604 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: n.Expression.Operand.Type(), value: val}).normalize(ctx, n)
3605 case a.Type().Kind() == Ptr && a.Type().Elem().Kind() == Function && b.Type().Kind() == Function:
3606 //TODO check compatible
3607 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: val}).normalize(ctx, n)
3608 case b.Type().Kind() == Ptr && b.Type().Elem().Kind() == Function && a.Type().Kind() == Function:
3609 //TODO check compatible
3610 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: b.Type(), value: val}).normalize(ctx, n)
3611 case a.Type().Kind() != Invalid:
3612 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: val}).normalize(ctx, n)
3613 case b.Type().Kind() != Invalid:
3614 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: b.Type(), value: val}).normalize(ctx, n)
3615 default:
3616 panic(todo(""))
3617 }
3618 default:
3619 panic(todo(""))
3620 }
3621 return n.Operand
3622}
3623
3624func (n *LogicalOrExpression) check(ctx *context, isAsmArg bool) Operand {
3625 if n == nil {
3626 return noOperand
3627 }
3628
3629 n.Operand = noOperand //TODO-
3630 switch n.Case {
3631 case LogicalOrExpressionLAnd: // LogicalAndExpression
3632 n.Operand = n.LogicalAndExpression.check(ctx, isAsmArg)
3633 n.IsSideEffectsFree = n.LogicalAndExpression.IsSideEffectsFree
3634 case LogicalOrExpressionLOr: // LogicalOrExpression "||" LogicalAndExpression
3635 lop := n.LogicalOrExpression.check(ctx, isAsmArg)
3636 rop := n.LogicalAndExpression.check(ctx, isAsmArg)
3637 n.IsSideEffectsFree = n.LogicalOrExpression.IsSideEffectsFree && n.LogicalAndExpression.IsSideEffectsFree ||
3638 lop.Value() != nil && lop.IsNonZero() && n.LogicalOrExpression.IsSideEffectsFree
3639 var v Value
3640 if lop.Value() != nil && rop.Value() != nil { //TODO lop.IsNonZero shortcut
3641 switch {
3642 case n.LogicalOrExpression.Operand.IsNonZero() || n.LogicalAndExpression.Operand.IsNonZero():
3643 v = Int64Value(1)
3644 default:
3645 v = Int64Value(0)
3646 }
3647 }
3648 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: v}).normalize(ctx, n)
3649 default:
3650 panic(todo(""))
3651 }
3652 return n.Operand
3653}
3654
3655func (n *LogicalAndExpression) check(ctx *context, isAsmArg bool) Operand {
3656 if n == nil {
3657 return noOperand
3658 }
3659
3660 n.Operand = noOperand //TODO-
3661 switch n.Case {
3662 case LogicalAndExpressionOr: // InclusiveOrExpression
3663 n.Operand = n.InclusiveOrExpression.check(ctx, isAsmArg)
3664 n.IsSideEffectsFree = n.InclusiveOrExpression.IsSideEffectsFree
3665 case LogicalAndExpressionLAnd: // LogicalAndExpression "&&" InclusiveOrExpression
3666 lop := n.LogicalAndExpression.check(ctx, isAsmArg)
3667 rop := n.InclusiveOrExpression.check(ctx, isAsmArg)
3668 n.IsSideEffectsFree = n.LogicalAndExpression.IsSideEffectsFree && n.InclusiveOrExpression.IsSideEffectsFree ||
3669 lop.Value() != nil && lop.IsZero() && n.LogicalAndExpression.IsSideEffectsFree
3670 var v Value
3671 if lop.Value() != nil && rop.Value() != nil { //TODO lop.IsZero shortcut
3672 switch {
3673 case n.LogicalAndExpression.Operand.IsNonZero() && n.InclusiveOrExpression.Operand.IsNonZero():
3674 v = Int64Value(1)
3675 default:
3676 v = Int64Value(0)
3677 }
3678 }
3679 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int), value: v}).normalize(ctx, n)
3680 default:
3681 panic(todo(""))
3682 }
3683 return n.Operand
3684}
3685
3686func (n *InclusiveOrExpression) check(ctx *context, isAsmArg bool) Operand {
3687 if n == nil {
3688 return noOperand
3689 }
3690
3691 n.Operand = noOperand //TODO-
3692 switch n.Case {
3693 case InclusiveOrExpressionXor: // ExclusiveOrExpression
3694 n.Operand = n.ExclusiveOrExpression.check(ctx, isAsmArg)
3695 n.IsSideEffectsFree = n.ExclusiveOrExpression.IsSideEffectsFree
3696 case InclusiveOrExpressionOr: // InclusiveOrExpression '|' ExclusiveOrExpression
3697 a := n.InclusiveOrExpression.check(ctx, isAsmArg)
3698 b := n.ExclusiveOrExpression.check(ctx, isAsmArg)
3699 n.IsSideEffectsFree = n.InclusiveOrExpression.IsSideEffectsFree && n.ExclusiveOrExpression.IsSideEffectsFree
3700 n.promote = noType
3701 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
3702 n.Operand = checkBinaryVectorIntegerArtithmetic(ctx, n, a, b)
3703 break
3704 }
3705
3706 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
3707 ctx.errNode(n, "operands must be integers")
3708 break
3709 }
3710
3711 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
3712 n.promote = a.Type()
3713 if a.Value() == nil || b.Value() == nil {
3714 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
3715 break
3716 }
3717
3718 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().or(b.Value())}).normalize(ctx, n)
3719 default:
3720 panic(todo(""))
3721 }
3722 return n.Operand
3723}
3724
3725func checkBinaryVectorIntegerArtithmetic(ctx *context, n Node, a, b Operand) Operand {
3726 var rt Type
3727 if a.Type().Kind() == Vector {
3728 rt = a.Type()
3729 a = &operand{abi: &ctx.cfg.ABI, typ: a.Type().Elem()}
3730 }
3731 if b.Type().Kind() == Vector {
3732 if rt == nil {
3733 rt = b.Type()
3734 }
3735 b = &operand{abi: &ctx.cfg.ABI, typ: b.Type().Elem()}
3736 }
3737 a, b = usualArithmeticConversions(ctx, n, a, b, true)
3738 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
3739 ctx.errNode(n, "operands must be integers")
3740 }
3741 return &operand{abi: &ctx.cfg.ABI, typ: rt}
3742}
3743
3744func (n *ExclusiveOrExpression) check(ctx *context, isAsmArg bool) Operand {
3745 if n == nil {
3746 return noOperand
3747 }
3748
3749 n.Operand = noOperand //TODO-
3750 switch n.Case {
3751 case ExclusiveOrExpressionAnd: // AndExpression
3752 n.Operand = n.AndExpression.check(ctx, isAsmArg)
3753 n.IsSideEffectsFree = n.AndExpression.IsSideEffectsFree
3754 case ExclusiveOrExpressionXor: // ExclusiveOrExpression '^' AndExpression
3755 a := n.ExclusiveOrExpression.check(ctx, isAsmArg)
3756 b := n.AndExpression.check(ctx, isAsmArg)
3757 n.IsSideEffectsFree = n.ExclusiveOrExpression.IsSideEffectsFree && n.AndExpression.IsSideEffectsFree
3758 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
3759 n.Operand = checkBinaryVectorIntegerArtithmetic(ctx, n, a, b)
3760 break
3761 }
3762
3763 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
3764 ctx.errNode(n, "operands must be integers")
3765 break
3766 }
3767
3768 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
3769 n.promote = a.Type()
3770 if a.Value() == nil || b.Value() == nil {
3771 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
3772 break
3773 }
3774
3775 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().xor(b.Value())}).normalize(ctx, n)
3776 default:
3777 panic(todo(""))
3778 }
3779 return n.Operand
3780}
3781
3782func (n *AndExpression) check(ctx *context, isAsmArg bool) Operand {
3783 if n == nil {
3784 return noOperand
3785 }
3786
3787 n.Operand = noOperand //TODO-
3788 switch n.Case {
3789 case AndExpressionEq: // EqualityExpression
3790 n.Operand = n.EqualityExpression.check(ctx, isAsmArg)
3791 n.IsSideEffectsFree = n.EqualityExpression.IsSideEffectsFree
3792 case AndExpressionAnd: // AndExpression '&' EqualityExpression
3793 a := n.AndExpression.check(ctx, isAsmArg)
3794 b := n.EqualityExpression.check(ctx, isAsmArg)
3795 n.IsSideEffectsFree = n.AndExpression.IsSideEffectsFree && n.EqualityExpression.IsSideEffectsFree
3796 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
3797 n.Operand = checkBinaryVectorIntegerArtithmetic(ctx, n, a, b)
3798 break
3799 }
3800
3801 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
3802 ctx.errNode(n, "operands must be integers")
3803 break
3804 }
3805
3806 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
3807 n.promote = a.Type()
3808 if a.Value() == nil || b.Value() == nil {
3809 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
3810 break
3811 }
3812
3813 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().and(b.Value())}).normalize(ctx, n)
3814 default:
3815 panic(todo(""))
3816 }
3817 return n.Operand
3818}
3819
3820func (n *EqualityExpression) check(ctx *context, isAsmArg bool) Operand {
3821 if n == nil {
3822 return noOperand
3823 }
3824
3825 switch n.Case {
3826 case EqualityExpressionRel: // RelationalExpression
3827 n.Operand = n.RelationalExpression.check(ctx, isAsmArg)
3828 n.IsSideEffectsFree = n.RelationalExpression.IsSideEffectsFree
3829 case
3830 EqualityExpressionEq, // EqualityExpression "==" RelationalExpression
3831 EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
3832
3833 op := &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int)}
3834 n.Operand = op
3835 lo := n.EqualityExpression.check(ctx, isAsmArg)
3836 ro := n.RelationalExpression.check(ctx, isAsmArg)
3837 n.IsSideEffectsFree = n.EqualityExpression.IsSideEffectsFree && n.RelationalExpression.IsSideEffectsFree
3838 lt := lo.Type().Decay()
3839 rt := ro.Type().Decay()
3840 n.promote = noType
3841 ok := false
3842 switch {
3843 case lo.Type().Kind() == Vector && ro.Type().Kind() == Vector:
3844 n.Operand = checkVectorComparison(ctx, n, lo.Type(), ro.Type())
3845 return n.Operand
3846 case lt.IsArithmeticType() && rt.IsArithmeticType():
3847 op, _ := usualArithmeticConversions(ctx, n, lo, ro, true)
3848 n.promote = op.Type()
3849 ok = true
3850 case lt.Kind() == Ptr && (rt.Kind() == Ptr || rt.IsIntegerType()):
3851 n.promote = lt
3852 //TODO
3853 case (lt.Kind() == Ptr || lt.IsIntegerType()) && rt.Kind() == Ptr:
3854 n.promote = rt
3855 //TODO
3856 case lt.Kind() == Function:
3857 n.promote = ctx.cfg.ABI.Ptr(n, lt)
3858 case rt.Kind() == Function:
3859 n.promote = ctx.cfg.ABI.Ptr(n, rt)
3860 default:
3861 //TODO report error
3862 }
3863 if n.promote.Kind() == Invalid || !ok {
3864 break
3865 }
3866
3867 lo = lo.convertTo(ctx, n, n.promote)
3868 ro = ro.convertTo(ctx, n, n.promote)
3869 if a, b := lo.Value(), ro.Value(); a != nil && b != nil {
3870 switch n.Case {
3871 case EqualityExpressionEq: // EqualityExpression "==" RelationalExpression
3872 op.value = a.eq(b)
3873 case EqualityExpressionNeq: // EqualityExpression "!=" RelationalExpression
3874 op.value = a.neq(b)
3875 }
3876 }
3877 default:
3878 panic(todo(""))
3879 }
3880 return n.Operand
3881}
3882
3883func checkVectorComparison(ctx *context, n Node, a, b Type) (r Operand) {
3884 a = a.underlyingType()
3885 b = b.underlyingType()
3886 rt := *a.(*vectorType)
3887 rt.elem = ctx.cfg.ABI.Type(Int)
3888 r = &operand{abi: &ctx.cfg.ABI, typ: &rt}
3889 x := a.Elem()
3890 y := b.Elem()
3891 if x.Kind() != y.Kind() {
3892 ctx.errNode(n, "cannot compare vectors of different element types: %s and %s", x, y)
3893 }
3894 return r
3895}
3896
3897func (n *RelationalExpression) check(ctx *context, isAsmArg bool) Operand {
3898 if n == nil {
3899 return noOperand
3900 }
3901
3902 n.Operand = noOperand //TODO-
3903 switch n.Case {
3904 case RelationalExpressionShift: // ShiftExpression
3905 n.Operand = n.ShiftExpression.check(ctx, isAsmArg)
3906 n.IsSideEffectsFree = n.ShiftExpression.IsSideEffectsFree
3907 case
3908 RelationalExpressionLt, // RelationalExpression '<' ShiftExpression
3909 RelationalExpressionGt, // RelationalExpression '>' ShiftExpression
3910 RelationalExpressionLeq, // RelationalExpression "<=" ShiftExpression
3911 RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
3912
3913 n.promote = noType
3914 op := &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Type(Int)}
3915 n.Operand = op
3916 lo := n.RelationalExpression.check(ctx, isAsmArg)
3917 ro := n.ShiftExpression.check(ctx, isAsmArg)
3918 n.IsSideEffectsFree = n.RelationalExpression.IsSideEffectsFree && n.ShiftExpression.IsSideEffectsFree
3919 if lo.Type().Kind() == Vector && ro.Type().Kind() == Vector {
3920 n.Operand = checkVectorComparison(ctx, n, lo.Type(), ro.Type())
3921 break
3922 }
3923
3924 if lo.Type().IsComplexType() || ro.Type().IsComplexType() {
3925 ctx.errNode(&n.Token, "complex numbers are not ordered")
3926 break
3927 }
3928
3929 lt := lo.Type().Decay()
3930 rt := ro.Type().Decay()
3931 n.promote = noType
3932 ok := true
3933 switch {
3934 case lt.IsRealType() && rt.IsRealType():
3935 op, _ := usualArithmeticConversions(ctx, n, lo, ro, true)
3936 n.promote = op.Type()
3937 case lt.Kind() == Ptr && (rt.Kind() == Ptr || rt.IsIntegerType()):
3938 n.promote = lt
3939 //TODO
3940 case (lt.Kind() == Ptr || lt.IsIntegerType()) && rt.Kind() == Ptr:
3941 n.promote = rt
3942 //TODO
3943 default:
3944 //TODO report error
3945 ok = false
3946 }
3947 if n.promote.Kind() == Invalid || !ok {
3948 break
3949 }
3950
3951 lo = lo.convertTo(ctx, n, n.promote)
3952 ro = ro.convertTo(ctx, n, n.promote)
3953 if a, b := lo.Value(), ro.Value(); a != nil && b != nil {
3954 switch n.Case {
3955 case RelationalExpressionLt: // RelationalExpression '<' ShiftExpression
3956 op.value = a.lt(b)
3957 case RelationalExpressionGt: // RelationalExpression '>' ShiftExpression
3958 op.value = a.gt(b)
3959 case RelationalExpressionLeq: // RelationalExpression "<=" ShiftExpression
3960 op.value = a.le(b)
3961 case RelationalExpressionGeq: // RelationalExpression ">=" ShiftExpression
3962 op.value = a.ge(b)
3963 }
3964 }
3965 default:
3966 panic(todo(""))
3967 }
3968 return n.Operand
3969}
3970
3971func (n *ShiftExpression) check(ctx *context, isAsmArg bool) Operand {
3972 if n == nil {
3973 return noOperand
3974 }
3975
3976 n.Operand = noOperand //TODO-
3977 switch n.Case {
3978 case ShiftExpressionAdd: // AdditiveExpression
3979 n.Operand = n.AdditiveExpression.check(ctx, isAsmArg)
3980 n.IsSideEffectsFree = n.AdditiveExpression.IsSideEffectsFree
3981 case ShiftExpressionLsh: // ShiftExpression "<<" AdditiveExpression
3982 a := n.ShiftExpression.check(ctx, isAsmArg)
3983 b := n.AdditiveExpression.check(ctx, isAsmArg)
3984 n.IsSideEffectsFree = n.ShiftExpression.IsSideEffectsFree && n.AdditiveExpression.IsSideEffectsFree
3985 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
3986 n.Operand = checkBinaryVectorIntegerArtithmetic(ctx, n, a, b)
3987 break
3988 }
3989
3990 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
3991 //TODO report err
3992 break
3993 }
3994
3995 a = a.integerPromotion(ctx, n)
3996 b = b.integerPromotion(ctx, n)
3997 n.promote = b.Type()
3998 if a.Value() == nil || b.Value() == nil {
3999 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4000 break
4001 }
4002
4003 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().lsh(b.Value())}).normalize(ctx, n)
4004 case ShiftExpressionRsh: // ShiftExpression ">>" AdditiveExpression
4005 a := n.ShiftExpression.check(ctx, isAsmArg)
4006 b := n.AdditiveExpression.check(ctx, isAsmArg)
4007 n.IsSideEffectsFree = n.ShiftExpression.IsSideEffectsFree && n.AdditiveExpression.IsSideEffectsFree
4008 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4009 n.Operand = checkBinaryVectorIntegerArtithmetic(ctx, n, a, b)
4010 break
4011 }
4012
4013 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
4014 //TODO report err
4015 break
4016 }
4017
4018 a = a.integerPromotion(ctx, n)
4019 b = b.integerPromotion(ctx, n)
4020 n.promote = b.Type()
4021 if a.Value() == nil || b.Value() == nil {
4022 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4023 break
4024 }
4025
4026 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().rsh(b.Value())}).normalize(ctx, n)
4027 default:
4028 panic(todo(""))
4029 }
4030 return n.Operand
4031}
4032
4033func (n *AdditiveExpression) check(ctx *context, isAsmArg bool) Operand {
4034 if n == nil {
4035 return noOperand
4036 }
4037
4038 n.Operand = noOperand //TODO-
4039 switch n.Case {
4040 case AdditiveExpressionMul: // MultiplicativeExpression
4041 n.Operand = n.MultiplicativeExpression.check(ctx, isAsmArg)
4042 n.IsSideEffectsFree = n.MultiplicativeExpression.IsSideEffectsFree
4043 case AdditiveExpressionAdd: // AdditiveExpression '+' MultiplicativeExpression
4044 n.promote = noType
4045 a := n.AdditiveExpression.check(ctx, isAsmArg)
4046 b := n.MultiplicativeExpression.check(ctx, isAsmArg)
4047 n.IsSideEffectsFree = n.AdditiveExpression.IsSideEffectsFree && n.MultiplicativeExpression.IsSideEffectsFree
4048 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4049 n.Operand = checkBinaryVectorArtithmetic(ctx, n, a, b)
4050 break
4051 }
4052
4053 if t := a.Type().Decay(); t.Kind() == Ptr && b.Type().IsScalarType() {
4054 var x uintptr
4055 hasx := false
4056 switch v := b.Value().(type) {
4057 case Int64Value:
4058 x = uintptr(v)
4059 hasx = true
4060 case Uint64Value:
4061 x = uintptr(v)
4062 hasx = true
4063 }
4064 off := x * a.Type().Elem().Size()
4065 switch y := a.Value().(type) {
4066 case StringValue:
4067 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, a.Type().Elem()), value: y, offset: a.Offset() + off}
4068 default:
4069 switch {
4070 case a.Value() == nil && a.Declarator() != nil && hasx:
4071 n.Operand = &lvalue{Operand: &operand{abi: &ctx.cfg.ABI, typ: ctx.cfg.ABI.Ptr(n, a.Type().Elem()), offset: a.Offset() + off}, declarator: a.Declarator()}
4072 default:
4073 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: t}
4074 }
4075 }
4076 break
4077 }
4078
4079 if t := b.Type().Decay(); t.Kind() == Ptr && a.Type().IsScalarType() {
4080 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: t}
4081 break
4082 }
4083
4084 if !a.Type().IsArithmeticType() || !b.Type().IsArithmeticType() {
4085 //TODO report error
4086 break
4087 }
4088
4089 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
4090 n.promote = a.Type()
4091 if a.Value() == nil || b.Value() == nil {
4092 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4093 break
4094 }
4095
4096 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().add(b.Value())}).normalize(ctx, n)
4097 case AdditiveExpressionSub: // AdditiveExpression '-' MultiplicativeExpression
4098 n.promote = noType
4099 a := n.AdditiveExpression.check(ctx, isAsmArg)
4100 b := n.MultiplicativeExpression.check(ctx, isAsmArg)
4101 n.IsSideEffectsFree = n.AdditiveExpression.IsSideEffectsFree && n.MultiplicativeExpression.IsSideEffectsFree
4102 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4103 n.Operand = checkBinaryVectorArtithmetic(ctx, n, a, b)
4104 break
4105 }
4106
4107 if a.Type().Decay().Kind() == Ptr && b.Type().Decay().Kind() == Ptr {
4108 var val Value
4109 if a.Value() != nil && b.Value() != nil {
4110 ae := a.Type().Decay().Elem()
4111 be := b.Type().Decay().Elem()
4112 switch {
4113 case ae.Size() == be.Size():
4114 var d int64
4115 switch x := a.Value().(type) {
4116 case Int64Value:
4117 d = int64(x)
4118 case Uint64Value:
4119 d = int64(x)
4120 }
4121 switch x := b.Value().(type) {
4122 case Int64Value:
4123 val = Int64Value(d - int64(x))
4124 case Uint64Value:
4125 val = Int64Value(d - int64(x))
4126 }
4127 default:
4128 ctx.errNode(n, "difference of pointers of differently sized elements")
4129 }
4130 }
4131 pt := ptrdiffT(ctx, n.lexicalScope, n.Token)
4132 n.promote = pt
4133 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: pt, value: val}
4134 if val != nil {
4135 n.Operand = n.Operand.convertTo(ctx, n, a.Type())
4136 }
4137 break
4138 }
4139
4140 if t := a.Type().Decay(); t.Kind() == Ptr && b.Type().IsScalarType() {
4141 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: t}
4142 break
4143 }
4144
4145 if !a.Type().IsArithmeticType() || !b.Type().IsArithmeticType() {
4146 //TODO report error
4147 break
4148 }
4149
4150 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
4151 n.promote = a.Type()
4152 if a.Value() == nil || b.Value() == nil {
4153 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4154 break
4155 }
4156
4157 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().sub(b.Value())}).normalize(ctx, n)
4158 default:
4159 panic(todo(""))
4160 }
4161 return n.Operand
4162}
4163
4164func checkBinaryVectorArtithmetic(ctx *context, n Node, a, b Operand) Operand {
4165 var rt Type
4166 if a.Type().Kind() == Vector {
4167 rt = a.Type()
4168 a = &operand{abi: &ctx.cfg.ABI, typ: a.Type().Elem()}
4169 }
4170 if b.Type().Kind() == Vector {
4171 if rt == nil {
4172 rt = b.Type()
4173 }
4174 b = &operand{abi: &ctx.cfg.ABI, typ: b.Type().Elem()}
4175 }
4176 usualArithmeticConversions(ctx, n, a, b, true)
4177 return &operand{abi: &ctx.cfg.ABI, typ: rt}
4178}
4179
4180func ptrdiffT(ctx *context, s Scope, tok Token) Type {
4181 if t := ctx.ptrdiffT; t != nil {
4182 return t
4183 }
4184
4185 t := ctx.stddef(idPtrdiffT, s, tok)
4186 if t.Kind() != Invalid {
4187 ctx.ptrdiffT = t
4188 }
4189 return t
4190}
4191
4192func (n *MultiplicativeExpression) check(ctx *context, isAsmArg bool) Operand {
4193 if n == nil {
4194 return noOperand
4195 }
4196
4197 n.Operand = noOperand //TODO-
4198 switch n.Case {
4199 case MultiplicativeExpressionCast: // CastExpression
4200 n.Operand = n.CastExpression.check(ctx, isAsmArg)
4201 n.IsSideEffectsFree = n.CastExpression.IsSideEffectsFree
4202 case MultiplicativeExpressionMul: // MultiplicativeExpression '*' CastExpression
4203 a := n.MultiplicativeExpression.check(ctx, isAsmArg)
4204 b := n.CastExpression.check(ctx, isAsmArg)
4205 n.IsSideEffectsFree = n.MultiplicativeExpression.IsSideEffectsFree && n.CastExpression.IsSideEffectsFree
4206 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4207 n.Operand = checkBinaryVectorArtithmetic(ctx, n, a, b)
4208 break
4209 }
4210
4211 if !a.Type().IsArithmeticType() || !b.Type().IsArithmeticType() {
4212 break
4213 }
4214
4215 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
4216 n.promote = a.Type()
4217 if a.Value() == nil || b.Value() == nil {
4218 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4219 break
4220 }
4221
4222 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().mul(b.Value())}).normalize(ctx, n)
4223 case MultiplicativeExpressionDiv: // MultiplicativeExpression '/' CastExpression
4224 a := n.MultiplicativeExpression.check(ctx, isAsmArg)
4225 b := n.CastExpression.check(ctx, isAsmArg)
4226 n.IsSideEffectsFree = n.MultiplicativeExpression.IsSideEffectsFree && n.CastExpression.IsSideEffectsFree
4227 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4228 n.Operand = checkBinaryVectorArtithmetic(ctx, n, a, b)
4229 break
4230 }
4231
4232 if !a.Type().IsArithmeticType() || !b.Type().IsArithmeticType() {
4233 break
4234 }
4235
4236 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
4237 n.promote = a.Type()
4238 if a.Value() == nil || b.Value() == nil {
4239 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4240 break
4241 }
4242
4243 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().div(b.Value())}).normalize(ctx, n)
4244 case MultiplicativeExpressionMod: // MultiplicativeExpression '%' CastExpression
4245 a := n.MultiplicativeExpression.check(ctx, isAsmArg)
4246 b := n.CastExpression.check(ctx, isAsmArg)
4247 n.IsSideEffectsFree = n.MultiplicativeExpression.IsSideEffectsFree && n.CastExpression.IsSideEffectsFree
4248 if a.Type().Kind() == Vector || b.Type().Kind() == Vector {
4249 n.Operand = checkBinaryVectorArtithmetic(ctx, n, a, b)
4250 break
4251 }
4252
4253 if !a.Type().IsArithmeticType() || !b.Type().IsArithmeticType() {
4254 break
4255 }
4256
4257 if !a.Type().IsIntegerType() || !b.Type().IsIntegerType() {
4258 ctx.errNode(&n.Token, "the operands of the %% operator shall have integer type.") // [0] 6.5.5, 2
4259 break
4260 }
4261
4262 a, b = usualArithmeticConversions(ctx, &n.Token, a, b, true)
4263 n.promote = a.Type()
4264 if a.Value() == nil || b.Value() == nil {
4265 n.Operand = &operand{abi: &ctx.cfg.ABI, typ: a.Type()}
4266 break
4267 }
4268
4269 n.Operand = (&operand{abi: &ctx.cfg.ABI, typ: a.Type(), value: a.Value().mod(b.Value())}).normalize(ctx, n)
4270 default:
4271 panic(todo(""))
4272 }
4273 return n.Operand
4274}
4275
4276func (n *Declarator) check(ctx *context, td typeDescriptor, typ Type, tld bool) Type {
4277 if n == nil {
4278 n.typ = ctx.cfg.ABI.Type(Int)
4279 return noType
4280 }
4281
4282 typ = n.Pointer.check(ctx, typ)
4283 n.td = td
4284 if attr := n.AttributeSpecifierList.check(ctx, typ.baseP()); len(attr) != 0 {
4285 typ = &attributedType{typ, attr}
4286 }
4287 n.typ = n.DirectDeclarator.check(ctx, typ)
4288
4289 hasStorageSpecifiers := td.typedef() || td.extern() || td.static() ||
4290 td.auto() || td.register() || td.threadLocal()
4291
4292 typ = n.typ
4293 if typ == nil {
4294 n.typ = ctx.cfg.ABI.Type(Int)
4295 ctx.errNode(n, "declarator has unsupported, invalid or incomplete type")
4296 return noType
4297 }
4298
4299 if typ.Kind() == Array && typ.IsVLA() {
4300 if f := ctx.checkFn; f != nil {
4301 f.VLAs = append(f.VLAs, n)
4302 }
4303 }
4304
4305 // 6.2.2 Linkages of identifiers
4306 n.Linkage = None
4307 switch {
4308 case tld && td.static():
4309 // 3: If the declaration of a file scope identifier for an object or a function
4310 // contains the storage-class specifier static, the identifier has internal
4311 // linkage.
4312 n.Linkage = Internal
4313 case td.extern():
4314 //TODO
4315 //
4316 // 4: For an identifier declared with the storage-class specifier extern in a
4317 // scope in which a prior declaration of that identifier is visible, 23) if the
4318 // prior declaration specifies internal or external linkage, the linkage of the
4319 // identifier at the later declaration is the same as the linkage specified at
4320 // the prior declaration. If no prior declaration is visible, or if the prior
4321 // declaration specifies no linkage, then the identifier has external linkage.
4322 n.Linkage = External
4323 case
4324 !n.IsParameter && typ.Kind() == Function && !hasStorageSpecifiers,
4325 tld && !hasStorageSpecifiers:
4326
4327 // 5: If the declaration of an identifier for a function has no storage-class
4328 // specifier, its linkage is determined exactly as if it were declared with the
4329 // storage-class specifier extern.
4330 n.Linkage = External
4331 }
4332
4333 // 6.2.4 Storage durations of objects
4334 switch {
4335 case n.Linkage == External, n.Linkage == Internal, td.static():
4336 // 2: An object whose identifier is declared with external or internal linkage,
4337 // or with the storage-class specifier static has static storage duration. Its
4338 // lifetime is the entire execution of the program and its stored value is
4339 // initialized only once, prior to
4340 // program startup.
4341 n.StorageClass = Static
4342 case n.Linkage == None && !td.static():
4343 // 4: An object whose identifier is declared with no linkage and without the
4344 // storage-class specifier static has automatic storage duration.
4345 n.StorageClass = Automatic
4346 }
4347 switch {
4348 case n.typ.Kind() == Invalid:
4349 ctx.errNode(n, "declarator has incomplete type")
4350 }
4351 if n.IsTypedefName {
4352 if k, ok := complexTypedefs[n.Name()]; ok {
4353 abi := ctx.cfg.ABI
4354 t := n.typ.Alias()
4355 t.setKind(k)
4356 abi.types[k] = t
4357 abi.Types[k] = ABIType{Size: t.Size(), Align: t.Align(), FieldAlign: t.FieldAlign()}
4358 }
4359 }
4360 switch expr, ok := n.AttributeSpecifierList.Has(idVectorSize, idVectorSize2); {
4361 case ok:
4362 n.vectorize(ctx, expr)
4363 default:
4364 switch x := td.(type) {
4365 case *DeclarationSpecifiers:
4366 for ; x != nil; x = x.DeclarationSpecifiers {
4367 if expr, ok := x.AttributeSpecifier.Has(idVectorSize, idVectorSize2); ok {
4368 n.vectorize(ctx, expr)
4369 break
4370 }
4371 }
4372 }
4373 }
4374 return n.typ
4375}
4376
4377func (n *Declarator) vectorize(ctx *context, expr *ExpressionList) {
4378 dst := &n.typ
4379 elem := n.typ
4380 switch n.typ.Kind() {
4381 case Function:
4382 dst = &n.typ.(*functionType).result
4383 elem = n.typ.Result()
4384 }
4385
4386 sz := expr.vectorSize(ctx)
4387 if sz == 0 {
4388 sz = elem.Size()
4389 }
4390 if elem.Size() == 0 {
4391 ctx.errNode(expr, "vector element has zero size")
4392 return
4393 }
4394
4395 if sz%elem.Size() != 0 {
4396 ctx.errNode(expr, "vector size must be a multiple of the base size")
4397 }
4398 b := n.typ.base()
4399 b.size = sz
4400 b.kind = byte(Vector)
4401 *dst = &vectorType{
4402 typeBase: b,
4403 elem: elem,
4404 length: sz / elem.Size(),
4405 }
4406}
4407
4408func (n *ExpressionList) vectorSize(ctx *context) (r uintptr) {
4409 if n.ExpressionList != nil {
4410 ctx.errNode(n, "expected single expression")
4411 return 0
4412 }
4413
4414 switch x := n.AssignmentExpression.Operand.Value().(type) {
4415 case Int64Value:
4416 if x <= 0 {
4417 ctx.errNode(n, "expected integer greater than zero")
4418 return 0
4419 }
4420
4421 r = uintptr(x)
4422 case Uint64Value:
4423 r = uintptr(x)
4424 case nil:
4425 ctx.errNode(n, "expected constant expression")
4426 r = 0
4427 default:
4428 panic(todo("%T", x))
4429 }
4430 if bits.OnesCount64(uint64(r)) != 1 {
4431 ctx.errNode(n, "expected a power of two")
4432 r = 0
4433 }
4434 return r
4435}
4436
4437func (n *DirectDeclarator) check(ctx *context, typ Type) Type {
4438 if n == nil {
4439 return noType
4440 }
4441
4442 switch n.Case {
4443 case DirectDeclaratorIdent: // IDENTIFIER Asm
4444 n.Asm.check(ctx)
4445 return typ
4446 case DirectDeclaratorDecl: // '(' AttributeSpecifierList Declarator ')'
4447 n.AttributeSpecifierList.check(ctx, typ.baseP())
4448 return n.Declarator.check(ctx, noTypeDescriptor, typ, false)
4449 case DirectDeclaratorArr: // DirectDeclarator '[' TypeQualifiers AssignmentExpression ']'
4450 return n.DirectDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, true, false))
4451 case DirectDeclaratorStaticArr: // DirectDeclarator '[' "static" TypeQualifiers AssignmentExpression ']'
4452 return n.DirectDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, false, false))
4453 case DirectDeclaratorArrStatic: // DirectDeclarator '[' TypeQualifiers "static" AssignmentExpression ']'
4454 return n.DirectDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, n.AssignmentExpression, false, false))
4455 case DirectDeclaratorStar: // DirectDeclarator '[' TypeQualifiers '*' ']'
4456 return n.DirectDeclarator.check(ctx, checkArray(ctx, &n.Token, typ, nil, true, true))
4457 case DirectDeclaratorFuncParam: // DirectDeclarator '(' ParameterTypeList ')'
4458 ft := &functionType{typeBase: typeBase{kind: byte(Function)}, result: typ}
4459 if typ != nil && typ.Inline() {
4460 ft.typeBase.flags = fInline
4461 }
4462 n.ParameterTypeList.check(ctx, ft)
4463 return n.DirectDeclarator.check(ctx, ft)
4464 case DirectDeclaratorFuncIdent: // DirectDeclarator '(' IdentifierList ')'
4465 ft := &functionType{typeBase: typeBase{kind: byte(Function)}, result: typ, paramList: n.IdentifierList.check(ctx)}
4466 if typ != nil && typ.Inline() {
4467 ft.typeBase.flags = fInline
4468 }
4469 if n.idListNoDeclList {
4470 n.checkIdentList(ctx, ft)
4471 }
4472 return n.DirectDeclarator.check(ctx, ft)
4473 }
4474
4475 panic(internalErrorf("%v: %v", n.Position(), n.Case))
4476}
4477
4478func (n *DirectDeclarator) checkIdentList(ctx *context, ft *functionType) {
4479 s := n.paramScope
4480 for _, nm := range ft.paramList {
4481 d := s[nm][0].(*Declarator)
4482 d.check(ctx, noTypeDescriptor, ctx.cfg.ABI.Type(Int), false)
4483 ft.params = append(ft.params, &Parameter{d, d.Type()})
4484 }
4485}
4486
4487func checkArray(ctx *context, n Node, typ Type, expr *AssignmentExpression, exprIsOptional, noExpr bool) Type { //TODO pass and use typeQualifiers
4488 if typ == nil {
4489 ctx.errNode(n, "array of invalid or incomplete type")
4490 return noType
4491 }
4492
4493 b := typ.base()
4494 b.align = byte(typ.Align())
4495 b.fieldAlign = byte(typ.FieldAlign())
4496 b.kind = byte(Array)
4497 switch {
4498 case expr != nil && noExpr:
4499 panic(todo(""))
4500 case expr != nil:
4501 op := expr.check(ctx, false)
4502 if op.Type().Kind() == Invalid {
4503 return noType
4504 }
4505
4506 if !op.Type().IsIntegerType() {
4507 //TODO report err
4508 return noType
4509 }
4510
4511 var length uintptr
4512 var vla bool
4513 var vlaExpr *AssignmentExpression
4514 switch x := op.Value().(type) {
4515 case nil:
4516 vla = true
4517 vlaExpr = expr
4518 case Int64Value:
4519 length = uintptr(x)
4520 case Uint64Value:
4521 length = uintptr(x)
4522 }
4523 switch {
4524 case vla:
4525 b.size = ctx.cfg.ABI.Types[Ptr].Size
4526 default:
4527 if typ.IsIncomplete() {
4528 //TODO report error
4529 return noType
4530 }
4531
4532 b.size = length * typ.Size()
4533 }
4534 return &arrayType{typeBase: b, decay: ctx.cfg.ABI.Ptr(n, typ), elem: typ, length: length, vla: vla, expr: vlaExpr}
4535 case noExpr:
4536 // nop
4537 case !exprIsOptional:
4538 panic(todo(""))
4539 }
4540 b.flags |= fIncomplete
4541 return &arrayType{typeBase: b, decay: ctx.cfg.ABI.Ptr(n, typ), elem: typ}
4542}
4543
4544func (n *IdentifierList) check(ctx *context) (r []StringID) {
4545 for ; n != nil; n = n.IdentifierList {
4546 tok := n.Token2.Value
4547 if tok == 0 {
4548 tok = n.Token.Value
4549 }
4550 r = append(r, tok)
4551 }
4552 return r
4553}
4554
4555func (n *Asm) check(ctx *context) {
4556 if n == nil {
4557 return
4558 }
4559
4560 n.AsmQualifierList.check(ctx)
4561 n.AsmArgList.check(ctx)
4562}
4563
4564func (n *AsmArgList) check(ctx *context) {
4565 for ; n != nil; n = n.AsmArgList {
4566 n.AsmExpressionList.check(ctx)
4567 }
4568}
4569
4570func (n *AsmExpressionList) check(ctx *context) {
4571 if ctx.cfg.DoNotTypecheckAsm {
4572 return
4573 }
4574
4575 for ; n != nil; n = n.AsmExpressionList {
4576 n.AsmIndex.check(ctx)
4577 n.AssignmentExpression.check(ctx, true)
4578 }
4579}
4580
4581func (n *AsmIndex) check(ctx *context) {
4582 if n == nil {
4583 return
4584 }
4585
4586 n.Expression.check(ctx, true)
4587}
4588
4589func (n *AsmQualifierList) check(ctx *context) {
4590 for ; n != nil; n = n.AsmQualifierList {
4591 n.AsmQualifier.check(ctx)
4592 }
4593}
4594
4595func (n *AsmQualifier) check(ctx *context) {
4596 if n == nil {
4597 return
4598 }
4599
4600 switch n.Case {
4601 case AsmQualifierVolatile: // "volatile"
4602 //TODO
4603 case AsmQualifierInline: // "inline"
4604 //TODO
4605 case AsmQualifierGoto: // "goto"
4606 //TODO
4607 default:
4608 panic(todo(""))
4609 }
4610}
4611
4612func (n *AttributeSpecifierList) check(ctx *context, t *typeBase) (a []*AttributeSpecifier) {
4613 for ; n != nil; n = n.AttributeSpecifierList {
4614 a = append(a, n.AttributeSpecifier.check(ctx, t))
4615 }
4616 return a
4617}
4618
4619func (n *AttributeSpecifier) check(ctx *context, t *typeBase) *AttributeSpecifier {
4620 if n == nil {
4621 return nil
4622 }
4623
4624 n.AttributeValueList.check(ctx, t)
4625 return n
4626}
4627
4628func (n *AttributeValueList) check(ctx *context, t *typeBase) {
4629 for ; n != nil; n = n.AttributeValueList {
4630 n.AttributeValue.check(ctx, t)
4631 }
4632}
4633
4634func (n *AttributeValue) check(ctx *context, t *typeBase) {
4635 if n == nil {
4636 return
4637 }
4638
4639 switch n.Case {
4640 case AttributeValueIdent: // IDENTIFIER
4641 if n.Token.Value == idPacked && t != nil {
4642 t.flags |= fPacked
4643 }
4644 case AttributeValueExpr: // IDENTIFIER '(' ExpressionList ')'
4645 v := ctx.cfg.ignoreErrors
4646 ctx.cfg.ignoreErrors = true
4647 defer func() { ctx.cfg.ignoreErrors = v }()
4648 n.ExpressionList.check(ctx, false)
4649 if n.Token.Value == idAligned && n.ExpressionList != nil && t != nil {
4650 switch x := n.ExpressionList.AssignmentExpression.Operand.Value().(type) {
4651 case Int64Value:
4652 t.setAligned(int(x))
4653 switch t.Kind() {
4654 case Struct, Union:
4655 ctx.structs[StructInfo{Size: t.Size(), Align: t.Align()}] = struct{}{}
4656 }
4657 }
4658 }
4659 default:
4660 panic(todo(""))
4661 }
4662}
4663
4664func (n *ExpressionList) check(ctx *context, isAsmArg bool) {
4665 for ; n != nil; n = n.ExpressionList {
4666 n.AssignmentExpression.check(ctx, isAsmArg)
4667 }
4668}
4669
4670func (n *DeclarationSpecifiers) check(ctx *context, inUnion bool) (r Type, inline, noret bool) {
4671 n0 := n
4672 typ := &typeBase{}
4673 for ; n != nil; n = n.DeclarationSpecifiers {
4674 switch n.Case {
4675 case DeclarationSpecifiersStorage: // StorageClassSpecifier DeclarationSpecifiers
4676 n.StorageClassSpecifier.check(ctx, n)
4677 case DeclarationSpecifiersTypeSpec: // TypeSpecifier DeclarationSpecifiers
4678 n.TypeSpecifier.check(ctx, typ, inUnion)
4679 case DeclarationSpecifiersTypeQual: // TypeQualifier DeclarationSpecifiers
4680 n.TypeQualifier.check(ctx, typ)
4681 case DeclarationSpecifiersFunc: // FunctionSpecifier DeclarationSpecifiers
4682 if n.FunctionSpecifier == nil {
4683 break
4684 }
4685
4686 switch n.FunctionSpecifier.Case {
4687 case FunctionSpecifierInline: // "inline"
4688 inline = true
4689 case FunctionSpecifierNoreturn: // "_Noreturn"
4690 noret = true
4691 default:
4692 panic(todo(""))
4693 }
4694 case DeclarationSpecifiersAlignSpec: // AlignmentSpecifier DeclarationSpecifiers
4695 n.AlignmentSpecifier.check(ctx)
4696 case DeclarationSpecifiersAttribute: // AttributeSpecifier DeclarationSpecifiers
4697 n.AttributeSpecifier.check(ctx, typ)
4698 default:
4699 panic(todo(""))
4700 }
4701 }
4702 r = typ.check(ctx, n0, true)
4703 return r, inline, noret
4704}
4705
4706func (n *AlignmentSpecifier) check(ctx *context) {
4707 if n == nil {
4708 return
4709 }
4710
4711 switch n.Case {
4712 case AlignmentSpecifierAlignasType: // "_Alignas" '(' TypeName ')'
4713 n.TypeName.check(ctx, false, false, nil)
4714 //TODO actually set the alignment
4715 case AlignmentSpecifierAlignasExpr: // "_Alignas" '(' ConstantExpression ')'
4716 n.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false)
4717 //TODO actually set the alignment
4718 default:
4719 panic(todo(""))
4720 }
4721}
4722
4723func (n *StorageClassSpecifier) check(ctx *context, ds *DeclarationSpecifiers) {
4724 if n == nil {
4725 return
4726 }
4727
4728 switch n.Case {
4729 case StorageClassSpecifierTypedef: // "typedef"
4730 ds.class |= fTypedef
4731 case StorageClassSpecifierExtern: // "extern"
4732 ds.class |= fExtern
4733 case StorageClassSpecifierStatic: // "static"
4734 ds.class |= fStatic
4735 case StorageClassSpecifierAuto: // "auto"
4736 ds.class |= fAuto
4737 case StorageClassSpecifierRegister: // "register"
4738 ds.class |= fRegister
4739 case StorageClassSpecifierThreadLocal: // "_Thread_local"
4740 ds.class |= fThreadLocal
4741 default:
4742 panic(todo(""))
4743 }
4744 c := bits.OnesCount(uint(ds.class & (fTypedef | fExtern | fStatic | fAuto | fRegister | fThreadLocal)))
4745 if c == 1 {
4746 return
4747 }
4748
4749 // [2], 6.7.1, 2
4750 if c == 2 && ds.class&fThreadLocal != 0 {
4751 if ds.class&(fStatic|fExtern) != 0 {
4752 return
4753 }
4754 }
4755
4756 ctx.errNode(n, "at most, one storage-class specifier may be given in the declaration specifiers in a declaration")
4757}
4758
4759// DeclarationSpecifiers Declarator DeclarationList CompoundStatement
4760func (n *FunctionDefinition) checkDeclarator(ctx *context) {
4761 if n == nil {
4762 return
4763 }
4764
4765 n.Declarator.fnDef = true
4766 n.Declarator.funcDefinition = n
4767 ctx.checkFn = n
4768 typ, inline, noret := n.DeclarationSpecifiers.check(ctx, false)
4769 typ = n.Declarator.check(ctx, n.DeclarationSpecifiers, typ, true)
4770 typ.setFnSpecs(inline, noret)
4771 ctx.checkFn = nil
4772 n.DeclarationList.checkFn(ctx, typ, n.Declarator.ParamScope())
4773}
4774
4775func (n *DeclarationList) checkFn(ctx *context, typ Type, s Scope) {
4776 if n == nil {
4777 return
4778 }
4779
4780 n.check(ctx)
4781 ft, ok := typ.(*functionType)
4782 if !ok {
4783 return
4784 }
4785
4786 if ft.params != nil {
4787 //TODO report error
4788 return
4789 }
4790
4791 if len(ft.paramList) == 0 {
4792 //TODO report error
4793 return
4794 }
4795
4796 m := make(map[StringID]int, len(ft.paramList))
4797 for i, v := range ft.paramList {
4798 if _, ok := m[v]; ok {
4799 ctx.errNode(n, "duplicate parameter: %s", v)
4800 continue
4801 }
4802
4803 m[v] = i
4804 }
4805 params := make([]*Parameter, len(m))
4806 i := 0
4807 for ; n != nil; n = n.DeclarationList {
4808 for n := n.Declaration.InitDeclaratorList; n != nil; n = n.InitDeclaratorList {
4809 n := n.InitDeclarator
4810 switch n.Case {
4811 case InitDeclaratorDecl: // Declarator AttributeSpecifierList
4812 nm := n.Declarator.Name()
4813 n.Declarator.IsParameter = true
4814 switch x, ok := m[nm]; {
4815 case ok:
4816 params[x] = &Parameter{d: n.Declarator, typ: n.Declarator.Type()}
4817 i++
4818 default:
4819 //TODO report error
4820 }
4821 case InitDeclaratorInit: // Declarator AttributeSpecifierList '=' Initializer
4822 //TODO report error
4823 return
4824 default:
4825 panic(todo(""))
4826 }
4827 }
4828 }
4829 for i, v := range params {
4830 if v != nil {
4831 continue
4832 }
4833
4834 nm := ft.paramList[i]
4835 d := &Declarator{
4836 DirectDeclarator: &DirectDeclarator{
4837 Case: DirectDeclaratorIdent,
4838 Token: Token{Rune: IDENTIFIER, Value: nm},
4839 },
4840 IsParameter: true,
4841 Linkage: None,
4842 StorageClass: Automatic,
4843 typ: ctx.cfg.ABI.Type(Int),
4844 }
4845 s.declare(nm, d)
4846 params[i] = &Parameter{d, d.typ}
4847 }
4848 ft.params = params
4849}
4850
4851func (n *CompoundStatement) check(ctx *context) Operand {
4852 n.Operand = n.BlockItemList.check(ctx)
4853 return n.Operand
4854}
4855
4856func (n *BlockItemList) check(ctx *context) (r Operand) {
4857 r = noOperand
4858 var last *BlockItem
4859 for ; n != nil; n = n.BlockItemList {
4860 last = n.BlockItem
4861 r = n.BlockItem.check(ctx)
4862 }
4863 if last != nil {
4864 last.Last = true
4865 }
4866 return r
4867}
4868
4869func (n *BlockItem) check(ctx *context) Operand {
4870 if n == nil {
4871 return noOperand
4872 }
4873
4874 switch n.Case {
4875 case BlockItemDecl: // Declaration
4876 n.Declaration.check(ctx, false)
4877 case BlockItemStmt: // Statement
4878 return n.Statement.check(ctx)
4879 case BlockItemLabel: // LabelDeclaration
4880 n.LabelDeclaration.check(ctx)
4881 case BlockItemFuncDef: // DeclarationSpecifiers Declarator CompoundStatement
4882 ctxClosure := ctx.closure
4883 ctx.closure = nil
4884 ctxCheckFn := ctx.checkFn
4885 fn := &FunctionDefinition{
4886 DeclarationSpecifiers: n.DeclarationSpecifiers,
4887 Declarator: n.Declarator,
4888 CompoundStatement: n.CompoundStatement,
4889 }
4890 n.fn = fn
4891 ctx.checkFn = fn
4892 n.CompoundStatement.scope.declare(idClosure, n)
4893 fn.checkDeclarator(ctx)
4894 ctxCapture := ctx.capture
4895 ctx.capture = true
4896 fn.checkBody(ctx)
4897 n.closure = ctx.closure
4898 ctx.capture = ctxCapture
4899 delete(n.CompoundStatement.scope, idClosure)
4900 ctx.checkFn = ctxCheckFn
4901 ctx.closure = ctxClosure
4902 case BlockItemPragma: // PragmaSTDC
4903 n.PragmaSTDC.check(ctx)
4904 default:
4905 panic(todo(""))
4906 }
4907 return noOperand
4908}
4909
4910func (n *LabelDeclaration) check(ctx *context) {
4911 if n == nil {
4912 return
4913 }
4914
4915 n.IdentifierList.check(ctx)
4916}
4917
4918func (n *Statement) check(ctx *context) Operand {
4919 if n == nil {
4920 return noOperand
4921 }
4922
4923 n.Operand = noOperand
4924 switch n.Case {
4925 case StatementLabeled: // LabeledStatement
4926 n.LabeledStatement.check(ctx)
4927 case StatementCompound: // CompoundStatement
4928 n.Operand = n.CompoundStatement.check(ctx)
4929 case StatementExpr: // ExpressionStatement
4930 n.Operand = n.ExpressionStatement.check(ctx)
4931 case StatementSelection: // SelectionStatement
4932 n.SelectionStatement.check(ctx)
4933 case StatementIteration: // IterationStatement
4934 n.IterationStatement.check(ctx)
4935 case StatementJump: // JumpStatement
4936 n.JumpStatement.check(ctx)
4937 case StatementAsm: // AsmStatement
4938 n.AsmStatement.check(ctx)
4939 default:
4940 panic(todo(""))
4941 }
4942 return n.Operand
4943}
4944
4945func (n *JumpStatement) check(ctx *context) {
4946 if n == nil {
4947 return
4948 }
4949
4950 switch n.Case {
4951 case JumpStatementGoto: // "goto" IDENTIFIER ';'
4952 n.context = ctx.breakCtx
4953 if ctx.checkFn.Gotos == nil {
4954 ctx.checkFn.Gotos = map[StringID]*JumpStatement{}
4955 }
4956 ctx.checkFn.Gotos[n.Token2.Value] = n
4957 case JumpStatementGotoExpr: // "goto" '*' Expression ';'
4958 n.Expression.check(ctx, false)
4959 //TODO
4960 case JumpStatementContinue: // "continue" ';'
4961 n.context = ctx.breakCtx
4962 if ctx.continues <= 0 {
4963 panic(n.Position().String())
4964 }
4965 //TODO
4966 case JumpStatementBreak: // "break" ';'
4967 n.context = ctx.breakCtx
4968 if ctx.breaks <= 0 {
4969 panic(n.Position().String())
4970 }
4971 //TODO
4972 case JumpStatementReturn: // "return" Expression ';'
4973 n.context = ctx.breakCtx
4974 op := n.Expression.check(ctx, false)
4975 if op.Type().IsComplexType() {
4976 ctx.checkFn.ReturnComplexExpr = append(ctx.checkFn.ReturnComplexExpr, n.Expression)
4977 }
4978 default:
4979 panic(todo(""))
4980 }
4981}
4982
4983func (n *IterationStatement) check(ctx *context) {
4984 if n == nil {
4985 return
4986 }
4987
4988 sv := ctx.breakCtx
4989 ctx.breakCtx = n
4990
4991 defer func() { ctx.breakCtx = sv }()
4992
4993 switch n.Case {
4994 case IterationStatementWhile: // "while" '(' Expression ')' Statement
4995 n.Expression.check(ctx, false)
4996 ctx.breaks++
4997 ctx.continues++
4998 n.Statement.check(ctx)
4999 ctx.breaks--
5000 ctx.continues--
5001 case IterationStatementDo: // "do" Statement "while" '(' Expression ')' ';'
5002 ctx.breaks++
5003 ctx.continues++
5004 n.Statement.check(ctx)
5005 ctx.breaks--
5006 ctx.continues--
5007 n.Expression.check(ctx, false)
5008 case IterationStatementFor: // "for" '(' Expression ';' Expression ';' Expression ')' Statement
5009 n.Expression.check(ctx, false)
5010 n.Expression2.check(ctx, false)
5011 n.Expression3.check(ctx, false)
5012 ctx.breaks++
5013 ctx.continues++
5014 n.Statement.check(ctx)
5015 ctx.breaks--
5016 ctx.continues--
5017 case IterationStatementForDecl: // "for" '(' Declaration Expression ';' Expression ')' Statement
5018 n.Declaration.check(ctx, false)
5019 n.Expression.check(ctx, false)
5020 n.Expression2.check(ctx, false)
5021 ctx.breaks++
5022 ctx.continues++
5023 n.Statement.check(ctx)
5024 ctx.breaks--
5025 ctx.continues--
5026 default:
5027 panic(todo(""))
5028 }
5029}
5030
5031func (n *SelectionStatement) check(ctx *context) {
5032 if n == nil {
5033 return
5034 }
5035
5036 switch n.Case {
5037 case SelectionStatementIf: // "if" '(' Expression ')' Statement
5038 n.Expression.check(ctx, false)
5039 n.Statement.check(ctx)
5040 case SelectionStatementIfElse: // "if" '(' Expression ')' Statement "else" Statement
5041 n.Expression.check(ctx, false)
5042 n.Statement.check(ctx)
5043 n.Statement2.check(ctx)
5044 if !n.Expression.Operand.Type().IsScalarType() {
5045 //TODO report err
5046 break
5047 }
5048 case SelectionStatementSwitch: // "switch" '(' Expression ')' Statement
5049 if n == nil {
5050 return
5051 }
5052
5053 sv := ctx.breakCtx
5054 ctx.breakCtx = n
5055
5056 defer func() { ctx.breakCtx = sv }()
5057
5058 op := n.Expression.check(ctx, false)
5059 n.promote = op.integerPromotion(ctx, n).Type()
5060 cp := ctx.casePromote
5061 ctx.casePromote = n.promote
5062 cs := ctx.cases
5063 ctx.cases = nil
5064 ctx.switches++
5065 ctx.breaks++
5066 n.Statement.check(ctx)
5067 ctx.breaks--
5068 ctx.switches--
5069 n.cases = ctx.cases
5070 ctx.cases = cs
5071 ctx.casePromote = cp
5072 default:
5073 panic(todo(""))
5074 }
5075}
5076
5077func (n *ExpressionStatement) check(ctx *context) Operand {
5078 if n == nil {
5079 return noOperand
5080 }
5081
5082 n.AttributeSpecifierList.check(ctx, nil)
5083 return n.Expression.check(ctx, false)
5084}
5085
5086func (n *LabeledStatement) check(ctx *context) {
5087 if n == nil {
5088 return
5089 }
5090
5091 switch n.Case {
5092 case LabeledStatementLabel: // IDENTIFIER ':' AttributeSpecifierList Statement
5093 if ctx.checkFn.Labels == nil {
5094 ctx.checkFn.Labels = map[StringID]*LabeledStatement{}
5095 }
5096 if _, ok := ctx.checkFn.Labels[n.Token.Value]; ok {
5097 //TODO report redeclared
5098 }
5099 ctx.checkFn.Labels[n.Token.Value] = n
5100 n.AttributeSpecifierList.check(ctx, nil)
5101 n.Statement.check(ctx)
5102 case LabeledStatementCaseLabel: // "case" ConstantExpression ':' Statement
5103 if ctx.switches <= 0 {
5104 //TODO report error
5105 break
5106 }
5107
5108 switch op := n.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false); op.Value().(type) {
5109 case Int64Value, Uint64Value:
5110 if t := ctx.casePromote; t.Kind() != Invalid {
5111 n.ConstantExpression.Operand = op.convertTo(ctx, n, t)
5112 break
5113 }
5114
5115 //TODO report error
5116 default:
5117 //TODO report error
5118 }
5119 ctx.cases = append(ctx.cases, n)
5120 n.Statement.check(ctx)
5121 case LabeledStatementRange: // "case" ConstantExpression "..." ConstantExpression ':' Statement
5122 if ctx.switches <= 0 {
5123 //TODO report error
5124 break
5125 }
5126
5127 switch n.ConstantExpression.check(ctx, ctx.mode|mIntConstExpr, false).Value().(type) {
5128 case Int64Value, Uint64Value:
5129 // ok
5130 default:
5131 //TODO report error
5132 }
5133 switch n.ConstantExpression2.check(ctx, ctx.mode|mIntConstExpr, false).Value().(type) {
5134 case Int64Value, Uint64Value:
5135 // ok
5136 default:
5137 //TODO report error
5138 }
5139 ctx.cases = append(ctx.cases, n)
5140 n.Statement.check(ctx)
5141 case LabeledStatementDefault: // "default" ':' Statement
5142 if ctx.switches <= 0 {
5143 //TODO report error
5144 break
5145 }
5146
5147 ctx.cases = append(ctx.cases, n)
5148 n.Statement.check(ctx)
5149 default:
5150 panic(todo(""))
5151 }
5152}
5153
5154func (n *DeclarationList) check(ctx *context) {
5155 for ; n != nil; n = n.DeclarationList {
5156 n.Declaration.check(ctx, false)
5157 }
5158}
5159
5160func setAddressTaken(n Node, d *Declarator, s string) {
5161 d.AddressTaken = true
5162 // fmt.Printf("%v: %s, type %v (%v, %v), declared at %v, AddressTaken = true: %v\n",
5163 // n.Position(), d.Name(), d.Type(), d.Type().Kind(), d.Type().Size(), d.Position(), s,
5164 // ) //TODO-
5165}
5166
5167// Dump returns a debug form of n.
5168func (n *Initializer) Dump() string {
5169 var b strings.Builder
5170 f := strutil.IndentFormatter(&b, "\t")
5171 n.dump(f)
5172 return b.String()
5173}
5174
5175func pos(n Node) (r token.Position) {
5176 if n == nil {
5177 return r
5178 }
5179
5180 r = token.Position(n.Position())
5181 if r.IsValid() {
5182 r.Filename = filepath.Base(r.Filename)
5183 }
5184 return r
5185}
5186
5187func (n *Initializer) dump(f strutil.Formatter) {
5188 list := n.List()
5189 if len(list) != 0 {
5190 for i, v := range list {
5191 f.Format("Initializer.List() #%d/%d: %v: off %v type %v", i, len(list), pos(v), v.Offset, v.Type())
5192 if fld := v.FirstDesignatorField(); fld != nil {
5193 f.Format(" [FirstDesignatorField %q]", fld.Name())
5194 }
5195 f.Format("\n")
5196 }
5197 }
5198 if f0 := n.FirstDesignatorField(); f0 != nil {
5199 f.Format("[FirstDesignatorField: %q, index %v, off %v, type %v] ", f0.Name(), f0.Index(), n.Offset, n.Type().Alias())
5200 }
5201 switch n.Case {
5202 case InitializerExpr: // AssignmentExpression
5203 if op := n.AssignmentExpression.Operand; op != nil {
5204 n.isConst = op.IsConst()
5205 n.isZero = op.IsZero()
5206 }
5207 var t Type
5208 if n.AssignmentExpression != nil && n.AssignmentExpression.Operand != nil {
5209 t = n.AssignmentExpression.Operand.Type()
5210 }
5211 f.Format("%v: %T@%[2]p, .Case %v, off %v, type %v\n", pos(n), n, n.Case, n.Offset, t.Alias())
5212 case InitializerInitList: // '{' InitializerList ',' '}'
5213 n.InitializerList.dump(f)
5214 default:
5215 panic(todo("%v:", n.Position()))
5216 }
5217}
5218
5219// Dump returns a debug form of n.
5220func (n *InitializerList) Dump() string {
5221 var b strings.Builder
5222 f := strutil.IndentFormatter(&b, "\t")
5223 n.dump(f)
5224 return b.String()
5225}
5226
5227func (n *InitializerList) dump(f strutil.Formatter) {
5228 if n == nil {
5229 f.Format("<nil>")
5230 return
5231 }
5232
5233 f.Format("%v: %T@%[2]p, len(.List()) %v {%i\n", pos(n), n, len(n.List()))
5234 list := n.List()
5235 for ; n != nil; n = n.InitializerList {
5236 n.Designation.dump(f)
5237 n.Initializer.dump(f)
5238 }
5239 for i, v := range list {
5240 f.Format("InitializerList.List() #%d/%d:", i, len(list))
5241 v.dump(f)
5242 }
5243 f.Format("%u}\n")
5244}
5245
5246func (n *Designation) dump(f strutil.Formatter) {
5247 if n == nil {
5248 return
5249 }
5250
5251 cnt := 0
5252 designatorField2 := false
5253 for n := n.DesignatorList; n != nil; n = n.DesignatorList {
5254 n.Designator.dump(f)
5255 if n.Designator.Case == DesignatorField2 {
5256 designatorField2 = true
5257 }
5258 cnt++
5259 }
5260 if cnt > 1 || !designatorField2 {
5261 f.Format(" = ")
5262 }
5263}
5264
5265func (n *Designator) dump(f strutil.Formatter) {
5266 switch n.Case {
5267 case DesignatorIndex: // '[' ConstantExpression ']'
5268 f.Format("[%v]", n.ConstantExpression.Operand.Value())
5269 case DesignatorField: // '.' IDENTIFIER
5270 f.Format(".%s", n.Token2.Value)
5271 case DesignatorField2: // IDENTIFIER ':'
5272 f.Format("%s:", n.Token.Value)
5273 default:
5274 panic(todo(""))
5275 }
5276}
Note: See TracBrowser for help on using the repository browser.