source: code/trunk/vendor/modernc.org/cc/v3/ast2.go@ 824

Last change on this file since 824 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: 33.0 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 "io"
10 "os"
11 "path/filepath"
12 "sort"
13 "strings"
14)
15
16// Source is a named part of a translation unit. If Value is empty, Name is
17// interpreted as a path to file containing the source code.
18type Source struct {
19 Name string
20 Value string
21 DoNotCache bool // Disable caching of this source
22}
23
24// Promote returns the type the operands of a binary operation are promoted to
25// or the type and argument passed in a function call is promoted.
26func (n *AssignmentExpression) Promote() Type { return n.promote }
27
28type StructInfo struct {
29 Size uintptr
30
31 Align int
32}
33
34// AST represents a translation unit and its related data.
35type AST struct {
36 Enums map[StringID]Operand // Enumeration constants declared in file scope.
37 Macros map[StringID]*Macro // Macros as defined after parsing.
38 PtrdiffType Type
39 Scope Scope // File scope.
40 SizeType Type
41 StructTypes map[StringID]Type // Tagged struct/union types declared in file scope.
42 // Alignment and size of every struct/union defined in the translation
43 // unit. Valid only after Translate.
44 Structs map[StructInfo]struct{}
45 // TLD contains pruned file scope declarators, ie. either the first one
46 // or the first one that has an initializer.
47 TLD map[*Declarator]struct{}
48 TrailingSeperator StringID // White space and/or comments preceding EOF.
49 TranslationUnit *TranslationUnit
50 WideCharType Type
51 cfg *Config
52 cpp *cpp
53}
54
55// Eval returns the operand that represents the value of m, if it expands to a
56// valid constant expression other than an identifier, or an error, if any.
57func (n *AST) Eval(m *Macro) (o Operand, err error) {
58 defer func() {
59 if e := recover(); e != nil {
60 o = nil
61 err = fmt.Errorf("%v", e)
62 }
63 }()
64
65 if m.IsFnLike() {
66 return nil, fmt.Errorf("cannot evaluate function-like macro")
67 }
68
69 n.cpp.ctx.cfg.ignoreErrors = true
70 n.cpp.ctx.evalIdentError = true
71 v := n.cpp.eval(m.repl)
72 switch x := v.(type) {
73 case int64:
74 return &operand{abi: &n.cfg.ABI, typ: n.cfg.ABI.Type(LongLong), value: Int64Value(x)}, nil
75 case uint64:
76 return &operand{abi: &n.cfg.ABI, typ: n.cfg.ABI.Type(ULongLong), value: Uint64Value(x)}, nil
77 default:
78 return nil, fmt.Errorf("unexpected value: %T", x)
79 }
80}
81
82// Parse preprocesses and parses a translation unit and returns an *AST or
83// error, if any.
84//
85// Search paths listed in includePaths and sysIncludePaths are used to resolve
86// #include "foo.h" and #include <foo.h> preprocessing directives respectively.
87// A special search path "@" is interpreted as 'the same directory as where the
88// file with the #include directive is'.
89//
90// The sources should typically provide, usually in this particular order:
91//
92// - predefined macros, eg.
93//
94// #define __SIZE_TYPE__ long unsigned int
95//
96// - built-in declarations, eg.
97//
98// int __builtin_printf(char *__format, ...);
99//
100// - command-line provided directives, eg.
101//
102// #define FOO
103// #define BAR 42
104// #undef QUX
105//
106// - normal C sources, eg.
107//
108// int main() {}
109//
110// All search and file paths should be absolute paths.
111//
112// If the preprocessed translation unit is empty, the function may return (nil,
113// nil).
114//
115// The parser does only the minimum declarations/identifier resolving necessary
116// for correct parsing. Redeclarations are not checked.
117//
118// Declarators (*Declarator) and StructDeclarators (*StructDeclarator) are
119// inserted in the appropriate scopes.
120//
121// Tagged struct/union specifier definitions (*StructOrUnionSpecifier) are
122// inserted in the appropriate scopes.
123//
124// Tagged enum specifier definitions (*EnumSpecifier) and enumeration constants
125// (*Enumerator) are inserted in the appropriate scopes.
126//
127// Labels (*LabeledStatement) are inserted in the appropriate scopes.
128func Parse(cfg *Config, includePaths, sysIncludePaths []string, sources []Source) (*AST, error) {
129 return parse(newContext(cfg), includePaths, sysIncludePaths, sources)
130}
131
132func parse(ctx *context, includePaths, sysIncludePaths []string, sources []Source) (*AST, error) {
133 if s := ctx.cfg.SharedFunctionDefinitions; s != nil {
134 if s.M == nil {
135 s.M = map[*FunctionDefinition]struct{}{}
136 }
137 if s.m == nil {
138 s.m = map[sharedFunctionDefinitionKey]*FunctionDefinition{}
139 }
140 }
141 if debugWorkingDir || ctx.cfg.DebugWorkingDir {
142 switch wd, err := os.Getwd(); err {
143 case nil:
144 fmt.Fprintf(os.Stderr, "OS working dir: %s\n", wd)
145 default:
146 fmt.Fprintf(os.Stderr, "OS working dir: error %s\n", err)
147 }
148 fmt.Fprintf(os.Stderr, "Config.WorkingDir: %s\n", ctx.cfg.WorkingDir)
149 }
150 if debugIncludePaths || ctx.cfg.DebugIncludePaths {
151 fmt.Fprintf(os.Stderr, "include paths: %v\n", includePaths)
152 fmt.Fprintf(os.Stderr, "system include paths: %v\n", sysIncludePaths)
153 }
154 ctx.includePaths = includePaths
155 ctx.sysIncludePaths = sysIncludePaths
156 var in []source
157 for _, v := range sources {
158 ts, err := cache.get(ctx, v)
159 if err != nil {
160 return nil, err
161 }
162
163 in = append(in, ts)
164 }
165
166 p := newParser(ctx, make(chan *[]Token, 5000)) //DONE benchmark tuned
167 var sep StringID
168 var ssep []byte
169 var seq int32
170 cpp := newCPP(ctx)
171 go func() {
172
173 defer func() {
174 close(p.in)
175 ctx.intMaxWidth = cpp.intMaxWidth()
176 }()
177
178 toks := tokenPool.Get().(*[]Token)
179 *toks = (*toks)[:0]
180 for pline := range cpp.translationPhase4(in) {
181 line := *pline
182 for _, tok := range line {
183 switch tok.char {
184 case ' ', '\n':
185 if ctx.cfg.PreserveOnlyLastNonBlankSeparator {
186 if strings.TrimSpace(tok.value.String()) != "" {
187 sep = tok.value
188 }
189 break
190 }
191
192 switch {
193 case sep != 0:
194 ssep = append(ssep, tok.String()...)
195 default:
196 sep = tok.value
197 ssep = append(ssep[:0], sep.String()...)
198 }
199 default:
200 var t Token
201 t.Rune = tok.char
202 switch {
203 case len(ssep) != 0:
204 t.Sep = dict.id(ssep)
205 default:
206 t.Sep = sep
207 }
208 t.Value = tok.value
209 t.Src = tok.src
210 t.file = tok.file
211 t.macro = tok.macro
212 t.pos = tok.pos
213 seq++
214 t.seq = seq
215 *toks = append(*toks, t)
216 sep = 0
217 ssep = ssep[:0]
218 }
219 }
220 token4Pool.Put(pline)
221 var c rune
222 if n := len(*toks); n != 0 {
223 c = (*toks)[n-1].Rune
224 }
225 switch c {
226 case STRINGLITERAL, LONGSTRINGLITERAL:
227 // nop
228 default:
229 if len(*toks) != 0 {
230 p.in <- translationPhase5(ctx, toks)
231 toks = tokenPool.Get().(*[]Token)
232 *toks = (*toks)[:0]
233 }
234 }
235 }
236 if len(*toks) != 0 {
237 p.in <- translationPhase5(ctx, toks)
238 }
239 }()
240
241 tu := p.translationUnit()
242 if p.errored { // Must drain
243 go func() {
244 for range p.in {
245 }
246 }()
247 }
248
249 if err := ctx.Err(); err != nil {
250 return nil, err
251 }
252
253 if p.errored && !ctx.cfg.ignoreErrors {
254 return nil, fmt.Errorf("%v: syntax error", p.tok.Position())
255 }
256
257 if p.scopes != 0 {
258 panic(internalErrorf("invalid scope nesting but no error reported"))
259 }
260
261 ts := sep
262 if len(ssep) != 0 {
263 ts = dict.id(ssep)
264 }
265 return &AST{
266 Macros: cpp.macros,
267 Scope: p.fileScope,
268 TLD: map[*Declarator]struct{}{},
269 TrailingSeperator: ts,
270 TranslationUnit: tu,
271 cfg: ctx.cfg,
272 cpp: cpp,
273 }, nil
274}
275
276func translationPhase5(ctx *context, toks *[]Token) *[]Token {
277 // [0], 5.1.1.2, 5
278 //
279 // Each source character set member and escape sequence in character
280 // constants and string literals is converted to the corresponding
281 // member of the execution character set; if there is no corresponding
282 // member, it is converted to an implementation- defined member other
283 // than the null (wide) character.
284 for i, tok := range *toks {
285 var cpt cppToken
286 switch tok.Rune {
287 case STRINGLITERAL, LONGSTRINGLITERAL:
288 cpt.char = tok.Rune
289 cpt.value = tok.Value
290 cpt.src = tok.Src
291 cpt.file = tok.file
292 cpt.pos = tok.pos
293 (*toks)[i].Value = dict.sid(stringConst(ctx, cpt))
294 case CHARCONST, LONGCHARCONST:
295 var cpt cppToken
296 cpt.char = tok.Rune
297 cpt.value = tok.Value
298 cpt.src = tok.Src
299 cpt.file = tok.file
300 cpt.pos = tok.pos
301 switch r := charConst(ctx, cpt); {
302 case r <= 255:
303 (*toks)[i].Value = dict.sid(string(r))
304 default:
305 switch cpt.char {
306 case CHARCONST:
307 ctx.err(tok.Position(), "invalid character constant: %s", tok.Value)
308 default:
309 (*toks)[i].Value = dict.sid(string(r))
310 }
311 }
312 }
313 }
314 return toks
315}
316
317// Preprocess preprocesses a translation unit and outputs the result to w.
318//
319// Please see Parse for the documentation of the other parameters.
320func Preprocess(cfg *Config, includePaths, sysIncludePaths []string, sources []Source, w io.Writer) error {
321 ctx := newContext(cfg)
322 if debugWorkingDir || ctx.cfg.DebugWorkingDir {
323 switch wd, err := os.Getwd(); err {
324 case nil:
325 fmt.Fprintf(os.Stderr, "OS working dir: %s\n", wd)
326 default:
327 fmt.Fprintf(os.Stderr, "OS working dir: error %s\n", err)
328 }
329 fmt.Fprintf(os.Stderr, "Config.WorkingDir: %s\n", ctx.cfg.WorkingDir)
330 }
331 if debugIncludePaths || ctx.cfg.DebugIncludePaths {
332 fmt.Fprintf(os.Stderr, "include paths: %v\n", includePaths)
333 fmt.Fprintf(os.Stderr, "system include paths: %v\n", sysIncludePaths)
334 }
335 ctx.includePaths = includePaths
336 ctx.sysIncludePaths = sysIncludePaths
337 var in []source
338 for _, v := range sources {
339 ts, err := cache.get(ctx, v)
340 if err != nil {
341 return err
342 }
343
344 in = append(in, ts)
345 }
346
347 var sep StringID
348 cpp := newCPP(ctx)
349 toks := tokenPool.Get().(*[]Token)
350 *toks = (*toks)[:0]
351 for pline := range cpp.translationPhase4(in) {
352 line := *pline
353 for _, tok := range line {
354 switch tok.char {
355 case ' ', '\n':
356 if ctx.cfg.PreserveOnlyLastNonBlankSeparator {
357 if strings.TrimSpace(tok.value.String()) != "" {
358 sep = tok.value
359 }
360 break
361 }
362
363 switch {
364 case sep != 0:
365 sep = dict.sid(sep.String() + tok.String())
366 default:
367 sep = tok.value
368 }
369 default:
370 var t Token
371 t.Rune = tok.char
372 t.Sep = sep
373 t.Value = tok.value
374 t.Src = tok.src
375 t.file = tok.file
376 t.pos = tok.pos
377 *toks = append(*toks, t)
378 sep = 0
379 }
380 }
381 token4Pool.Put(pline)
382 var c rune
383 if n := len(*toks); n != 0 {
384 c = (*toks)[n-1].Rune
385 }
386 switch c {
387 case STRINGLITERAL, LONGSTRINGLITERAL:
388 // nop
389 default:
390 if len(*toks) != 0 {
391 for _, v := range *translationPhase5(ctx, toks) {
392 if err := wTok(w, v); err != nil {
393 return err
394 }
395 }
396 toks = tokenPool.Get().(*[]Token)
397 *toks = (*toks)[:0]
398 }
399 }
400 }
401 if len(*toks) != 0 {
402 for _, v := range *translationPhase5(ctx, toks) {
403 if err := wTok(w, v); err != nil {
404 return err
405 }
406 }
407 }
408 if _, err := fmt.Fprintln(w); err != nil {
409 return err
410 }
411 return ctx.Err()
412}
413
414func wTok(w io.Writer, tok Token) (err error) {
415 switch tok.Rune {
416 case STRINGLITERAL, LONGSTRINGLITERAL:
417 _, err = fmt.Fprintf(w, `%s"%s"`, tok.Sep, cQuotedString(tok.String(), true))
418 case CHARCONST, LONGCHARCONST:
419 _, err = fmt.Fprintf(w, `%s'%s'`, tok.Sep, cQuotedString(tok.String(), false))
420 default:
421 _, err = fmt.Fprintf(w, "%s%s", tok.Sep, tok)
422 }
423 return err
424}
425
426func cQuotedString(s string, isString bool) []byte {
427 var b []byte
428 for i := 0; i < len(s); i++ {
429 c := s[i]
430 switch c {
431 case '\b':
432 b = append(b, '\\', 'b')
433 continue
434 case '\f':
435 b = append(b, '\\', 'f')
436 continue
437 case '\n':
438 b = append(b, '\\', 'n')
439 continue
440 case '\r':
441 b = append(b, '\\', 'r')
442 continue
443 case '\t':
444 b = append(b, '\\', 't')
445 continue
446 case '\\':
447 b = append(b, '\\', '\\')
448 continue
449 case '"':
450 switch {
451 case isString:
452 b = append(b, '\\', '"')
453 default:
454 b = append(b, '"')
455 }
456 continue
457 case '\'':
458 switch {
459 case isString:
460 b = append(b, '\'')
461 default:
462 b = append(b, '\\', '\'')
463 }
464 continue
465 }
466
467 switch {
468 case c < ' ' || c >= 0x7f:
469 b = append(b, '\\', octal(c>>6), octal(c>>3), octal(c))
470 default:
471 b = append(b, c)
472 }
473 }
474 return b
475}
476
477func octal(b byte) byte { return '0' + b&7 }
478
479var trcSource = Source{"<builtin-trc>", `
480extern void *stderr;
481int fflush(void *stream);
482int fprintf(void *stream, const char *format, ...);
483`, false}
484
485// Translate parses and typechecks a translation unit and returns an *AST or
486// error, if any.
487//
488// Please see Parse for the documentation of the parameters.
489func Translate(cfg *Config, includePaths, sysIncludePaths []string, sources []Source) (*AST, error) {
490 if cfg.InjectTracingCode {
491 for i, v := range sources {
492 if filepath.Ext(v.Name) == ".c" {
493 sources = append(append(append([]Source(nil), sources[:i]...), trcSource), sources[i:]...)
494 }
495 }
496 }
497 return translate(newContext(cfg), includePaths, sysIncludePaths, sources)
498}
499
500func translate(ctx *context, includePaths, sysIncludePaths []string, sources []Source) (*AST, error) {
501 ast, err := parse(ctx, includePaths, sysIncludePaths, sources)
502 if err != nil {
503 return nil, err
504 }
505
506 if ctx, err = ast.typecheck(); err != nil {
507 return nil, err
508 }
509
510 ast.PtrdiffType = ptrdiffT(ctx, ast.Scope, Token{})
511 ast.SizeType = sizeT(ctx, ast.Scope, Token{})
512 ast.WideCharType = wcharT(ctx, ast.Scope, Token{})
513 return ast, nil
514}
515
516// Typecheck determines types of objects and expressions and verifies types are
517// valid in the context they are used.
518func (n *AST) Typecheck() error {
519 _, err := n.typecheck()
520 return err
521}
522
523func (n *AST) typecheck() (*context, error) {
524 ctx := newContext(n.cfg)
525 if err := ctx.cfg.ABI.sanityCheck(ctx, int(ctx.intMaxWidth), n.Scope); err != nil {
526 return nil, err
527 }
528
529 ctx.intBits = int(ctx.cfg.ABI.Types[Int].Size) * 8
530 ctx.ast = n
531 n.TranslationUnit.check(ctx)
532 n.Structs = ctx.structs
533 var a []int
534 for k := range n.Scope {
535 a = append(a, int(k))
536 }
537 sort.Ints(a)
538 for _, v := range a {
539 nm := StringID(v)
540 defs := n.Scope[nm]
541 var r, w int
542 for _, v := range defs {
543 switch x := v.(type) {
544 case *Declarator:
545 r += x.Read
546 w += x.Write
547 }
548 }
549 for _, v := range defs {
550 switch x := v.(type) {
551 case *Declarator:
552 x.Read = r
553 x.Write = w
554 }
555 }
556 var pruned *Declarator
557 for _, v := range defs {
558 switch x := v.(type) {
559 case *Declarator:
560 //TODO check compatible types
561 switch {
562 case x.IsExtern() && !x.fnDef:
563 // nop
564 case pruned == nil:
565 pruned = x
566 case pruned.hasInitializer && x.hasInitializer:
567 ctx.errNode(x, "multiple initializers for the same symbol")
568 continue
569 case pruned.fnDef && x.fnDef:
570 ctx.errNode(x, "multiple function definitions")
571 continue
572 case x.hasInitializer || x.fnDef:
573 pruned = x
574 }
575 }
576 }
577 if pruned == nil {
578 continue
579 }
580
581 n.TLD[pruned] = struct{}{}
582 }
583 n.Enums = ctx.enums
584 n.StructTypes = ctx.structTypes
585 return ctx, ctx.Err()
586}
587
588func (n *AlignmentSpecifier) align() int {
589 switch n.Case {
590 case AlignmentSpecifierAlignasType: // "_Alignas" '(' TypeName ')'
591 return n.TypeName.Type().Align()
592 case AlignmentSpecifierAlignasExpr: // "_Alignas" '(' ConstantExpression ')'
593 return n.ConstantExpression.Operand.Type().Align()
594 default:
595 panic(internalError())
596 }
597}
598
599// Closure reports the variables closed over by a nested function (case
600// BlockItemFuncDef).
601func (n *BlockItem) Closure() map[StringID]struct{} { return n.closure }
602
603// FunctionDefinition returns the nested function (case BlockItemFuncDef).
604func (n *BlockItem) FunctionDefinition() *FunctionDefinition { return n.fn }
605
606func (n *Declarator) IsStatic() bool { return n.td != nil && n.td.static() }
607
608// IsImplicit reports whether n was not declared nor defined, only inferred.
609func (n *Declarator) IsImplicit() bool { return n.implicit }
610
611func (n *Declarator) isVisible(at int32) bool { return at == 0 || n.DirectDeclarator.ends() < at }
612
613func (n *Declarator) setLHS(lhs *Declarator) {
614 if n == nil {
615 return
616 }
617
618 if n.lhs == nil {
619 n.lhs = map[*Declarator]struct{}{}
620 }
621 n.lhs[lhs] = struct{}{}
622}
623
624// LHS reports which declarators n is used in assignment RHS or which function
625// declarators n is used in a function argument. To collect this information,
626// TrackAssignments in Config must be set during type checking.
627// The returned map may contain a nil key. That means that n is assigned to a
628// declarator not known at typechecking time.
629func (n *Declarator) LHS() map[*Declarator]struct{} { return n.lhs }
630
631// Called reports whether n is involved in expr in expr(callArgs).
632func (n *Declarator) Called() bool { return n.called }
633
634// FunctionDefinition returns the function definition associated with n, if any.
635func (n *Declarator) FunctionDefinition() *FunctionDefinition {
636 return n.funcDefinition
637}
638
639// NameTok returns n's declaring name token.
640func (n *Declarator) NameTok() (r Token) {
641 if n == nil || n.DirectDeclarator == nil {
642 return r
643 }
644
645 return n.DirectDeclarator.NameTok()
646}
647
648// LexicalScope returns the lexical scope of n.
649func (n *Declarator) LexicalScope() Scope { return n.DirectDeclarator.lexicalScope }
650
651// Name returns n's declared name.
652func (n *Declarator) Name() StringID {
653 if n == nil || n.DirectDeclarator == nil {
654 return 0
655 }
656
657 return n.DirectDeclarator.Name()
658}
659
660// ParamScope returns the scope in which n's function parameters are declared
661// if the underlying type of n is a function or nil otherwise. If n is part of
662// a function definition the scope is the same as the scope of the function
663// body.
664func (n *Declarator) ParamScope() Scope {
665 if n == nil {
666 return nil
667 }
668
669 return n.DirectDeclarator.ParamScope()
670}
671
672// Type returns the type of n.
673func (n *Declarator) Type() Type { return n.typ }
674
675// IsExtern reports whether n was declared with storage class specifier 'extern'.
676func (n *Declarator) IsExtern() bool { return n.td != nil && n.td.extern() }
677
678func (n *DeclarationSpecifiers) auto() bool { return n != nil && n.class&fAuto != 0 }
679func (n *DeclarationSpecifiers) extern() bool { return n != nil && n.class&fExtern != 0 }
680func (n *DeclarationSpecifiers) register() bool { return n != nil && n.class&fRegister != 0 }
681func (n *DeclarationSpecifiers) static() bool { return n != nil && n.class&fStatic != 0 }
682func (n *DeclarationSpecifiers) threadLocal() bool { return n != nil && n.class&fThreadLocal != 0 }
683func (n *DeclarationSpecifiers) typedef() bool { return n != nil && n.class&fTypedef != 0 }
684
685func (n *DirectAbstractDeclarator) TypeQualifier() Type { return n.typeQualifiers }
686
687func (n *DirectDeclarator) ends() int32 {
688 switch n.Case {
689 case DirectDeclaratorIdent: // IDENTIFIER
690 return n.Token.seq
691 case DirectDeclaratorDecl: // '(' Declarator ')'
692 return n.Token2.seq
693 case DirectDeclaratorArr: // DirectDeclarator '[' TypeQualifierList AssignmentExpression ']'
694 return n.Token2.seq
695 case DirectDeclaratorStaticArr: // DirectDeclarator '[' "static" TypeQualifierList AssignmentExpression ']'
696 return n.Token3.seq
697 case DirectDeclaratorArrStatic: // DirectDeclarator '[' TypeQualifierList "static" AssignmentExpression ']'
698 return n.Token3.seq
699 case DirectDeclaratorStar: // DirectDeclarator '[' TypeQualifierList '*' ']'
700 return n.Token3.seq
701 case DirectDeclaratorFuncParam: // DirectDeclarator '(' ParameterTypeList ')'
702 return n.Token2.seq
703 case DirectDeclaratorFuncIdent: // DirectDeclarator '(' IdentifierList ')'
704 return n.Token2.seq
705 default:
706 panic(internalError())
707 }
708}
709
710func (n *DirectDeclarator) TypeQualifier() Type { return n.typeQualifiers }
711
712// NameTok returns n's declarin name token.
713func (n *DirectDeclarator) NameTok() (r Token) {
714 for {
715 if n == nil {
716 return r
717 }
718
719 switch n.Case {
720 case DirectDeclaratorIdent: // IDENTIFIER
721 return n.Token
722 case DirectDeclaratorDecl: // '(' Declarator ')'
723 return n.Declarator.NameTok()
724 default:
725 n = n.DirectDeclarator
726 }
727 }
728}
729
730// Name returns n's declared name.
731func (n *DirectDeclarator) Name() StringID {
732 for {
733 if n == nil {
734 return 0
735 }
736
737 switch n.Case {
738 case DirectDeclaratorIdent: // IDENTIFIER
739 return n.Token.Value
740 case DirectDeclaratorDecl: // '(' Declarator ')'
741 return n.Declarator.Name()
742 default:
743 n = n.DirectDeclarator
744 }
745 }
746}
747
748// ParamScope returns the innermost scope in which function parameters are
749// declared for Case DirectDeclaratorFuncParam or DirectDeclaratorFuncIdent or
750// nil otherwise.
751func (n *DirectDeclarator) ParamScope() Scope {
752 if n == nil {
753 return nil
754 }
755
756 switch n.Case {
757 case DirectDeclaratorIdent: // IDENTIFIER
758 return nil
759 case DirectDeclaratorDecl: // '(' Declarator ')'
760 return n.Declarator.ParamScope()
761 case DirectDeclaratorArr: // DirectDeclarator '[' TypeQualifierList AssignmentExpression ']'
762 return n.DirectDeclarator.ParamScope()
763 case DirectDeclaratorStaticArr: // DirectDeclarator '[' "static" TypeQualifierList AssignmentExpression ']'
764 return n.DirectDeclarator.ParamScope()
765 case DirectDeclaratorArrStatic: // DirectDeclarator '[' TypeQualifierList "static" AssignmentExpression ']'
766 return n.DirectDeclarator.ParamScope()
767 case DirectDeclaratorStar: // DirectDeclarator '[' TypeQualifierList '*' ']'
768 return n.DirectDeclarator.ParamScope()
769 case DirectDeclaratorFuncParam: // DirectDeclarator '(' ParameterTypeList ')'
770 if s := n.DirectDeclarator.ParamScope(); s != nil {
771 return s
772 }
773
774 return n.paramScope
775 case DirectDeclaratorFuncIdent: // DirectDeclarator '(' IdentifierList ')'
776 if s := n.DirectDeclarator.ParamScope(); s != nil {
777 return s
778 }
779
780 return n.paramScope
781 default:
782 panic(internalError())
783 }
784}
785
786func (n *Enumerator) isVisible(at int32) bool { return n.Token.seq < at }
787
788func (n *EnumSpecifier) Type() Type { return n.typ }
789
790// Promote returns the type the operands of the binary operation are promoted to.
791func (n *EqualityExpression) Promote() Type { return n.promote }
792
793// Promote returns the type the operands of the binary operation are promoted to.
794func (n *AdditiveExpression) Promote() Type { return n.promote }
795
796// Promote returns the type the operands of the binary operation are promoted to.
797func (n *MultiplicativeExpression) Promote() Type { return n.promote }
798
799// Promote returns the type the operands of the binary operation are promoted to.
800func (n *InclusiveOrExpression) Promote() Type { return n.promote }
801
802// Promote returns the type the operands of the binary operation are promoted to.
803func (n *ExclusiveOrExpression) Promote() Type { return n.promote }
804
805// Promote returns the type the operands of the binary operation are promoted to.
806func (n *AndExpression) Promote() Type { return n.promote }
807
808func (n *InitDeclarator) Value() *InitializerValue { return n.initializer }
809
810// FirstDesignatorField returns the first field a designator of an union type
811// denotes, if any.
812func (n *Initializer) FirstDesignatorField() Field { return n.field0 }
813
814// TrailingComma returns the comma token following n, if any.
815func (n *Initializer) TrailingComma() *Token { return n.trailingComma }
816
817// IsConst reports whether n is constant.
818func (n *Initializer) IsConst() bool { return n == nil || n.isConst }
819
820// IsZero reports whether n is a zero value.
821func (n *Initializer) IsZero() bool { return n == nil || n.isZero }
822
823// List returns n as a flattened list of all items that are case
824// InitializerExpr.
825func (n *Initializer) List() []*Initializer { return n.list }
826
827// Parent returns the parent of n, if any.
828func (n *Initializer) Parent() *Initializer { return n.parent }
829
830// Type returns the type this initializer initializes.
831func (n *Initializer) Type() Type { return n.typ }
832
833// IsConst reports whether n is constant.
834func (n *InitializerList) IsConst() bool { return n == nil || n.isConst }
835
836// IsZero reports whether n is a zero value.
837func (n *InitializerList) IsZero() bool { return n == nil || n.isZero }
838
839// List returns n as a flattened list of all items that are case
840// InitializerExpr.
841func (n *InitializerList) List() []*Initializer {
842 if n == nil {
843 return nil
844 }
845
846 return n.list
847}
848
849// IsEmpty reprts whether n is an empty list.
850func (n *InitializerList) IsEmpty() bool { return len(n.list) == 0 }
851
852// LexicalScope returns the lexical scope of n.
853func (n *JumpStatement) LexicalScope() Scope { return n.lexicalScope }
854
855// LexicalScope returns the lexical scope of n.
856func (n *LabeledStatement) LexicalScope() Scope { return n.lexicalScope }
857
858func (n *ParameterDeclaration) Type() Type { return n.typ }
859
860func (n *Pointer) TypeQualifier() Type { return n.typeQualifiers }
861
862// ResolvedIn reports which scope the identifier of cases
863// PrimaryExpressionIdent, PrimaryExpressionEnum were resolved in, if any.
864func (n *PrimaryExpression) ResolvedIn() Scope { return n.resolvedIn }
865
866// ResolvedTo reports which Node the identifier of cases
867// PrimaryExpressionIdent, PrimaryExpressionEnum resolved to, if any.
868func (n *PrimaryExpression) ResolvedTo() Node { return n.resolvedTo }
869
870// Promote returns the type the operands of the binary operation are promoted to.
871func (n *RelationalExpression) Promote() Type { return n.promote }
872
873// Cases returns the cases a switch statement consist of, in source order.
874func (n *SelectionStatement) Cases() []*LabeledStatement { return n.cases }
875
876// Promote returns the type the shift count operand is promoted to.
877func (n *ShiftExpression) Promote() Type { return n.promote }
878
879func (n *StructOrUnionSpecifier) Type() Type { return n.typ }
880
881// Promote returns the type the type the switch expression is promoted to.
882func (n *SelectionStatement) Promote() Type { return n.promote }
883
884// Type returns the type of n.
885func (n *TypeName) Type() Type { return n.typ }
886
887// // LexicalScope returns the lexical scope of n.
888// func (n *AttributeValue) LexicalScope() Scope { return n.lexicalScope }
889
890// // Scope returns n's scope.
891// func (n *CompoundStatement) Scope() Scope { return n.scope }
892
893// // LexicalScope returns the lexical scope of n.
894// func (n *Designator) LexicalScope() Scope { return n.lexicalScope }
895
896// // LexicalScope returns the lexical scope of n.
897// func (n *DirectDeclarator) LexicalScope() Scope { return n.lexicalScope }
898
899// LexicalScope returns the lexical scope of n.
900func (n *EnumSpecifier) LexicalScope() Scope { return n.lexicalScope }
901
902// // LexicalScope returns the lexical scope of n.
903// func (n *IdentifierList) LexicalScope() Scope { return n.lexicalScope }
904
905// // LexicalScope returns the lexical scope of n.
906// func (n *PrimaryExpression) LexicalScope() Scope { return n.lexicalScope }
907
908// // LexicalScope returns the lexical scope of n.
909// func (n *StructOrUnionSpecifier) LexicalScope() Scope { return n.lexicalScope }
910
911// // ResolvedIn reports which scope the identifier of case
912// // TypeSpecifierTypedefName was resolved in, if any.
913// func (n *TypeSpecifier) ResolvedIn() Scope { return n.resolvedIn }
914
915func (n *TypeSpecifier) list() (r []*TypeSpecifier) {
916 switch n.Case {
917 case TypeSpecifierAtomic:
918 return n.AtomicTypeSpecifier.list
919 default:
920 return []*TypeSpecifier{n}
921 }
922}
923
924// // LexicalScope returns the lexical scope of n.
925// func (n *UnaryExpression) LexicalScope() Scope { return n.lexicalScope }
926
927func (n *UnaryExpression) Declarator() *Declarator {
928 switch n.Case {
929 case UnaryExpressionPostfix: // PostfixExpression
930 return n.PostfixExpression.Declarator()
931 default:
932 return nil
933 }
934}
935
936func (n *PostfixExpression) Declarator() *Declarator {
937 switch n.Case {
938 case PostfixExpressionPrimary: // PrimaryExpression
939 return n.PrimaryExpression.Declarator()
940 default:
941 return nil
942 }
943}
944
945func (n *PrimaryExpression) Declarator() *Declarator {
946 switch n.Case {
947 case PrimaryExpressionIdent: // IDENTIFIER
948 if n.Operand != nil {
949 return n.Operand.Declarator()
950 }
951
952 return nil
953 case PrimaryExpressionExpr: // '(' Expression ')'
954 return n.Expression.Declarator()
955 default:
956 return nil
957 }
958}
959
960func (n *Expression) Declarator() *Declarator {
961 switch n.Case {
962 case ExpressionAssign: // AssignmentExpression
963 return n.AssignmentExpression.Declarator()
964 default:
965 return nil
966 }
967}
968
969func (n *AssignmentExpression) Declarator() *Declarator {
970 switch n.Case {
971 case AssignmentExpressionCond: // ConditionalExpression
972 return n.ConditionalExpression.Declarator()
973 default:
974 return nil
975 }
976}
977
978func (n *ConditionalExpression) Declarator() *Declarator {
979 switch n.Case {
980 case ConditionalExpressionLOr: // LogicalOrExpression
981 return n.LogicalOrExpression.Declarator()
982 default:
983 return nil
984 }
985}
986
987func (n *LogicalOrExpression) Declarator() *Declarator {
988 switch n.Case {
989 case LogicalOrExpressionLAnd: // LogicalAndExpression
990 return n.LogicalAndExpression.Declarator()
991 default:
992 return nil
993 }
994}
995
996func (n *LogicalAndExpression) Declarator() *Declarator {
997 switch n.Case {
998 case LogicalAndExpressionOr: // InclusiveOrExpression
999 return n.InclusiveOrExpression.Declarator()
1000 default:
1001 return nil
1002 }
1003}
1004
1005func (n *InclusiveOrExpression) Declarator() *Declarator {
1006 switch n.Case {
1007 case InclusiveOrExpressionXor: // ExclusiveOrExpression
1008 return n.ExclusiveOrExpression.Declarator()
1009 default:
1010 return nil
1011 }
1012}
1013
1014func (n *ExclusiveOrExpression) Declarator() *Declarator {
1015 switch n.Case {
1016 case ExclusiveOrExpressionAnd: // AndExpression
1017 return n.AndExpression.Declarator()
1018 default:
1019 return nil
1020 }
1021}
1022
1023func (n *AndExpression) Declarator() *Declarator {
1024 switch n.Case {
1025 case AndExpressionEq: // EqualityExpression
1026 return n.EqualityExpression.Declarator()
1027 default:
1028 return nil
1029 }
1030}
1031
1032func (n *EqualityExpression) Declarator() *Declarator {
1033 switch n.Case {
1034 case EqualityExpressionRel: // RelationalExpression
1035 return n.RelationalExpression.Declarator()
1036 default:
1037 return nil
1038 }
1039}
1040
1041func (n *RelationalExpression) Declarator() *Declarator {
1042 switch n.Case {
1043 case RelationalExpressionShift: // ShiftExpression
1044 return n.ShiftExpression.Declarator()
1045 default:
1046 return nil
1047 }
1048}
1049
1050func (n *ShiftExpression) Declarator() *Declarator {
1051 switch n.Case {
1052 case ShiftExpressionAdd: // AdditiveExpression
1053 return n.AdditiveExpression.Declarator()
1054 default:
1055 return nil
1056 }
1057}
1058
1059func (n *AdditiveExpression) Declarator() *Declarator {
1060 switch n.Case {
1061 case AdditiveExpressionMul: // MultiplicativeExpression
1062 return n.MultiplicativeExpression.Declarator()
1063 default:
1064 return nil
1065 }
1066}
1067
1068func (n *MultiplicativeExpression) Declarator() *Declarator {
1069 switch n.Case {
1070 case MultiplicativeExpressionCast: // CastExpression
1071 return n.CastExpression.Declarator()
1072 default:
1073 return nil
1074 }
1075}
1076
1077func (n *CastExpression) Declarator() *Declarator {
1078 switch n.Case {
1079 case CastExpressionUnary: // UnaryExpression
1080 return n.UnaryExpression.Declarator()
1081 default:
1082 return nil
1083 }
1084}
1085
1086// Has reports whether n has any of attributes in key.
1087func (n *AttributeSpecifier) Has(key ...StringID) (*ExpressionList, bool) {
1088 if n == nil {
1089 return nil, false
1090 }
1091
1092 for list := n.AttributeValueList; list != nil; list = list.AttributeValueList {
1093 av := list.AttributeValue
1094 for _, k := range key {
1095 if av.Token.Value == k {
1096 switch av.Case {
1097 case AttributeValueIdent: // IDENTIFIER
1098 return nil, true
1099 case AttributeValueExpr: // IDENTIFIER '(' ExpressionList ')'
1100 return av.ExpressionList, true
1101 }
1102 }
1103 }
1104 }
1105 return nil, false
1106}
1107
1108// Has reports whether n has any of attributes in key.
1109func (n *AttributeSpecifierList) Has(key ...StringID) (*ExpressionList, bool) {
1110 for ; n != nil; n = n.AttributeSpecifierList {
1111 if exprList, ok := n.AttributeSpecifier.Has(key...); ok {
1112 return exprList, ok
1113 }
1114 }
1115 return nil, false
1116}
1117
1118// Parent returns the CompoundStatement that contains n, if any.
1119func (n *CompoundStatement) Parent() *CompoundStatement { return n.parent }
1120
1121// IsJumpTarget returns whether n or any of its children contain a named
1122// labeled statement.
1123func (n *CompoundStatement) IsJumpTarget() bool { return n.isJumpTarget }
1124
1125func (n *CompoundStatement) hasLabel() {
1126 for ; n != nil; n = n.parent {
1127 n.isJumpTarget = true
1128 }
1129}
1130
1131// Declarations returns the list of declarations in n.
1132func (n *CompoundStatement) Declarations() []*Declaration { return n.declarations }
1133
1134// Children returns the list of n's children.
1135func (n *CompoundStatement) Children() []*CompoundStatement { return n.children }
1136
1137// CompoundStatements returns the list of compound statements in n.
1138func (n *FunctionDefinition) CompoundStatements() []*CompoundStatement { return n.compoundStatements }
1139
1140// CompoundStatement returns the block containing n.
1141func (n *LabeledStatement) CompoundStatement() *CompoundStatement { return n.block }
1142
1143// LabeledStatements returns labeled statements of n.
1144func (n *CompoundStatement) LabeledStatements() []*LabeledStatement { return n.labeledStmts }
1145
1146// HasInitializer reports whether d has an initializator.
1147func (n *Declarator) HasInitializer() bool { return n.hasInitializer }
1148
1149// Context reports the statement, if any, a break or continue belongs to. Valid
1150// only after typecheck and for n.Case == JumpStatementBreak or
1151// JumpStatementContinue.
1152func (n *JumpStatement) Context() Node { return n.context }
1153
1154// IsFunctionPrototype reports whether n is a function prototype.
1155func (n *Declarator) IsFunctionPrototype() bool {
1156 return n != nil && n.Type() != nil && n.Type().Kind() == Function && !n.fnDef && !n.IsParameter
1157}
1158
1159// DeclarationSpecifiers returns the declaration specifiers associated with n or nil.
1160func (n *Declarator) DeclarationSpecifiers() *DeclarationSpecifiers {
1161 if x, ok := n.td.(*DeclarationSpecifiers); ok {
1162 return x
1163 }
1164
1165 return nil
1166}
1167
1168// SpecifierQualifierList returns the specifier qualifer list associated with n or nil.
1169func (n *Declarator) SpecifierQualifierList() *SpecifierQualifierList {
1170 if x, ok := n.td.(*SpecifierQualifierList); ok {
1171 return x
1172 }
1173
1174 return nil
1175}
1176
1177// TypeQualifier returns the type qualifiers associated with n or nil.
1178func (n *Declarator) TypeQualifiers() *TypeQualifiers {
1179 if x, ok := n.td.(*TypeQualifiers); ok {
1180 return x
1181 }
1182
1183 return nil
1184}
1185
1186// StructDeclaration returns the struct declaration associated with n.
1187func (n *StructDeclarator) StructDeclaration() *StructDeclaration { return n.decl }
Note: See TracBrowser for help on using the repository browser.