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 |
|
---|
5 | package cc // import "modernc.org/cc/v3"
|
---|
6 |
|
---|
7 | import (
|
---|
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.
|
---|
18 | type 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.
|
---|
26 | func (n *AssignmentExpression) Promote() Type { return n.promote }
|
---|
27 |
|
---|
28 | type StructInfo struct {
|
---|
29 | Size uintptr
|
---|
30 |
|
---|
31 | Align int
|
---|
32 | }
|
---|
33 |
|
---|
34 | // AST represents a translation unit and its related data.
|
---|
35 | type 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.
|
---|
57 | func (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.
|
---|
128 | func Parse(cfg *Config, includePaths, sysIncludePaths []string, sources []Source) (*AST, error) {
|
---|
129 | return parse(newContext(cfg), includePaths, sysIncludePaths, sources)
|
---|
130 | }
|
---|
131 |
|
---|
132 | func 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 |
|
---|
276 | func 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.
|
---|
320 | func 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 |
|
---|
414 | func 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 |
|
---|
426 | func 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 |
|
---|
477 | func octal(b byte) byte { return '0' + b&7 }
|
---|
478 |
|
---|
479 | var trcSource = Source{"<builtin-trc>", `
|
---|
480 | extern void *stderr;
|
---|
481 | int fflush(void *stream);
|
---|
482 | int 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.
|
---|
489 | func 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 |
|
---|
500 | func 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.
|
---|
518 | func (n *AST) Typecheck() error {
|
---|
519 | _, err := n.typecheck()
|
---|
520 | return err
|
---|
521 | }
|
---|
522 |
|
---|
523 | func (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 |
|
---|
588 | func (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).
|
---|
601 | func (n *BlockItem) Closure() map[StringID]struct{} { return n.closure }
|
---|
602 |
|
---|
603 | // FunctionDefinition returns the nested function (case BlockItemFuncDef).
|
---|
604 | func (n *BlockItem) FunctionDefinition() *FunctionDefinition { return n.fn }
|
---|
605 |
|
---|
606 | func (n *Declarator) IsStatic() bool { return n.td != nil && n.td.static() }
|
---|
607 |
|
---|
608 | // IsImplicit reports whether n was not declared nor defined, only inferred.
|
---|
609 | func (n *Declarator) IsImplicit() bool { return n.implicit }
|
---|
610 |
|
---|
611 | func (n *Declarator) isVisible(at int32) bool { return at == 0 || n.DirectDeclarator.ends() < at }
|
---|
612 |
|
---|
613 | func (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.
|
---|
629 | func (n *Declarator) LHS() map[*Declarator]struct{} { return n.lhs }
|
---|
630 |
|
---|
631 | // Called reports whether n is involved in expr in expr(callArgs).
|
---|
632 | func (n *Declarator) Called() bool { return n.called }
|
---|
633 |
|
---|
634 | // FunctionDefinition returns the function definition associated with n, if any.
|
---|
635 | func (n *Declarator) FunctionDefinition() *FunctionDefinition {
|
---|
636 | return n.funcDefinition
|
---|
637 | }
|
---|
638 |
|
---|
639 | // NameTok returns n's declaring name token.
|
---|
640 | func (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.
|
---|
649 | func (n *Declarator) LexicalScope() Scope { return n.DirectDeclarator.lexicalScope }
|
---|
650 |
|
---|
651 | // Name returns n's declared name.
|
---|
652 | func (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.
|
---|
664 | func (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.
|
---|
673 | func (n *Declarator) Type() Type { return n.typ }
|
---|
674 |
|
---|
675 | // IsExtern reports whether n was declared with storage class specifier 'extern'.
|
---|
676 | func (n *Declarator) IsExtern() bool { return n.td != nil && n.td.extern() }
|
---|
677 |
|
---|
678 | func (n *DeclarationSpecifiers) auto() bool { return n != nil && n.class&fAuto != 0 }
|
---|
679 | func (n *DeclarationSpecifiers) extern() bool { return n != nil && n.class&fExtern != 0 }
|
---|
680 | func (n *DeclarationSpecifiers) register() bool { return n != nil && n.class&fRegister != 0 }
|
---|
681 | func (n *DeclarationSpecifiers) static() bool { return n != nil && n.class&fStatic != 0 }
|
---|
682 | func (n *DeclarationSpecifiers) threadLocal() bool { return n != nil && n.class&fThreadLocal != 0 }
|
---|
683 | func (n *DeclarationSpecifiers) typedef() bool { return n != nil && n.class&fTypedef != 0 }
|
---|
684 |
|
---|
685 | func (n *DirectAbstractDeclarator) TypeQualifier() Type { return n.typeQualifiers }
|
---|
686 |
|
---|
687 | func (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 |
|
---|
710 | func (n *DirectDeclarator) TypeQualifier() Type { return n.typeQualifiers }
|
---|
711 |
|
---|
712 | // NameTok returns n's declarin name token.
|
---|
713 | func (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.
|
---|
731 | func (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.
|
---|
751 | func (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 |
|
---|
786 | func (n *Enumerator) isVisible(at int32) bool { return n.Token.seq < at }
|
---|
787 |
|
---|
788 | func (n *EnumSpecifier) Type() Type { return n.typ }
|
---|
789 |
|
---|
790 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
791 | func (n *EqualityExpression) Promote() Type { return n.promote }
|
---|
792 |
|
---|
793 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
794 | func (n *AdditiveExpression) Promote() Type { return n.promote }
|
---|
795 |
|
---|
796 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
797 | func (n *MultiplicativeExpression) Promote() Type { return n.promote }
|
---|
798 |
|
---|
799 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
800 | func (n *InclusiveOrExpression) Promote() Type { return n.promote }
|
---|
801 |
|
---|
802 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
803 | func (n *ExclusiveOrExpression) Promote() Type { return n.promote }
|
---|
804 |
|
---|
805 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
806 | func (n *AndExpression) Promote() Type { return n.promote }
|
---|
807 |
|
---|
808 | func (n *InitDeclarator) Value() *InitializerValue { return n.initializer }
|
---|
809 |
|
---|
810 | // FirstDesignatorField returns the first field a designator of an union type
|
---|
811 | // denotes, if any.
|
---|
812 | func (n *Initializer) FirstDesignatorField() Field { return n.field0 }
|
---|
813 |
|
---|
814 | // TrailingComma returns the comma token following n, if any.
|
---|
815 | func (n *Initializer) TrailingComma() *Token { return n.trailingComma }
|
---|
816 |
|
---|
817 | // IsConst reports whether n is constant.
|
---|
818 | func (n *Initializer) IsConst() bool { return n == nil || n.isConst }
|
---|
819 |
|
---|
820 | // IsZero reports whether n is a zero value.
|
---|
821 | func (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.
|
---|
825 | func (n *Initializer) List() []*Initializer { return n.list }
|
---|
826 |
|
---|
827 | // Parent returns the parent of n, if any.
|
---|
828 | func (n *Initializer) Parent() *Initializer { return n.parent }
|
---|
829 |
|
---|
830 | // Type returns the type this initializer initializes.
|
---|
831 | func (n *Initializer) Type() Type { return n.typ }
|
---|
832 |
|
---|
833 | // IsConst reports whether n is constant.
|
---|
834 | func (n *InitializerList) IsConst() bool { return n == nil || n.isConst }
|
---|
835 |
|
---|
836 | // IsZero reports whether n is a zero value.
|
---|
837 | func (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.
|
---|
841 | func (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.
|
---|
850 | func (n *InitializerList) IsEmpty() bool { return len(n.list) == 0 }
|
---|
851 |
|
---|
852 | // LexicalScope returns the lexical scope of n.
|
---|
853 | func (n *JumpStatement) LexicalScope() Scope { return n.lexicalScope }
|
---|
854 |
|
---|
855 | // LexicalScope returns the lexical scope of n.
|
---|
856 | func (n *LabeledStatement) LexicalScope() Scope { return n.lexicalScope }
|
---|
857 |
|
---|
858 | func (n *ParameterDeclaration) Type() Type { return n.typ }
|
---|
859 |
|
---|
860 | func (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.
|
---|
864 | func (n *PrimaryExpression) ResolvedIn() Scope { return n.resolvedIn }
|
---|
865 |
|
---|
866 | // ResolvedTo reports which Node the identifier of cases
|
---|
867 | // PrimaryExpressionIdent, PrimaryExpressionEnum resolved to, if any.
|
---|
868 | func (n *PrimaryExpression) ResolvedTo() Node { return n.resolvedTo }
|
---|
869 |
|
---|
870 | // Promote returns the type the operands of the binary operation are promoted to.
|
---|
871 | func (n *RelationalExpression) Promote() Type { return n.promote }
|
---|
872 |
|
---|
873 | // Cases returns the cases a switch statement consist of, in source order.
|
---|
874 | func (n *SelectionStatement) Cases() []*LabeledStatement { return n.cases }
|
---|
875 |
|
---|
876 | // Promote returns the type the shift count operand is promoted to.
|
---|
877 | func (n *ShiftExpression) Promote() Type { return n.promote }
|
---|
878 |
|
---|
879 | func (n *StructOrUnionSpecifier) Type() Type { return n.typ }
|
---|
880 |
|
---|
881 | // Promote returns the type the type the switch expression is promoted to.
|
---|
882 | func (n *SelectionStatement) Promote() Type { return n.promote }
|
---|
883 |
|
---|
884 | // Type returns the type of n.
|
---|
885 | func (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.
|
---|
900 | func (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 |
|
---|
915 | func (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 |
|
---|
927 | func (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 |
|
---|
936 | func (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 |
|
---|
945 | func (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 |
|
---|
960 | func (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 |
|
---|
969 | func (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 |
|
---|
978 | func (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 |
|
---|
987 | func (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 |
|
---|
996 | func (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 |
|
---|
1005 | func (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 |
|
---|
1014 | func (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 |
|
---|
1023 | func (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 |
|
---|
1032 | func (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 |
|
---|
1041 | func (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 |
|
---|
1050 | func (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 |
|
---|
1059 | func (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 |
|
---|
1068 | func (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 |
|
---|
1077 | func (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.
|
---|
1087 | func (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.
|
---|
1109 | func (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.
|
---|
1119 | func (n *CompoundStatement) Parent() *CompoundStatement { return n.parent }
|
---|
1120 |
|
---|
1121 | // IsJumpTarget returns whether n or any of its children contain a named
|
---|
1122 | // labeled statement.
|
---|
1123 | func (n *CompoundStatement) IsJumpTarget() bool { return n.isJumpTarget }
|
---|
1124 |
|
---|
1125 | func (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.
|
---|
1132 | func (n *CompoundStatement) Declarations() []*Declaration { return n.declarations }
|
---|
1133 |
|
---|
1134 | // Children returns the list of n's children.
|
---|
1135 | func (n *CompoundStatement) Children() []*CompoundStatement { return n.children }
|
---|
1136 |
|
---|
1137 | // CompoundStatements returns the list of compound statements in n.
|
---|
1138 | func (n *FunctionDefinition) CompoundStatements() []*CompoundStatement { return n.compoundStatements }
|
---|
1139 |
|
---|
1140 | // CompoundStatement returns the block containing n.
|
---|
1141 | func (n *LabeledStatement) CompoundStatement() *CompoundStatement { return n.block }
|
---|
1142 |
|
---|
1143 | // LabeledStatements returns labeled statements of n.
|
---|
1144 | func (n *CompoundStatement) LabeledStatements() []*LabeledStatement { return n.labeledStmts }
|
---|
1145 |
|
---|
1146 | // HasInitializer reports whether d has an initializator.
|
---|
1147 | func (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.
|
---|
1152 | func (n *JumpStatement) Context() Node { return n.context }
|
---|
1153 |
|
---|
1154 | // IsFunctionPrototype reports whether n is a function prototype.
|
---|
1155 | func (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.
|
---|
1160 | func (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.
|
---|
1169 | func (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.
|
---|
1178 | func (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.
|
---|
1187 | func (n *StructDeclarator) StructDeclaration() *StructDeclaration { return n.decl }
|
---|