rubycc 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +56 -0
- data/LICENSE.txt +21 -0
- data/NOTICE +52 -0
- data/README.md +208 -0
- data/data/README.md +117 -0
- data/data/r10_corpus_scan.json +4082 -0
- data/data/r10_manual_classification.json +5342 -0
- data/data/r10_verification_m4a.json +1531 -0
- data/data/r10_verification_m4b.json +1818 -0
- data/data/r10_verification_m4c.json +1489 -0
- data/data/r10_verification_m4d.json +318 -0
- data/data/r10_verification_rbs.json +192 -0
- data/data/verified_gems.json +397 -0
- data/exe/rmake +16 -0
- data/exe/rubycc +9 -0
- data/exe/rubycc-ar +114 -0
- data/exe/rubycc-doctor +14 -0
- data/exe/rubycc-pkgconf +8 -0
- data/include/float.h +87 -0
- data/include/iso646.h +18 -0
- data/include/libc/alloca.h +18 -0
- data/include/libc/arpa/inet.h +61 -0
- data/include/libc/assert.h +43 -0
- data/include/libc/dirent.h +72 -0
- data/include/libc/dlfcn.h +58 -0
- data/include/libc/features.h +205 -0
- data/include/libc/glibc/aarch64/ctype.h +108 -0
- data/include/libc/glibc/aarch64/endian.h +54 -0
- data/include/libc/glibc/aarch64/errno.h +154 -0
- data/include/libc/glibc/aarch64/fcntl.h +144 -0
- data/include/libc/glibc/aarch64/inttypes.h +182 -0
- data/include/libc/glibc/aarch64/limits.h +63 -0
- data/include/libc/glibc/aarch64/pthread.h +131 -0
- data/include/libc/glibc/aarch64/setjmp.h +84 -0
- data/include/libc/glibc/aarch64/stdint.h +174 -0
- data/include/libc/glibc/aarch64/sys/epoll.h +88 -0
- data/include/libc/glibc/aarch64/sys/fcntl.h +19 -0
- data/include/libc/glibc/aarch64/sys/select.h +75 -0
- data/include/libc/glibc/aarch64/sys/stat.h +136 -0
- data/include/libc/glibc/aarch64/sys/syscall.h +167 -0
- data/include/libc/glibc/aarch64/sys/time.h +74 -0
- data/include/libc/glibc/aarch64/sys/types.h +127 -0
- data/include/libc/glibc/aarch64/time.h +113 -0
- data/include/libc/glibc/x86_64/ctype.h +108 -0
- data/include/libc/glibc/x86_64/endian.h +54 -0
- data/include/libc/glibc/x86_64/errno.h +154 -0
- data/include/libc/glibc/x86_64/fcntl.h +134 -0
- data/include/libc/glibc/x86_64/inttypes.h +182 -0
- data/include/libc/glibc/x86_64/limits.h +61 -0
- data/include/libc/glibc/x86_64/pthread.h +111 -0
- data/include/libc/glibc/x86_64/setjmp.h +82 -0
- data/include/libc/glibc/x86_64/stdint.h +163 -0
- data/include/libc/glibc/x86_64/sys/epoll.h +91 -0
- data/include/libc/glibc/x86_64/sys/fcntl.h +19 -0
- data/include/libc/glibc/x86_64/sys/select.h +75 -0
- data/include/libc/glibc/x86_64/sys/stat.h +130 -0
- data/include/libc/glibc/x86_64/sys/syscall.h +188 -0
- data/include/libc/glibc/x86_64/sys/time.h +74 -0
- data/include/libc/glibc/x86_64/sys/types.h +123 -0
- data/include/libc/glibc/x86_64/time.h +113 -0
- data/include/libc/grp.h +50 -0
- data/include/libc/langinfo.h +126 -0
- data/include/libc/link.h +18 -0
- data/include/libc/locale.h +83 -0
- data/include/libc/math.h +191 -0
- data/include/libc/netinet/in.h +126 -0
- data/include/libc/netinet/tcp.h +44 -0
- data/include/libc/poll.h +46 -0
- data/include/libc/pwd.h +58 -0
- data/include/libc/regex.h +53 -0
- data/include/libc/sched.h +35 -0
- data/include/libc/signal.h +204 -0
- data/include/libc/stdio.h +157 -0
- data/include/libc/stdlib.h +92 -0
- data/include/libc/string.h +74 -0
- data/include/libc/strings.h +25 -0
- data/include/libc/sys/cdefs.h +126 -0
- data/include/libc/sys/inotify.h +111 -0
- data/include/libc/sys/ioctl.h +36 -0
- data/include/libc/sys/mman.h +65 -0
- data/include/libc/sys/param.h +41 -0
- data/include/libc/sys/resource.h +109 -0
- data/include/libc/sys/socket.h +167 -0
- data/include/libc/sys/statfs.h +82 -0
- data/include/libc/sys/timerfd.h +55 -0
- data/include/libc/sys/uio.h +40 -0
- data/include/libc/sys/un.h +25 -0
- data/include/libc/sys/utsname.h +35 -0
- data/include/libc/sys/wait.h +135 -0
- data/include/libc/termios.h +179 -0
- data/include/libc/unistd.h +194 -0
- data/include/stdalign.h +16 -0
- data/include/stdarg.h +31 -0
- data/include/stdatomic.h +158 -0
- data/include/stdbool.h +15 -0
- data/include/stdckdint.h +28 -0
- data/include/stddef.h +60 -0
- data/include/stdnoreturn.h +18 -0
- data/include/x86intrin.h +16 -0
- data/lib/rubycc/backend/aarch64.rb +1724 -0
- data/lib/rubycc/backend/x86_64.rb +1369 -0
- data/lib/rubycc/compile_error.rb +36 -0
- data/lib/rubycc/compiler.rb +305 -0
- data/lib/rubycc/doctor/builder.rb +151 -0
- data/lib/rubycc/doctor/cli.rb +190 -0
- data/lib/rubycc/doctor/fetcher.rb +84 -0
- data/lib/rubycc/doctor/gemfile.rb +115 -0
- data/lib/rubycc/doctor/verified_gems.rb +114 -0
- data/lib/rubycc/doctor.rb +16 -0
- data/lib/rubycc/driver.rb +463 -0
- data/lib/rubycc/front/ast.rb +528 -0
- data/lib/rubycc/front/constant_evaluator.rb +631 -0
- data/lib/rubycc/front/initializer_resolver.rb +592 -0
- data/lib/rubycc/front/lexeme_reader.rb +460 -0
- data/lib/rubycc/front/lexer.rb +232 -0
- data/lib/rubycc/front/parser.rb +4122 -0
- data/lib/rubycc/front/token.rb +49 -0
- data/lib/rubycc/ir/call_convention.rb +486 -0
- data/lib/rubycc/ir/generator.rb +6036 -0
- data/lib/rubycc/ir/ir.rb +417 -0
- data/lib/rubycc/link/compat_runtime.rb +89 -0
- data/lib/rubycc/link/errors.rb +13 -0
- data/lib/rubycc/link/executable_linker.rb +405 -0
- data/lib/rubycc/link/library_resolver.rb +437 -0
- data/lib/rubycc/link/partial_linker.rb +546 -0
- data/lib/rubycc/link/shared_linker.rb +1732 -0
- data/lib/rubycc/mkmf_shim.rb +83 -0
- data/lib/rubycc/objfile/ar_archive.rb +437 -0
- data/lib/rubycc/objfile/elf_reader.rb +646 -0
- data/lib/rubycc/objfile/elf_writer.rb +891 -0
- data/lib/rubycc/objfile/relocatable_writer.rb +376 -0
- data/lib/rubycc/pkgconf/cli.rb +139 -0
- data/lib/rubycc/pkgconf/errors.rb +39 -0
- data/lib/rubycc/pkgconf/model.rb +28 -0
- data/lib/rubycc/pkgconf/parser.rb +109 -0
- data/lib/rubycc/pkgconf/pkgconf.rb +15 -0
- data/lib/rubycc/pkgconf/resolver.rb +70 -0
- data/lib/rubycc/pkgconf/search_path.rb +38 -0
- data/lib/rubycc/pkgconf/system_path_filter.rb +131 -0
- data/lib/rubycc/preprocess/constant_expression.rb +219 -0
- data/lib/rubycc/preprocess/glibc_version.rb +124 -0
- data/lib/rubycc/preprocess/pp_token.rb +62 -0
- data/lib/rubycc/preprocess/preprocessor.rb +2020 -0
- data/lib/rubycc/preprocess/scanner.rb +290 -0
- data/lib/rubycc/preprocess/token_converter.rb +157 -0
- data/lib/rubycc/rmake/cli.rb +143 -0
- data/lib/rubycc/rmake/errors.rb +71 -0
- data/lib/rubycc/rmake/executor.rb +818 -0
- data/lib/rubycc/rmake/expander.rb +251 -0
- data/lib/rubycc/rmake/makefile.rb +352 -0
- data/lib/rubycc/rmake/model.rb +137 -0
- data/lib/rubycc/rmake/parser.rb +226 -0
- data/lib/rubycc/rmake/rmake.rb +15 -0
- data/lib/rubycc/type.rb +1236 -0
- data/lib/rubycc/version.rb +5 -0
- data/lib/rubycc.rb +36 -0
- data/lib/rubygems_plugin.rb +102 -0
- metadata +219 -0
|
@@ -0,0 +1,4122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "ast"
|
|
4
|
+
require_relative "constant_evaluator"
|
|
5
|
+
require_relative "initializer_resolver"
|
|
6
|
+
require_relative "../type"
|
|
7
|
+
require_relative "../compile_error"
|
|
8
|
+
|
|
9
|
+
module Rubycc
|
|
10
|
+
module Front
|
|
11
|
+
# Recursive-descent parser for the C subset. Nonterminals follow the
|
|
12
|
+
# grammar productions of ISO C (6.5.x / 6.7 / 6.8.x):
|
|
13
|
+
#
|
|
14
|
+
# translation-unit = external-declaration*
|
|
15
|
+
# external-declaration = type-specifier ";" -- tag only
|
|
16
|
+
# | type-specifier declarator
|
|
17
|
+
# ( (";" | compound-statement) -- function
|
|
18
|
+
# (declarator
|
|
19
|
+
# is a
|
|
20
|
+
# function)
|
|
21
|
+
# | ("=" initializer)?
|
|
22
|
+
# ("," declarator ("=" initializer)?)*
|
|
23
|
+
# ";" ) -- variables
|
|
24
|
+
# declaration-specifiers = (storage-class-specifier | type-specifier)+
|
|
25
|
+
# storage-class-specifier = "typedef"
|
|
26
|
+
# type-specifier = "void" | "char" | "short" | "int" | "long"
|
|
27
|
+
# | "signed" | "unsigned" | "_Bool"
|
|
28
|
+
# | struct-or-union-specifier | enum-specifier
|
|
29
|
+
# | typedef-name
|
|
30
|
+
# typedef-name = identifier
|
|
31
|
+
# struct-or-union-specifier = struct-or-union identifier?
|
|
32
|
+
# "{" struct-declaration+ "}"
|
|
33
|
+
# | struct-or-union identifier
|
|
34
|
+
# struct-or-union = "struct" | "union"
|
|
35
|
+
# enum-specifier = "enum" identifier? "{" enumerator-list ","? "}"
|
|
36
|
+
# | "enum" identifier
|
|
37
|
+
# enumerator-list = enumerator ("," enumerator)*
|
|
38
|
+
# enumerator = identifier ("=" constant-expression)?
|
|
39
|
+
# struct-declaration = type-specifier declarator
|
|
40
|
+
# ("," declarator)* ";"
|
|
41
|
+
# | struct-or-union-specifier ";" -- anonymous
|
|
42
|
+
# parameter-type-list = "void"
|
|
43
|
+
# | parameter-declaration
|
|
44
|
+
# ("," parameter-declaration)*
|
|
45
|
+
# parameter-declaration = type-specifier declarator
|
|
46
|
+
# identifier-list = identifier ("," identifier)*
|
|
47
|
+
# declarator = "*"* direct-declarator
|
|
48
|
+
# direct-declarator = (identifier | "(" declarator ")")
|
|
49
|
+
# direct-declarator-suffix*
|
|
50
|
+
# direct-declarator-suffix = "[" constant-expression? "]"
|
|
51
|
+
# | "(" parameter-type-list? ")"
|
|
52
|
+
# | "(" identifier-list ")" -- old style
|
|
53
|
+
# function-definition = declaration-specifiers declarator
|
|
54
|
+
# declaration-list? compound-statement
|
|
55
|
+
# declaration-list = declaration+
|
|
56
|
+
# abstract-declarator = "*"* direct-abstract-declarator?
|
|
57
|
+
# direct-abstract-declarator = ("(" abstract-declarator ")")?
|
|
58
|
+
# direct-declarator-suffix*
|
|
59
|
+
# compound-statement = "{" block-item* "}"
|
|
60
|
+
# block-item = declaration | statement
|
|
61
|
+
# declaration = type-specifier ";"
|
|
62
|
+
# | type-specifier init-declarator
|
|
63
|
+
# ("," init-declarator)* ";"
|
|
64
|
+
# init-declarator = declarator ("=" initializer)?
|
|
65
|
+
# initializer = assignment-expression
|
|
66
|
+
# | "{" initializer-list ","? "}"
|
|
67
|
+
# initializer-list = designation? initializer
|
|
68
|
+
# ("," designation? initializer)*
|
|
69
|
+
# designation = designator+ "="
|
|
70
|
+
# designator = "[" constant-expression "]" | "." identifier
|
|
71
|
+
# statement = labeled-statement | return-statement
|
|
72
|
+
# | expression-statement | selection-statement
|
|
73
|
+
# | iteration-statement | jump-statement
|
|
74
|
+
# | compound-statement
|
|
75
|
+
# labeled-statement = identifier ":" statement
|
|
76
|
+
# | "case" constant-expression ":" statement
|
|
77
|
+
# | "default" ":" statement
|
|
78
|
+
# return-statement = "return" expression? ";"
|
|
79
|
+
# expression-statement = expression? ";"
|
|
80
|
+
# selection-statement = "if" "(" expression ")" statement
|
|
81
|
+
# ("else" statement)?
|
|
82
|
+
# | "switch" "(" expression ")" statement
|
|
83
|
+
# iteration-statement = "while" "(" expression ")" statement
|
|
84
|
+
# | "do" statement "while" "(" expression ")" ";"
|
|
85
|
+
# | "for" "(" for-init expression? ";"
|
|
86
|
+
# expression? ")" statement
|
|
87
|
+
# for-init = declaration | expression? ";"
|
|
88
|
+
# jump-statement = "break" ";" | "continue" ";"
|
|
89
|
+
# | "goto" identifier ";"
|
|
90
|
+
# expression = assignment-expression
|
|
91
|
+
# ("," assignment-expression)*
|
|
92
|
+
# assignment-expression = conditional-expression
|
|
93
|
+
# (("=" | "+=" | "-=" | "*=" | "/=" | "%="
|
|
94
|
+
# | "&=" | "|=" | "^=" | "<<=" | ">>=")
|
|
95
|
+
# assignment-expression)?
|
|
96
|
+
# conditional-expression = logical-OR-expression
|
|
97
|
+
# ("?" expression ":" conditional-expression)?
|
|
98
|
+
# constant-expression = conditional-expression
|
|
99
|
+
# logical-OR-expression = logical-AND-expression
|
|
100
|
+
# ("||" logical-AND-expression)*
|
|
101
|
+
# logical-AND-expression = inclusive-OR-expression
|
|
102
|
+
# ("&&" inclusive-OR-expression)*
|
|
103
|
+
# inclusive-OR-expression = exclusive-OR-expression
|
|
104
|
+
# ("|" exclusive-OR-expression)*
|
|
105
|
+
# exclusive-OR-expression = AND-expression ("^" AND-expression)*
|
|
106
|
+
# AND-expression = equality-expression ("&" equality-expression)*
|
|
107
|
+
# equality-expression = relational-expression
|
|
108
|
+
# (("==" | "!=") relational-expression)*
|
|
109
|
+
# relational-expression = shift-expression
|
|
110
|
+
# (("<" | ">" | "<=" | ">=") shift-expression)*
|
|
111
|
+
# shift-expression = additive-expression
|
|
112
|
+
# (("<<" | ">>") additive-expression)*
|
|
113
|
+
# additive-expression = multiplicative-expression
|
|
114
|
+
# (("+" | "-") multiplicative-expression)*
|
|
115
|
+
# multiplicative-expression = cast-expression
|
|
116
|
+
# (("*" | "/" | "%") cast-expression)*
|
|
117
|
+
# cast-expression = "(" type-name ")" cast-expression
|
|
118
|
+
# | unary-expression
|
|
119
|
+
# unary-expression = ("+" | "-" | "!" | "~" | "&" | "*")* cast-expression
|
|
120
|
+
# | ("++" | "--") unary-expression
|
|
121
|
+
# | "sizeof" unary-expression
|
|
122
|
+
# | "sizeof" "(" type-name ")"
|
|
123
|
+
# type-name = type-specifier abstract-declarator?
|
|
124
|
+
# postfix-expression = primary-expression
|
|
125
|
+
# ("[" expression "]"
|
|
126
|
+
# | "(" argument-expression-list? ")"
|
|
127
|
+
# | "." identifier | "->" identifier
|
|
128
|
+
# | "++" | "--")*
|
|
129
|
+
# argument-expression-list = assignment-expression
|
|
130
|
+
# ("," assignment-expression)*
|
|
131
|
+
# primary-expression = integer-constant | string-literal
|
|
132
|
+
# | identifier | "(" expression ")"
|
|
133
|
+
#
|
|
134
|
+
# Binary precedence levels are parsed by a single table-driven
|
|
135
|
+
# left-associative loop (see #parse_left_associative) rather than one
|
|
136
|
+
# hand-written loop per level, so adding an operator or a precedence
|
|
137
|
+
# tier only requires a new table entry. assignment-expression is
|
|
138
|
+
# right-associative and is handled separately (see #parse_assignment_expression),
|
|
139
|
+
# as is conditional-expression (see #parse_conditional_expression), whose
|
|
140
|
+
# third operand recurses back into itself rather than into the tier above.
|
|
141
|
+
class Parser
|
|
142
|
+
# Punctuator → AST operator tables, one per precedence tier
|
|
143
|
+
# (weakest binding first).
|
|
144
|
+
COMPOUND_ASSIGNMENT_OPERATORS = {
|
|
145
|
+
"+=" => :add, "-=" => :sub, "*=" => :mul, "/=" => :div, "%=" => :mod,
|
|
146
|
+
"&=" => :and, "|=" => :or, "^=" => :xor, "<<=" => :shl, ">>=" => :shr
|
|
147
|
+
}.freeze
|
|
148
|
+
INCLUSIVE_OR_OPERATORS = { "|" => :or }.freeze
|
|
149
|
+
EXCLUSIVE_OR_OPERATORS = { "^" => :xor }.freeze
|
|
150
|
+
AND_OPERATORS = { "&" => :and }.freeze
|
|
151
|
+
EQUALITY_OPERATORS = { "==" => :eq, "!=" => :ne }.freeze
|
|
152
|
+
RELATIONAL_OPERATORS = { "<" => :lt, ">" => :gt, "<=" => :le, ">=" => :ge }.freeze
|
|
153
|
+
# ">>" desugars to an arithmetic shift (:shr here names the source
|
|
154
|
+
# operator, which the generator lowers to a signed :sar); a future
|
|
155
|
+
# unsigned type will lower the same :shr to a logical shift instead.
|
|
156
|
+
SHIFT_OPERATORS = { "<<" => :shl, ">>" => :shr }.freeze
|
|
157
|
+
ADDITIVE_OPERATORS = { "+" => :add, "-" => :sub }.freeze
|
|
158
|
+
MULTIPLICATIVE_OPERATORS = { "*" => :mul, "/" => :div, "%" => :mod }.freeze
|
|
159
|
+
|
|
160
|
+
# The keywords that make up an integer/void type-specifier list (a "struct"
|
|
161
|
+
# specifier is handled on its own). A declaration begins with one or more
|
|
162
|
+
# of these; #normalize_type_specifiers collapses the collected multiset
|
|
163
|
+
# into a single Rubycc::Type. "void" is only ever valid as a function's
|
|
164
|
+
# return type or as the target of a pointer; every other use is rejected
|
|
165
|
+
# by #reject_void_type.
|
|
166
|
+
DECL_SPECIFIER_KEYWORDS = %w[void char short int long signed unsigned _Bool float double __int128].freeze
|
|
167
|
+
|
|
168
|
+
# The x86_64 "biggest alignment" gcc gives a bare
|
|
169
|
+
# `__attribute__((aligned))` with no argument (BIGGEST_ALIGNMENT, 16
|
|
170
|
+
# bytes): the most useful boundary, enough for any scalar or vector type.
|
|
171
|
+
BIGGEST_ALIGNMENT = 16
|
|
172
|
+
|
|
173
|
+
# The GNU attribute names Step 28 gives real layout meaning; every other
|
|
174
|
+
# attribute is accepted and silently discarded. Kept in sync with the
|
|
175
|
+
# preprocessor's __has_attribute answer (see Preprocessor#fold_has_attribute).
|
|
176
|
+
LAYOUT_ATTRIBUTES = %w[aligned packed].freeze
|
|
177
|
+
|
|
178
|
+
# The GNU attribute names that register a function with the runtime rather
|
|
179
|
+
# than describe it: `constructor` puts it in the object's .init_array (the
|
|
180
|
+
# loader calls it before main / at dlopen) and `destructor` in .fini_array
|
|
181
|
+
# (at exit / dlclose). Mapped to the array kind the later stages use.
|
|
182
|
+
# Kept in sync with the preprocessor's __has_attribute answer.
|
|
183
|
+
INIT_ATTRIBUTES = { "constructor" => :constructor, "destructor" => :destructor }.freeze
|
|
184
|
+
|
|
185
|
+
# The priority window these attributes accept, measured by handing
|
|
186
|
+
# `__attribute__((constructor(N)))` to gcc and reading back what it emitted:
|
|
187
|
+
# 0..65535 inclusive is taken (0..100 only with a -Wprio-ctor-dtor warning,
|
|
188
|
+
# that range being reserved for the implementation), and anything outside is
|
|
189
|
+
# the hard error "constructor priorities must be integers from 0 to 65535
|
|
190
|
+
# inclusive". The same measurement showed 65535 is gcc's *default*:
|
|
191
|
+
# `constructor(65535)` emits the plain, unnumbered `.init_array`, exactly as
|
|
192
|
+
# a bare `constructor` does, so an absent priority is represented as 65535
|
|
193
|
+
# here and the two spellings coincide downstream just as they do in gcc.
|
|
194
|
+
# ObjFile::ELFWriter::DEFAULT_ARRAY_PRIORITY is the same number on the
|
|
195
|
+
# other side of the IR, where it decides the section's name.
|
|
196
|
+
MIN_INIT_PRIORITY = 0
|
|
197
|
+
MAX_INIT_PRIORITY = 65535
|
|
198
|
+
DEFAULT_INIT_PRIORITY = 65535
|
|
199
|
+
|
|
200
|
+
# The spellings of the "restrict" type qualifier this subset recognizes.
|
|
201
|
+
# ISO "restrict" is not a keyword here (it never gains semantics — a
|
|
202
|
+
# restricted pointer is treated like any other), and glibc prototypes use
|
|
203
|
+
# the reserved GNU spellings "__restrict"/"__restrict__" unconditionally, so
|
|
204
|
+
# all three arrive as ordinary identifiers and are accepted and discarded
|
|
205
|
+
# wherever a pointer or array-parameter qualifier may appear.
|
|
206
|
+
RESTRICT_SPELLINGS = %w[restrict __restrict __restrict__].freeze
|
|
207
|
+
|
|
208
|
+
# The gcc __atomic_* builtins this subset lowers, mapping each keyword to
|
|
209
|
+
# its [AST::BuiltinAtomic kind, argument count]. The nine object forms
|
|
210
|
+
# cover <ruby/atomic.h>; the fence is also supported because C11 library
|
|
211
|
+
# headers and libev use it without an _Atomic object. The test-and-set and
|
|
212
|
+
# the generic (non-"_n") address-taking forms remain deliberately absent,
|
|
213
|
+
# so a program using one of those gets an "undeclared identifier" rather
|
|
214
|
+
# than a silently wrong lowering. (The legacy __sync_* family has its own
|
|
215
|
+
# table below.)
|
|
216
|
+
#
|
|
217
|
+
# The counts include the trailing memory-order argument(s) gcc's signatures
|
|
218
|
+
# take — one for every form but __atomic_compare_exchange_n, which takes a
|
|
219
|
+
# `weak` flag and *two* orders (success and failure).
|
|
220
|
+
ATOMIC_BUILTINS = {
|
|
221
|
+
"__atomic_load_n" => [:load, 2],
|
|
222
|
+
"__atomic_store_n" => [:store, 3],
|
|
223
|
+
"__atomic_exchange_n" => [:exchange, 3],
|
|
224
|
+
"__atomic_compare_exchange_n" => [:compare_exchange, 6],
|
|
225
|
+
"__atomic_fetch_add" => [:fetch_add, 3],
|
|
226
|
+
"__atomic_fetch_sub" => [:fetch_sub, 3],
|
|
227
|
+
"__atomic_add_fetch" => [:add_fetch, 3],
|
|
228
|
+
"__atomic_sub_fetch" => [:sub_fetch, 3],
|
|
229
|
+
"__atomic_or_fetch" => [:or_fetch, 3],
|
|
230
|
+
"__atomic_thread_fence" => [:fence, 1]
|
|
231
|
+
}.freeze
|
|
232
|
+
|
|
233
|
+
# The legacy gcc __sync_* builtins this subset lowers, mapping each keyword
|
|
234
|
+
# to its [AST::BuiltinSync kind, argument count]. These predate the
|
|
235
|
+
# __atomic_* family and differ from it in two ways that matter here: each
|
|
236
|
+
# one is a *full barrier* by definition, so none takes a memory-order
|
|
237
|
+
# argument, and the two compare-and-swap forms take the value they expect
|
|
238
|
+
# directly rather than through a pointer.
|
|
239
|
+
#
|
|
240
|
+
# The set is exactly the forms an existing IR op already gives the right
|
|
241
|
+
# meaning for. The bitwise members with no matching op — __sync_fetch_and_or,
|
|
242
|
+
# __sync_fetch_and_and, __sync_fetch_and_xor, __sync_fetch_and_nand,
|
|
243
|
+
# __sync_and_and_fetch, __sync_xor_and_fetch and __sync_nand_and_fetch —
|
|
244
|
+
# stay deliberately absent for the same reason the missing __atomic_* forms
|
|
245
|
+
# do: a program using one gets an "undeclared identifier" instead of a
|
|
246
|
+
# silently wrong lowering.
|
|
247
|
+
#
|
|
248
|
+
# gcc tolerates extra trailing arguments on all of these (its documented
|
|
249
|
+
# but ignored list of variables to protect). rubycc requires the exact
|
|
250
|
+
# count, so a miscount is reported here rather than quietly dropped.
|
|
251
|
+
SYNC_BUILTINS = {
|
|
252
|
+
"__sync_fetch_and_add" => [:fetch_add, 2],
|
|
253
|
+
"__sync_fetch_and_sub" => [:fetch_sub, 2],
|
|
254
|
+
"__sync_add_and_fetch" => [:add_fetch, 2],
|
|
255
|
+
"__sync_sub_and_fetch" => [:sub_fetch, 2],
|
|
256
|
+
"__sync_or_and_fetch" => [:or_fetch, 2],
|
|
257
|
+
"__sync_lock_test_and_set" => [:exchange, 2],
|
|
258
|
+
"__sync_lock_release" => [:release, 1],
|
|
259
|
+
"__sync_synchronize" => [:fence, 0],
|
|
260
|
+
"__sync_bool_compare_and_swap" => [:bool_compare_and_swap, 3],
|
|
261
|
+
"__sync_val_compare_and_swap" => [:val_compare_and_swap, 3]
|
|
262
|
+
}.freeze
|
|
263
|
+
|
|
264
|
+
# The gcc overflow-checked arithmetic builtins, mapping each keyword to its
|
|
265
|
+
# AST::BuiltinOverflow operator. All three take the same three arguments
|
|
266
|
+
# (the two operands and the pointer the result is stored through), so the
|
|
267
|
+
# operator is the only thing the spelling decides. The width-suffixed forms
|
|
268
|
+
# (__builtin_uaddll_overflow and kin) are deliberately absent: the generic
|
|
269
|
+
# forms cover every use here, and a missing one is an "undeclared
|
|
270
|
+
# identifier" rather than a wrong lowering.
|
|
271
|
+
OVERFLOW_BUILTINS = {
|
|
272
|
+
"__builtin_add_overflow" => :add,
|
|
273
|
+
"__builtin_sub_overflow" => :sub,
|
|
274
|
+
"__builtin_mul_overflow" => :mul
|
|
275
|
+
}.freeze
|
|
276
|
+
|
|
277
|
+
# The hard ceiling on how deeply the recursive descent will nest before it
|
|
278
|
+
# rejects an input rather than recurse further. A hostile source (tens of
|
|
279
|
+
# thousands of nested parentheses, unary operators, braces, ...) would
|
|
280
|
+
# otherwise drive the descent until the Ruby machine stack overflows,
|
|
281
|
+
# raising a bare SystemStackError that escapes as an unhandled crash
|
|
282
|
+
# instead of a diagnostic. Capping the depth turns that into an ordinary
|
|
283
|
+
# located CompileError.
|
|
284
|
+
#
|
|
285
|
+
# The value is deliberately well below the depth at which the stack
|
|
286
|
+
# actually gives out. On this toolchain the full pipeline (parser plus IR
|
|
287
|
+
# generation plus the backend, all of which recurse over the same AST)
|
|
288
|
+
# overflows at roughly 330 nested parentheses — the parenthesized-
|
|
289
|
+
# expression path is the most expensive, spending the entire binary-
|
|
290
|
+
# precedence chain per level. A single counter is shared across every
|
|
291
|
+
# recursive path — parenthesized/unary/cast/ternary/assignment expressions,
|
|
292
|
+
# compound statements, initializer lists, nested declarators and
|
|
293
|
+
# struct/union bodies — because these forms interleave (an expression
|
|
294
|
+
# inside a statement inside an initializer ...), so it is their *combined*
|
|
295
|
+
# live depth that threatens the stack, and bounding it here also bounds the
|
|
296
|
+
# AST depth every later pass recurses over.
|
|
297
|
+
#
|
|
298
|
+
# Because the expression grammar's right-recursive tiers each carry their
|
|
299
|
+
# own guard (assignment, conditional, unary, cast), one parenthesized level
|
|
300
|
+
# descends through several of them, so the counter climbs about 4 per
|
|
301
|
+
# nested parenthesis — the worst multiplier of any construct. 500 therefore
|
|
302
|
+
# admits roughly 122 nested parentheses: comfortably above C11 §5.2.4.1's
|
|
303
|
+
# 63-level implementation minimum, and about 12x the deepest nesting real
|
|
304
|
+
# inputs reach (measured: 41 in the c-testsuite, 32 for the ruby.h smoke
|
|
305
|
+
# header graph, 22 in the examples). At that ceiling the parser rejects
|
|
306
|
+
# after ~4900 live frames, well under the ~13000 at which Ruby's stack
|
|
307
|
+
# gives out, leaving headroom for a caller that starts from a deeper stack.
|
|
308
|
+
MAX_NESTING_DEPTH = 500
|
|
309
|
+
|
|
310
|
+
# The storage-class specifiers (6.7.1): at most one may appear in a
|
|
311
|
+
# declaration. "typedef", "static" and "extern" are recorded in
|
|
312
|
+
# DeclSpecInfo#storage and consumed downstream, while "register" and "auto"
|
|
313
|
+
# are accepted for compatibility but carry no effect in this subset, so
|
|
314
|
+
# they are consumed without being recorded; all five still participate in
|
|
315
|
+
# the "at most one storage class" duplicate check.
|
|
316
|
+
STORAGE_CLASS_KEYWORDS = %w[typedef static extern register auto].freeze
|
|
317
|
+
|
|
318
|
+
# The non-type parts of a declaration's specifier run, collected by
|
|
319
|
+
# #parse_declaration_specifiers alongside the base type. `storage` is the
|
|
320
|
+
# recorded storage class (nil, :typedef, :static or :extern); `const` is
|
|
321
|
+
# whether the declaration is const-qualified (const seen among the
|
|
322
|
+
# specifiers, or folded in from a const typedef name); `inline_p` and
|
|
323
|
+
# `noreturn_p` are whether "inline" or "_Noreturn" appeared (the two
|
|
324
|
+
# function specifiers, 6.7.4, accepted on functions and rejected on
|
|
325
|
+
# objects). `attributes` holds the GNU attributes written among the
|
|
326
|
+
# specifiers (position a), which apply to every declarator of the
|
|
327
|
+
# declaration; only the init attributes are read back from it, and only
|
|
328
|
+
# where they are admitted at all (see #parse_declaration_specifiers).
|
|
329
|
+
# `alignas` is the strongest _Alignas the run asked for (an Alignas, or nil
|
|
330
|
+
# when none appeared). volatile and register/auto leave no trace here.
|
|
331
|
+
DeclSpecInfo = Data.define(:storage, :const, :inline_p, :noreturn_p, :attributes, :alignas)
|
|
332
|
+
|
|
333
|
+
# One parsed GNU attribute: its normalized `name`, the folded `argument`
|
|
334
|
+
# (an integer for "aligned" and for the init attributes' priority, nil for
|
|
335
|
+
# every other attribute, whose arguments are skipped) and the `token` that
|
|
336
|
+
# spelled it, so a diagnostic about the attribute can be located.
|
|
337
|
+
Attribute = Data.define(:name, :argument, :token)
|
|
338
|
+
|
|
339
|
+
# The alignment an _Alignas specifier run asks for (6.7.5): `alignment` is
|
|
340
|
+
# the strongest boundary requested — a declaration may carry several
|
|
341
|
+
# alignment-specifiers and the largest wins (measured: gcc gives
|
|
342
|
+
# "_Alignas(8) _Alignas(16) int a" a 16-byte boundary whichever order the
|
|
343
|
+
# two are written in) — and `token` is the "_Alignas" that asked for it, so
|
|
344
|
+
# a diagnostic about the request can be located.
|
|
345
|
+
Alignas = Data.define(:alignment, :token)
|
|
346
|
+
|
|
347
|
+
# The identifier list of an old-style (K&R) function declarator — the
|
|
348
|
+
# "(a, b)" of "int add(a, b)", whose parentheses hold parameter *names*
|
|
349
|
+
# with no types at all (6.7.6.3, identifier-list form). `names` are the
|
|
350
|
+
# identifier tokens in order and `token` is the "(" that opened the list,
|
|
351
|
+
# both wanted by the declaration-list checks below.
|
|
352
|
+
#
|
|
353
|
+
# It rides the very channel a prototype's Parameter array does (the
|
|
354
|
+
# `function_params` a declarator reports), so it reaches every declarator
|
|
355
|
+
# position a parameter list can — and each of those refuses it (see
|
|
356
|
+
# #reject_identifier_list) except the one 6.7.6.3p3 allows, the definition
|
|
357
|
+
# of that same function.
|
|
358
|
+
IdentifierList = Data.define(:names, :token)
|
|
359
|
+
|
|
360
|
+
# A tag scope entry for an enum tag. C keeps struct, union and enum tags in
|
|
361
|
+
# one shared namespace, so enum tags live in @tag_scopes alongside the
|
|
362
|
+
# StructType objects that stand for struct tags. An enum contributes no
|
|
363
|
+
# distinct type — an enum object is just an int (6.7.2.2) — so this marker
|
|
364
|
+
# only records that the tag names an enum, which lets a later "struct X"
|
|
365
|
+
# (or "enum X" against a struct tag) be diagnosed as the wrong kind of tag.
|
|
366
|
+
EnumTag = Data.define(:tag)
|
|
367
|
+
|
|
368
|
+
# An entry in the ordinary-identifier scope (see @ordinary_scopes). `kind`
|
|
369
|
+
# is :typedef for a typedef name (`value` a [resolved Rubycc::Type, const?]
|
|
370
|
+
# pair, the flag carrying a "typedef const int" so a use folds it back into
|
|
371
|
+
# the object's const-ness), :enum
|
|
372
|
+
# for an enumeration constant (`value` its Integer value), or :ordinary for
|
|
373
|
+
# a variable, parameter or function name (`value` nil). The ordinary
|
|
374
|
+
# entries carry no payload; they exist only so a declarator can shadow a
|
|
375
|
+
# typedef name or an enum constant of the same name from an outer scope,
|
|
376
|
+
# keeping "typedef int T; { int T; ... }" from misreading the inner T as a
|
|
377
|
+
# type.
|
|
378
|
+
OrdinaryName = Data.define(:kind, :value)
|
|
379
|
+
|
|
380
|
+
# `plain_char` is the Rubycc::Type a bare `char` type-specifier resolves
|
|
381
|
+
# to. Its signedness is implementation-defined and pinned per ABI, so the
|
|
382
|
+
# caller that knows the target hands it in (see Compiler#compile);
|
|
383
|
+
# defaulting to the signed instance keeps a target-less caller on the
|
|
384
|
+
# x86-64 System V choice. `signed char` and `unsigned char` are unaffected —
|
|
385
|
+
# both are separate types with a fixed signedness.
|
|
386
|
+
#
|
|
387
|
+
# `unnamed_bitfields_align` is the second such per-ABI trait: whether an
|
|
388
|
+
# unnamed bit-field's type raises its aggregate's alignment (it does under
|
|
389
|
+
# AAPCS64, not under the x86-64 System V psABI). It is passed straight to
|
|
390
|
+
# StructType#define, which documents the rule.
|
|
391
|
+
#
|
|
392
|
+
# `builtin_va_list` is the third: the type `__builtin_va_list` names, whose
|
|
393
|
+
# tag layout differs between the ABIs (four fields on System V, five on
|
|
394
|
+
# AAPCS64). The caller hands in the target's from its CallConvention so the
|
|
395
|
+
# typedef the parser seeds below reserves the right-sized object and, being
|
|
396
|
+
# the same tag instance the generator type-checks against, is recognized by
|
|
397
|
+
# identity there.
|
|
398
|
+
def initialize(tokens, plain_char: Type::Char, unnamed_bitfields_align: false,
|
|
399
|
+
builtin_va_list: Type::BuiltinVaList)
|
|
400
|
+
@tokens = tokens
|
|
401
|
+
@plain_char = plain_char
|
|
402
|
+
@unnamed_bitfields_align = unnamed_bitfields_align
|
|
403
|
+
@builtin_va_list = builtin_va_list
|
|
404
|
+
@pos = 0
|
|
405
|
+
# The number of recursive-descent nesting levels currently live, capped
|
|
406
|
+
# at MAX_NESTING_DEPTH by #with_nesting_guard. One counter is shared by
|
|
407
|
+
# every recursive construct so their interleaved depth is what is bounded.
|
|
408
|
+
@nesting_depth = 0
|
|
409
|
+
# Struct and enum tags live in their own namespace, separate from
|
|
410
|
+
# variables and functions, and follow the same block scoping.
|
|
411
|
+
# @tag_scopes is a stack of "tag name -> Type::StructType | EnumTag"
|
|
412
|
+
# maps, innermost last, with the file scope at the bottom; a
|
|
413
|
+
# compound-statement (and a for-loop's own parentheses, and a function
|
|
414
|
+
# body) pushes a fresh map so a tag defined inside a block shadows an
|
|
415
|
+
# outer one and vanishes at the block's end. Tag resolution happens here,
|
|
416
|
+
# at parse time, because every other type is built here too — the
|
|
417
|
+
# generator only ever consumes finished Type objects.
|
|
418
|
+
@tag_scopes = [{}]
|
|
419
|
+
# The ordinary-identifier namespace, scoped in lockstep with @tag_scopes:
|
|
420
|
+
# a stack of "name -> OrdinaryName" maps. It records typedef names
|
|
421
|
+
# (resolved to a Type), enum constants (resolved to an Integer) and the
|
|
422
|
+
# plain declarator names that shadow them, so a name is looked up here to
|
|
423
|
+
# decide whether an identifier opens a declaration (a typedef name), folds
|
|
424
|
+
# to a constant (an enumerator) or is an ordinary reference. The outermost
|
|
425
|
+
# scope is pre-seeded with `__builtin_va_list` as a typedef for the
|
|
426
|
+
# target's va_list type (a one-element __va_list_tag array), exactly as
|
|
427
|
+
# gcc predeclares it, so "__builtin_va_list ap;" is parsed as a
|
|
428
|
+
# declaration with no dedicated keyword and a program may still shadow the
|
|
429
|
+
# name.
|
|
430
|
+
@ordinary_scopes = [{ "__builtin_va_list" => OrdinaryName.new(:typedef, [@builtin_va_list, false]) }]
|
|
431
|
+
# The constructor/destructor registrations the unit asked for, keyed by
|
|
432
|
+
# function name (see #register_init_attributes). Filled as declarations
|
|
433
|
+
# are read and handed to AST::Program whole, because the attribute may be
|
|
434
|
+
# written on a prototype that precedes *or* follows the definition, so no
|
|
435
|
+
# single declaration node can be the one that carries it.
|
|
436
|
+
@init_attributes = {}
|
|
437
|
+
# GNU visibility attributes are also declaration-order independent:
|
|
438
|
+
# Ruby's exported-function macro puts the explicit default visibility
|
|
439
|
+
# on a prototype, while the definition appears later without it.
|
|
440
|
+
@visibility_attributes = {}
|
|
441
|
+
# The parameter types each file-scope function *prototype* declared,
|
|
442
|
+
# keyed by name. Only one construct reads them: an old-style definition
|
|
443
|
+
# of a name a prototype already declared, which 6.7.6.3p14 checks
|
|
444
|
+
# against that prototype and which is then passed its arguments in the
|
|
445
|
+
# prototype's form rather than the promoted one (see
|
|
446
|
+
# #old_style_parameter_abi_types). Every other agreement between
|
|
447
|
+
# declarations of one function is the generator's to enforce.
|
|
448
|
+
@prototype_param_types = {}
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
# Parses the whole translation unit into an AST::Program. An external
|
|
452
|
+
# declaration yields a single node (a function) or, for a comma-separated
|
|
453
|
+
# run of global variables, an array of GlobalDecl; both are flattened into
|
|
454
|
+
# one source-ordered list.
|
|
455
|
+
def parse
|
|
456
|
+
declarations = []
|
|
457
|
+
until peek.eof?
|
|
458
|
+
# GCC accepts a stray semicolon at file scope as an empty external
|
|
459
|
+
# declaration. X-macro headers commonly leave one after a macro that
|
|
460
|
+
# already emits semicolon-terminated declarations (for example pg's
|
|
461
|
+
# GVL wrapper table), so consume the GNU extension here.
|
|
462
|
+
if peek.punct?(";")
|
|
463
|
+
advance
|
|
464
|
+
next
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
node = parse_external_declaration
|
|
468
|
+
node.is_a?(Array) ? declarations.concat(node) : declarations << node
|
|
469
|
+
end
|
|
470
|
+
AST::Program.new(declarations, @init_attributes, @visibility_attributes)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
private
|
|
474
|
+
|
|
475
|
+
def peek
|
|
476
|
+
@tokens[@pos]
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
# Looks ahead `offset` tokens without consuming; used to disambiguate a
|
|
480
|
+
# parenthesized declarator from a parameter list, a cast/sizeof type-name
|
|
481
|
+
# from a parenthesized expression, and a labeled statement from an
|
|
482
|
+
# expression-statement.
|
|
483
|
+
def peek_ahead(offset)
|
|
484
|
+
@tokens[@pos + offset]
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def advance
|
|
488
|
+
tok = @tokens[@pos]
|
|
489
|
+
@pos += 1 unless tok.eof?
|
|
490
|
+
tok
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
# Runs `block` one recursive-descent level deeper, first rejecting the
|
|
494
|
+
# input with a located CompileError once MAX_NESTING_DEPTH levels are
|
|
495
|
+
# already live — so a pathologically nested source is diagnosed rather than
|
|
496
|
+
# left to overflow the Ruby stack with a bare SystemStackError. The counter
|
|
497
|
+
# is decremented in an ensure, so a parse error thrown from within the
|
|
498
|
+
# block still unwinds the depth correctly. `token` locates the diagnostic
|
|
499
|
+
# and `what` names the construct (e.g. "expression", "block").
|
|
500
|
+
def with_nesting_guard(token, what)
|
|
501
|
+
error_at(token, "#{what} nested too deeply") if @nesting_depth >= MAX_NESTING_DEPTH
|
|
502
|
+
|
|
503
|
+
@nesting_depth += 1
|
|
504
|
+
begin
|
|
505
|
+
yield
|
|
506
|
+
ensure
|
|
507
|
+
@nesting_depth -= 1
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
# An external declaration is either a function (a prototype ending in ";"
|
|
512
|
+
# or a definition ending in a compound-statement) or a file-scope variable
|
|
513
|
+
# declaration. Both begin with a type-specifier and a declarator; the
|
|
514
|
+
# declarator's built type settles the form — a function type is the
|
|
515
|
+
# function form (its declarator having read the "(" parameter list), any
|
|
516
|
+
# other type the variable form.
|
|
517
|
+
def parse_external_declaration
|
|
518
|
+
# A leading "__extension__" (a GNU marker that silences pedantic
|
|
519
|
+
# warnings) prefixes a declaration with no semantic effect; every
|
|
520
|
+
# external declaration is a declaration, so any run of them is discarded.
|
|
521
|
+
skip_extension_markers
|
|
522
|
+
|
|
523
|
+
# A file-scope "_Static_assert(expr, "msg");" is a declaration that binds
|
|
524
|
+
# nothing; it is checked and flattened away here (see #parse_static_assert).
|
|
525
|
+
return parse_static_assert if peek.keyword?("_Static_assert")
|
|
526
|
+
|
|
527
|
+
type_tok = peek
|
|
528
|
+
# A file-scope declaration is the one place a constructor/destructor
|
|
529
|
+
# attribute means something, so it is the one place the specifier run
|
|
530
|
+
# admits it; everywhere else it is refused rather than dropped.
|
|
531
|
+
base_type, spec_info = parse_declaration_specifiers(allow_storage_class: true,
|
|
532
|
+
allow_init_attributes: true)
|
|
533
|
+
|
|
534
|
+
# "struct point { ... };" (or "struct node;", or a tag-only "enum E { ...
|
|
535
|
+
# };") with no declarator only declares or defines the tag, which the
|
|
536
|
+
# specifier parse already registered; it contributes no object and no
|
|
537
|
+
# code, so it flattens away to an empty run of declarations. A stray
|
|
538
|
+
# "typedef int;" with no declarator flattens away the same way. A
|
|
539
|
+
# declaration with no declarator declares no function either, so an init
|
|
540
|
+
# attribute the specifier run admitted has nothing to register.
|
|
541
|
+
if peek.punct?(";")
|
|
542
|
+
reject_init_attributes(spec_info.attributes)
|
|
543
|
+
advance
|
|
544
|
+
return []
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
# A typedef declaration binds each declarator's name as a type; it
|
|
548
|
+
# yields no object and no code (see #parse_typedef_declaration).
|
|
549
|
+
if spec_info.storage == :typedef
|
|
550
|
+
# A typedef binds a name, not a function, so an init attribute among
|
|
551
|
+
# its specifiers has nothing to register; the specifier run admitted it
|
|
552
|
+
# only because a file-scope *function* declaration may start the same
|
|
553
|
+
# way, so it is refused here rather than dropped.
|
|
554
|
+
reject_init_attributes(spec_info.attributes)
|
|
555
|
+
return parse_typedef_declaration(base_type, spec_info)
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
name_tok, type, function_params, pointer_quals =
|
|
559
|
+
parse_declarator(base_type, allow_incomplete_array: true)
|
|
560
|
+
# A GNU attribute may trail the declarator (position d):
|
|
561
|
+
# "int f(void) __attribute__((noreturn));". Accepted and discarded, on a
|
|
562
|
+
# function prototype/definition or a variable alike — except an init
|
|
563
|
+
# attribute, which is claimed below. The specifier-position attributes
|
|
564
|
+
# belong to every declarator of this declaration, so they join it here.
|
|
565
|
+
#
|
|
566
|
+
# gcc rejects the *definition* form ("void f(void)
|
|
567
|
+
# __attribute__((constructor)) { }") with "attributes should be specified
|
|
568
|
+
# before the declarator in a function definition"; this parser accepts it,
|
|
569
|
+
# a deliberate superset — refusing a form whose intent is unambiguous
|
|
570
|
+
# would buy nothing, while dropping it silently is the failure this whole
|
|
571
|
+
# position-by-position handling exists to avoid.
|
|
572
|
+
attributes = spec_info.attributes + parse_attribute_specifiers(init_attributes: :allow)
|
|
573
|
+
|
|
574
|
+
# An old-style declarator ("int add(a, b)") names its parameters without
|
|
575
|
+
# typing them, so what follows is not a "{" but the declaration-list that
|
|
576
|
+
# supplies those types (6.9.1). This is the one position where such a
|
|
577
|
+
# declarator is legal at all, so it branches off before the ordinary
|
|
578
|
+
# "declarator then {" test below.
|
|
579
|
+
if function_params.is_a?(IdentifierList)
|
|
580
|
+
return parse_old_style_function_definition(name_tok, type, function_params, spec_info,
|
|
581
|
+
type_tok, attributes)
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
# A function definition is the one external declaration whose declarator
|
|
585
|
+
# is followed by a compound statement (6.9.1); the declarator must be a
|
|
586
|
+
# function type and it stands alone. Every other shape — a function
|
|
587
|
+
# prototype, an object, or a comma-separated run mixing the two
|
|
588
|
+
# ("int f(int a), g(int a), a;") — is a declaration list, so a
|
|
589
|
+
# function-typed *first* declarator does not by itself commit the line to
|
|
590
|
+
# a definition: only a following "{" does.
|
|
591
|
+
if type.function? && peek.punct?("{")
|
|
592
|
+
# A function's parameters must be declared by the definition's own
|
|
593
|
+
# declarator (6.9.1p2): a function type reached through a typedef
|
|
594
|
+
# ("typedef int F(int); F f { ... }") supplies no parameter list of
|
|
595
|
+
# its own — `function_params` is nil — so it may declare a prototype
|
|
596
|
+
# but not a definition.
|
|
597
|
+
if function_params.nil?
|
|
598
|
+
error_at(name_tok, "function definition through a typedef is not allowed")
|
|
599
|
+
end
|
|
600
|
+
# A function reserves no object to align (6.7.5p2).
|
|
601
|
+
reject_alignas(spec_info.alignas, "function '#{name_tok.value}'")
|
|
602
|
+
declare_ordinary_name(name_tok.value, type)
|
|
603
|
+
register_visibility_attributes(name_tok.value, attributes)
|
|
604
|
+
register_init_attributes(name_tok.value, attributes)
|
|
605
|
+
return parse_function_definition(name_tok.value, type.return_type, function_params,
|
|
606
|
+
type_tok, spec_info.storage, type.variadic)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
parse_external_declaration_list(base_type, name_tok, type, function_params,
|
|
610
|
+
pointer_quals, spec_info, type_tok, attributes)
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
# An old-style (K&R) function definition, 6.9.1's second form: a declarator
|
|
614
|
+
# whose parentheses hold an identifier-list, then the declaration-list that
|
|
615
|
+
# gives those identifiers their types, then the body —
|
|
616
|
+
#
|
|
617
|
+
# int add(a, b)
|
|
618
|
+
# int a;
|
|
619
|
+
# int b;
|
|
620
|
+
# { return a + b; }
|
|
621
|
+
#
|
|
622
|
+
# The declarator has already been read (`type` is the function type its
|
|
623
|
+
# suffix built with an empty parameter list, a placeholder this rebuilds).
|
|
624
|
+
# Three rules of 6.9.1 shape what follows: an identifier the
|
|
625
|
+
# declaration-list never declares has type `int` (p6); the parameters are
|
|
626
|
+
# adjusted and default-argument promoted, because a function defined this
|
|
627
|
+
# way has no prototype and its arguments therefore arrive promoted (p10
|
|
628
|
+
# with 6.5.2.2p6); and the identifier list is only legal here, in the
|
|
629
|
+
# definition of that very function (6.7.6.3p3).
|
|
630
|
+
#
|
|
631
|
+
# The declaration-list is read in the *enclosing* scope rather than the
|
|
632
|
+
# body's, so a tag first mentioned there ("int f(p) struct s *p; {...}")
|
|
633
|
+
# lands at file scope. That is a superset of what C scopes it to, and the
|
|
634
|
+
# alternative — a scope the body then inherits — would need the body's
|
|
635
|
+
# scope opened before the declaration-list is even seen; gcc warns about
|
|
636
|
+
# such a tag rather than making it useful, so nothing real depends on the
|
|
637
|
+
# difference.
|
|
638
|
+
def parse_old_style_function_definition(name_tok, type, identifier_list, spec_info,
|
|
639
|
+
return_tok, attributes)
|
|
640
|
+
# Every suffix that could have wrapped the identifier list into something
|
|
641
|
+
# other than a function type is already refused where it is applied (a
|
|
642
|
+
# function returning a function, an array of functions), so this only
|
|
643
|
+
# guards the invariant the rebuild below depends on.
|
|
644
|
+
error_at(name_tok, "expected a function declarator") unless type.function?
|
|
645
|
+
|
|
646
|
+
declared = parse_parameter_declaration_list(identifier_list)
|
|
647
|
+
params = old_style_parameters(identifier_list, declared)
|
|
648
|
+
abi_types = old_style_parameter_abi_types(name_tok.value, params.map(&:type))
|
|
649
|
+
params = params.each_with_index.map do |param, i|
|
|
650
|
+
next param if abi_types[i] == param.type
|
|
651
|
+
|
|
652
|
+
AST::Parameter.new(param.name, param.type, param.token, param.const, abi_types[i])
|
|
653
|
+
end
|
|
654
|
+
# The declarator's own suffix could only build "returning T" with an
|
|
655
|
+
# empty parameter list; the types are known now, so the function's real
|
|
656
|
+
# type is put together here. An old-style definition is never variadic —
|
|
657
|
+
# an identifier list has no "..." — so the flag is false throughout.
|
|
658
|
+
type = Type::FunctionType.new(type.return_type, abi_types, false)
|
|
659
|
+
|
|
660
|
+
# A function reserves no object to align (6.7.5p2).
|
|
661
|
+
reject_alignas(spec_info.alignas, "function '#{name_tok.value}'")
|
|
662
|
+
declare_ordinary_name(name_tok.value, type)
|
|
663
|
+
register_visibility_attributes(name_tok.value, attributes)
|
|
664
|
+
register_init_attributes(name_tok.value, attributes)
|
|
665
|
+
parse_function_definition(name_tok.value, type.return_type, params, return_tok,
|
|
666
|
+
spec_info.storage, false)
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
# The declaration-list of an old-style definition: the run of declarations
|
|
670
|
+
# between the declarator and the body, each declaring one or more of the
|
|
671
|
+
# identifiers the list named. Returns a "name => [type, const, token]" map
|
|
672
|
+
# for #old_style_parameters, and leaves the stream on the body's "{".
|
|
673
|
+
#
|
|
674
|
+
# These are parameter declarations, so they take a parameter's specifiers —
|
|
675
|
+
# const/volatile but no storage class other than `register`, the only one
|
|
676
|
+
# 6.9.1p6 admits (the shared specifier parse raises "'static' is not
|
|
677
|
+
# allowed here" for the rest) — and a parameter's adjustments, an array or
|
|
678
|
+
# function declarator becoming a pointer (6.7.6.3p7-8), which is what makes
|
|
679
|
+
# "int f(a) int a[10];" a pointer parameter exactly as the prototyped
|
|
680
|
+
# spelling is.
|
|
681
|
+
def parse_parameter_declaration_list(identifier_list)
|
|
682
|
+
names = identifier_list.names.map(&:value)
|
|
683
|
+
declared = {}
|
|
684
|
+
until peek.punct?("{")
|
|
685
|
+
unless type_specifier?(peek)
|
|
686
|
+
# A ";", "," or "=" here ends the declarator as a *declaration*, so
|
|
687
|
+
# this was never a definition and 6.7.6.3p3 has the last word on the
|
|
688
|
+
# identifier list. Anything else (a stray token, end of file) is a
|
|
689
|
+
# definition that simply broke off, and says so.
|
|
690
|
+
reject_identifier_list(identifier_list) if peek.punct?(";") || peek.punct?(",") ||
|
|
691
|
+
peek.punct?("=")
|
|
692
|
+
error_at(peek, "expected a parameter declaration or '{'")
|
|
693
|
+
end
|
|
694
|
+
parse_one_parameter_declaration(names, declared)
|
|
695
|
+
end
|
|
696
|
+
declared
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
# One declaration of the declaration-list: shared specifiers, then a
|
|
700
|
+
# comma-separated run of named declarators ("int a, *b;"), each of which
|
|
701
|
+
# must name a parameter of the identifier list exactly once.
|
|
702
|
+
def parse_one_parameter_declaration(names, declared)
|
|
703
|
+
base_type, spec_info = parse_declaration_specifiers(allow_storage_class: false,
|
|
704
|
+
allow_register: true)
|
|
705
|
+
loop do
|
|
706
|
+
# A parameter's array declarator adjusts to a pointer, so "[]" is
|
|
707
|
+
# admitted here for the same reason #parse_parameter_declaration admits
|
|
708
|
+
# it in a prototype.
|
|
709
|
+
name_tok, param_type, params, pointer_quals =
|
|
710
|
+
parse_declarator(base_type, allow_incomplete_array: true)
|
|
711
|
+
reject_identifier_list(params)
|
|
712
|
+
parse_attribute_specifiers # position d: a trailing attribute on this declarator
|
|
713
|
+
# A parameter's boundary belongs to the calling convention, not to the
|
|
714
|
+
# declaration (6.7.5p2) — the same refusal a prototyped parameter gets.
|
|
715
|
+
reject_alignas(spec_info.alignas, "parameter '#{name_tok.value}'")
|
|
716
|
+
if peek.punct?("=")
|
|
717
|
+
error_at(name_tok, "parameter '#{name_tok.value}' must not be initialized")
|
|
718
|
+
end
|
|
719
|
+
unless names.include?(name_tok.value)
|
|
720
|
+
error_at(name_tok, "declaration for '#{name_tok.value}', which is not a parameter")
|
|
721
|
+
end
|
|
722
|
+
if declared.key?(name_tok.value)
|
|
723
|
+
error_at(name_tok, "redefinition of parameter '#{name_tok.value}'")
|
|
724
|
+
end
|
|
725
|
+
param_type = adjust_parameter_type(param_type)
|
|
726
|
+
reject_void_type(param_type, name_tok)
|
|
727
|
+
declared[name_tok.value] = [param_type,
|
|
728
|
+
declarator_object_const(param_type, spec_info.const, pointer_quals),
|
|
729
|
+
name_tok]
|
|
730
|
+
break unless peek.punct?(",")
|
|
731
|
+
|
|
732
|
+
advance # ","
|
|
733
|
+
end
|
|
734
|
+
expect_punct(";")
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
# The parameters of an old-style definition, in the identifier list's
|
|
738
|
+
# order: each name's declared entry, or — for a name the declaration-list
|
|
739
|
+
# left out — type `int`, located at the identifier itself (6.9.1p6). C90
|
|
740
|
+
# spelled that default out; C11 instead requires every identifier to be
|
|
741
|
+
# declared, but gcc keeps accepting the omission with a -Wimplicit-int
|
|
742
|
+
# warning (measured), and a warning is not a channel this compiler has, so
|
|
743
|
+
# the older, permissive reading is the one implemented.
|
|
744
|
+
def old_style_parameters(identifier_list, declared)
|
|
745
|
+
identifier_list.names.map do |name_tok|
|
|
746
|
+
type, const, decl_tok = declared[name_tok.value]
|
|
747
|
+
if type
|
|
748
|
+
AST::Parameter.new(name_tok.value, type, decl_tok, const)
|
|
749
|
+
else
|
|
750
|
+
AST::Parameter.new(name_tok.value, Type::Int, name_tok, false)
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
# The types an old-style definition's parameters are actually *passed* as,
|
|
756
|
+
# which is also its function type's parameter list.
|
|
757
|
+
#
|
|
758
|
+
# Normally these are the default-argument promotions of the declared types:
|
|
759
|
+
# the definition supplies no prototype, so every call to it promotes its
|
|
760
|
+
# arguments (6.5.2.2p6) and 6.9.1p10 makes the definition receive them that
|
|
761
|
+
# way — a `float` parameter is handed a `double`, a `char`/`short`/`_Bool`
|
|
762
|
+
# parameter an `int`.
|
|
763
|
+
#
|
|
764
|
+
# A prototype already declared for the same name overrides that, because
|
|
765
|
+
# calls compiled against it pass what *it* says (measured: gcc's
|
|
766
|
+
# "double h(float); double h(f) float f; {...}" receives a bare float in
|
|
767
|
+
# xmm0, while the same definition without the prototype receives a double
|
|
768
|
+
# and narrows it). 6.7.6.3p14 requires each prototype parameter to be
|
|
769
|
+
# compatible with the promoted declared type; gcc additionally accepts the
|
|
770
|
+
# unpromoted declared type there, warning only under -Wpedantic, and that
|
|
771
|
+
# is the case this branch exists for. Anything else is left to reach the
|
|
772
|
+
# generator's "conflicting types" check as the promoted form, which rejects
|
|
773
|
+
# exactly the mismatches gcc rejects ("int f(long); int f(a) int a;").
|
|
774
|
+
def old_style_parameter_abi_types(name, declared_types)
|
|
775
|
+
promoted = declared_types.map { |type| default_argument_promotion(type) }
|
|
776
|
+
prototype = @prototype_param_types[name]
|
|
777
|
+
return promoted unless prototype && prototype.size == declared_types.size
|
|
778
|
+
|
|
779
|
+
adoptable = prototype.each_with_index.all? do |type, i|
|
|
780
|
+
type == declared_types[i] || type == promoted[i]
|
|
781
|
+
end
|
|
782
|
+
adoptable ? prototype : promoted
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
# The default argument promotions (6.5.2.2p6) applied to one parameter
|
|
786
|
+
# type: `float` widens to `double` and an integer type narrower than `int`
|
|
787
|
+
# (char, short, their unsigned forms and _Bool) to `int`, which every such
|
|
788
|
+
# type fits since `int` is 32 bits on both targets. Everything else — int,
|
|
789
|
+
# long, their unsigned forms, __int128, double, pointers and structs —
|
|
790
|
+
# passes through unchanged. The array/function adjustments are not applied
|
|
791
|
+
# here: the declaration-list already made them (see
|
|
792
|
+
# #parse_one_parameter_declaration), exactly as a prototype's parameters do.
|
|
793
|
+
def default_argument_promotion(type)
|
|
794
|
+
return Type::Double if type.float? && type.size < 8
|
|
795
|
+
return Type::Int if type.integer? && type.size < 4
|
|
796
|
+
|
|
797
|
+
type
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
# Refuses an identifier list at a declarator position that cannot be the
|
|
801
|
+
# definition of that function. 6.7.6.3p3 lets a non-empty identifier list
|
|
802
|
+
# appear only there, so a prototype, a typedef, a member, a parameter or a
|
|
803
|
+
# local written that way ("int f(a, b);") names parameters whose types it
|
|
804
|
+
# never supplies. gcc only warns and reads such a declarator as the
|
|
805
|
+
# unprototyped "int f()"; this compiler models no unprototyped function
|
|
806
|
+
# type, so reading it that way would silently give the name a "(void)"
|
|
807
|
+
# signature and then check every call against it — a confident wrong
|
|
808
|
+
# diagnosis in place of an accurate one.
|
|
809
|
+
def reject_identifier_list(params)
|
|
810
|
+
return unless params.is_a?(IdentifierList)
|
|
811
|
+
|
|
812
|
+
error_at(params.token,
|
|
813
|
+
"parameter names without types are only allowed in a function definition")
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
# The declaration-list form of an external declaration: a comma-separated
|
|
817
|
+
# run of init-declarators sharing `base_type`, the first already read into
|
|
818
|
+
# `first_*`. Each declarator independently becomes a FunctionDecl (a
|
|
819
|
+
# function prototype) or a GlobalDecl (a file-scope object), so one
|
|
820
|
+
# declaration may mix the two ("int f(int a), g(int a), a;"). The run ends
|
|
821
|
+
# at ";".
|
|
822
|
+
def parse_external_declaration_list(base_type, first_name_tok, first_type, first_params,
|
|
823
|
+
first_pointer_quals, spec_info, return_tok, first_attributes)
|
|
824
|
+
decls = [parse_external_declarator(first_name_tok, first_type, first_params,
|
|
825
|
+
first_pointer_quals, spec_info, return_tok, first_attributes)]
|
|
826
|
+
while peek.punct?(",")
|
|
827
|
+
advance
|
|
828
|
+
name_tok, type, params, pointer_quals = parse_declarator(base_type, allow_incomplete_array: true)
|
|
829
|
+
# position d: a trailing attribute on this declarator, joined by the
|
|
830
|
+
# specifier-position ones the whole declaration shares.
|
|
831
|
+
attributes = spec_info.attributes + parse_attribute_specifiers(init_attributes: :allow)
|
|
832
|
+
decls << parse_external_declarator(name_tok, type, params, pointer_quals, spec_info,
|
|
833
|
+
return_tok, attributes)
|
|
834
|
+
end
|
|
835
|
+
expect_punct(";")
|
|
836
|
+
decls
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
# One init-declarator of an external declaration list. A function-typed
|
|
840
|
+
# declarator is a prototype — a FunctionDecl whose name is recorded as an
|
|
841
|
+
# ordinary identifier (so an inner block shadowing it is told from a typedef
|
|
842
|
+
# use); every other declarator is a file-scope object (see
|
|
843
|
+
# #parse_global_declarator, which reads any "=" initializer). `spec_info`
|
|
844
|
+
# carries the shared storage class and the "inline"/"_Noreturn" flags,
|
|
845
|
+
# legal only on the function declarators (an object declarator rejects
|
|
846
|
+
# them downstream).
|
|
847
|
+
def parse_external_declarator(name_tok, type, params, pointer_quals, spec_info, return_tok,
|
|
848
|
+
attributes)
|
|
849
|
+
# This declarator ends at a "," or a ";", so it is a declaration and not
|
|
850
|
+
# a definition — the one place 6.7.6.3p3 allows a non-empty identifier
|
|
851
|
+
# list.
|
|
852
|
+
reject_identifier_list(params)
|
|
853
|
+
if type.function?
|
|
854
|
+
# A function reserves no object to align (6.7.5p2).
|
|
855
|
+
reject_alignas(spec_info.alignas, "function '#{name_tok.value}'")
|
|
856
|
+
declare_ordinary_name(name_tok.value, type)
|
|
857
|
+
# A prototype's parameter types are kept for the one construct that
|
|
858
|
+
# consults them, an old-style definition of the same name.
|
|
859
|
+
@prototype_param_types[name_tok.value] = type.param_types
|
|
860
|
+
register_visibility_attributes(name_tok.value, attributes)
|
|
861
|
+
register_init_attributes(name_tok.value, attributes)
|
|
862
|
+
AST::FunctionDecl.new(name_tok.value, type.return_type,
|
|
863
|
+
declarator_prototype_params(type, params, return_tok), return_tok,
|
|
864
|
+
spec_info.storage, type.variadic)
|
|
865
|
+
else
|
|
866
|
+
# An init attribute on an object has nothing to register — there is no
|
|
867
|
+
# function to call — so it is refused here. gcc only warns ("attribute
|
|
868
|
+
# ignored"), but a warning this compiler has no channel for would be a
|
|
869
|
+
# silent drop, and a dropped initializer is invisible until the program
|
|
870
|
+
# misbehaves at run time.
|
|
871
|
+
reject_init_attributes(attributes)
|
|
872
|
+
register_visibility_attributes(name_tok.value, attributes)
|
|
873
|
+
parse_global_declarator(type, name_tok, pointer_quals, spec_info)
|
|
874
|
+
end
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
# The Parameter list a function-typed declarator contributes to its
|
|
878
|
+
# prototype. When the declarator carries its own "( parameter-list )"
|
|
879
|
+
# suffix, `params` is that list (each with the declared name). When the
|
|
880
|
+
# function type instead arrives through a typedef — "typedef VALUE
|
|
881
|
+
# getter_t(ID, VALUE *); getter_t g;" — the declarator has no parameter
|
|
882
|
+
# suffix of its own, so `params` is nil; the prototype's parameters are
|
|
883
|
+
# then synthesized from the typedef's parameter types as unnamed
|
|
884
|
+
# parameters (6.7.6.3), exactly as an explicit "int f(int, int);"
|
|
885
|
+
# prototype models its own. Such a declaration is always a prototype: a
|
|
886
|
+
# function may not be *defined* through a typedef (6.9.1p2), which the
|
|
887
|
+
# definition path rejects separately.
|
|
888
|
+
def declarator_prototype_params(type, params, token)
|
|
889
|
+
return params if params
|
|
890
|
+
|
|
891
|
+
type.param_types.map { |param_type| AST::Parameter.new(nil, param_type, token, false) }
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
# One global declarator's tail, its type (array suffix included) already
|
|
895
|
+
# built: the void/incomplete checks and an optional "=" initializer.
|
|
896
|
+
# A plain scalar-integer initializer is a constant-expression (6.6) folded
|
|
897
|
+
# to a Ruby Integer on the spot (initializer_value). Every other admitted
|
|
898
|
+
# form is deferred to the generator as a raw node (initializer_node): a
|
|
899
|
+
# brace initializer-list for an aggregate or scalar, a string for a char
|
|
900
|
+
# array, or an address constant for a pointer (a null pointer, a "&global",
|
|
901
|
+
# a decayed global array name, or a string literal). A structural
|
|
902
|
+
# initializer also completes an inferred "[]" bound here. A non-constant
|
|
903
|
+
# scalar-integer initializer (a call, another variable, ...) is still
|
|
904
|
+
# rejected with "unsupported initializer for global variable"; the deferred
|
|
905
|
+
# forms the generator cannot fold reach the same diagnostic there.
|
|
906
|
+
def parse_global_declarator(type, name_tok, pointer_quals, spec_info)
|
|
907
|
+
reject_void_type(type, name_tok)
|
|
908
|
+
reject_object_specifiers(name_tok, spec_info)
|
|
909
|
+
const = declarator_object_const(type, spec_info.const, pointer_quals)
|
|
910
|
+
initializer_value = nil
|
|
911
|
+
initializer_node = nil
|
|
912
|
+
if peek.punct?("=")
|
|
913
|
+
# An "extern" object with an initializer is a definition, not a mere
|
|
914
|
+
# reference; the two together are contradictory, so reject them.
|
|
915
|
+
if spec_info.storage == :extern
|
|
916
|
+
error_at(name_tok, "'#{name_tok.value}' has both 'extern' and initializer")
|
|
917
|
+
end
|
|
918
|
+
advance # "="
|
|
919
|
+
init = parse_initializer
|
|
920
|
+
if InitializerResolver.structural?(type, init)
|
|
921
|
+
# A file-scope object always has static storage duration, which is
|
|
922
|
+
# what lets a trailing flexible array member be initialized.
|
|
923
|
+
type = InitializerResolver.resolve(type, init, static_storage: true).type
|
|
924
|
+
initializer_node = init
|
|
925
|
+
elsif type.integer? && !references_sizeof_expr?(init) && !references_address_of?(init)
|
|
926
|
+
# An integer scalar initializer is folded to a value here, where the
|
|
927
|
+
# constant evaluator carries no type table. A `sizeof <expression>`
|
|
928
|
+
# operand needs the operand's type, and an address-of (the
|
|
929
|
+
# "(size_t)&((T*)0)->m" offsetof idiom) needs the generator's
|
|
930
|
+
# address-constant machinery, so an initializer that uses either is
|
|
931
|
+
# deferred as a raw node for the generator to fold instead (it reaches
|
|
932
|
+
# the same "unsupported initializer" diagnostic there when genuinely
|
|
933
|
+
# not a constant).
|
|
934
|
+
initializer_value = evaluate_constant_expression(init, "unsupported initializer for global variable")
|
|
935
|
+
else
|
|
936
|
+
initializer_node = init
|
|
937
|
+
end
|
|
938
|
+
elsif type.array? && type.length.nil? && spec_info.storage != :extern
|
|
939
|
+
# An `extern T a[];` is a reference to an array defined elsewhere, an
|
|
940
|
+
# incomplete type the defining unit completes (6.7.6.2p1, 6.9.2); it is
|
|
941
|
+
# kept as-is. A non-extern `T a[];` is a tentative definition whose
|
|
942
|
+
# bound the standard completes to [1] — a completion M1 does not
|
|
943
|
+
# perform — so it stays a diagnostic here.
|
|
944
|
+
error_at(name_tok, "array size missing in '#{name_tok.value}'")
|
|
945
|
+
end
|
|
946
|
+
declare_ordinary_name(name_tok.value, type)
|
|
947
|
+
# The boundary is settled against the *finished* type, so an inferred
|
|
948
|
+
# "[]" bound is already in place when the "cannot reduce" check runs.
|
|
949
|
+
AST::GlobalDecl.new(name_tok.value, type, initializer_value, initializer_node, name_tok, const,
|
|
950
|
+
spec_info.storage,
|
|
951
|
+
alignas_boundary(spec_info.alignas, type, "'#{name_tok.value}'"))
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
# A bare type-specifier list with no storage class, used where a type is
|
|
955
|
+
# written with no declaration to hang it on: the type-name of a cast,
|
|
956
|
+
# sizeof, _Alignof or compound literal. It resolves to a single
|
|
957
|
+
# Rubycc::Type, discarding the (always-false) typedef flag. A type-name
|
|
958
|
+
# declares no object, so it has nothing for an _Alignas to align
|
|
959
|
+
# (6.7.5p2) — gcc refuses one here and so does this.
|
|
960
|
+
def parse_type_specifier
|
|
961
|
+
type, spec_info = parse_declaration_specifiers(allow_storage_class: false)
|
|
962
|
+
reject_alignas(spec_info.alignas, "type name")
|
|
963
|
+
type
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
# declaration-specifiers = (storage-class-specifier | type-qualifier |
|
|
967
|
+
# function-specifier | type-specifier)+. Consumes the whole specifier run —
|
|
968
|
+
# at most one storage class (6.7.1), any const/volatile/inline, and the
|
|
969
|
+
# type itself, all in any order. The base type any
|
|
970
|
+
# leading "*" run then builds a pointer from is one of: a run of
|
|
971
|
+
# integer/void keywords collected and normalized by
|
|
972
|
+
# #normalize_type_specifiers; a "struct"/"enum" specifier, which resolves
|
|
973
|
+
# or defines its tag; or a single typedef name, an identifier bound to a
|
|
974
|
+
# type in the ordinary namespace. A typedef name is recognized only as the
|
|
975
|
+
# first (and only) type-specifier — once any type keyword has been seen, a
|
|
976
|
+
# following identifier is the declarator, so "int T" declares a variable T
|
|
977
|
+
# even where T names a type (the standard rule that keeps typedef names
|
|
978
|
+
# shadowable). "_Atomic" appears in both of the roles C11 gives it — a
|
|
979
|
+
# qualifier written among the other specifiers ("_Atomic int x", "int
|
|
980
|
+
# _Atomic x") and the parenthesized atomic-type-specifier
|
|
981
|
+
# ("_Atomic(int) x"), the two told apart by #atomic_type_specifier? — and
|
|
982
|
+
# #reject_unsupported_atomic_type settles which types it may name. Mixing
|
|
983
|
+
# categories ("unsigned struct", "enum T", ...) is a
|
|
984
|
+
# diagnostic; `allow_storage_class` is false in the contexts a storage
|
|
985
|
+
# class or a function specifier ("inline"/"_Noreturn") cannot appear (a
|
|
986
|
+
# member, a parameter, a type-name), where const/volatile are still
|
|
987
|
+
# admitted ("int f(const int x)",
|
|
988
|
+
# "sizeof(const int)"). `allow_init_attributes` opens the
|
|
989
|
+
# constructor/destructor attributes, which only a file-scope declaration
|
|
990
|
+
# can act on; every other context refuses them rather than dropping them.
|
|
991
|
+
# Returns [base_type, DeclSpecInfo].
|
|
992
|
+
def parse_declaration_specifiers(allow_storage_class:, allow_register: false,
|
|
993
|
+
allow_init_attributes: false)
|
|
994
|
+
start_tok = peek
|
|
995
|
+
specs = [] # collected integer/void keyword strings
|
|
996
|
+
composite = nil # a struct/enum/typedef-name Type (excludes `specs`)
|
|
997
|
+
attributes = [] # GNU attributes written among the specifiers (position a)
|
|
998
|
+
storage = nil # recorded storage class: :typedef / :static / :extern
|
|
999
|
+
storage_seen = false # any storage-class specifier (for the 6.7.1 check)
|
|
1000
|
+
const_p = false
|
|
1001
|
+
inline_p = false
|
|
1002
|
+
noreturn_p = false
|
|
1003
|
+
typedef_const = false # const folded in from a const typedef name
|
|
1004
|
+
atomic_tok = nil # the first "_Atomic" written as a qualifier, for its diagnostic
|
|
1005
|
+
alignas = nil # the strongest _Alignas the run asked for
|
|
1006
|
+
loop do
|
|
1007
|
+
tok = peek
|
|
1008
|
+
if tok.type == :keyword && STORAGE_CLASS_KEYWORDS.include?(tok.value)
|
|
1009
|
+
# A parameter declaration admits exactly one storage class, `register`
|
|
1010
|
+
# (6.7.6.3p2), and no other — so `allow_register` opens that one
|
|
1011
|
+
# keyword without letting typedef/static/extern/auto through.
|
|
1012
|
+
unless allow_storage_class || (allow_register && tok.value == "register")
|
|
1013
|
+
error_at(tok, "'#{tok.value}' is not allowed here")
|
|
1014
|
+
end
|
|
1015
|
+
error_at(tok, "multiple storage classes in declaration specifiers") if storage_seen
|
|
1016
|
+
storage_seen = true
|
|
1017
|
+
# register/auto have no effect in this subset: they are consumed but
|
|
1018
|
+
# left unrecorded, only typedef/static/extern reaching later stages.
|
|
1019
|
+
storage = tok.value.to_sym if %w[typedef static extern].include?(tok.value)
|
|
1020
|
+
advance
|
|
1021
|
+
elsif tok.keyword?("const")
|
|
1022
|
+
const_p = true
|
|
1023
|
+
advance
|
|
1024
|
+
elsif tok.keyword?("volatile")
|
|
1025
|
+
advance # accepted and ignored: M1 carries no qualified types
|
|
1026
|
+
elsif tok.keyword?("_Atomic")
|
|
1027
|
+
if atomic_type_specifier?
|
|
1028
|
+
# "_Atomic ( type-name )" — a type-specifier, so it excludes every
|
|
1029
|
+
# other one exactly as a struct or enum specifier does.
|
|
1030
|
+
error_at(tok, "two or more data types in declaration specifiers") if composite || !specs.empty?
|
|
1031
|
+
composite = parse_atomic_type_specifier
|
|
1032
|
+
else
|
|
1033
|
+
# "_Atomic" written as a bare type qualifier, before or after the
|
|
1034
|
+
# type it qualifies. The type it lands on is only known once the
|
|
1035
|
+
# whole run is read, so the token is kept for the check below.
|
|
1036
|
+
atomic_tok ||= tok
|
|
1037
|
+
advance
|
|
1038
|
+
end
|
|
1039
|
+
elsif tok.keyword?("_Alignas")
|
|
1040
|
+
# An alignment-specifier may sit anywhere among the specifiers
|
|
1041
|
+
# ("_Alignas(8) int x", "int _Alignas(8) x"). Where it may appear at
|
|
1042
|
+
# all is the declarator's business — a typedef, function, parameter,
|
|
1043
|
+
# bit-field or type-name refuses it (6.7.5p2) — so it is only
|
|
1044
|
+
# collected here, strongest request winning.
|
|
1045
|
+
alignas = stronger_alignas(alignas, parse_alignment_specifier)
|
|
1046
|
+
elsif tok.keyword?("inline")
|
|
1047
|
+
error_at(tok, "'inline' is not allowed here") unless allow_storage_class
|
|
1048
|
+
inline_p = true
|
|
1049
|
+
advance
|
|
1050
|
+
elsif tok.keyword?("_Noreturn")
|
|
1051
|
+
# The second function specifier (6.7.4): rides the same "may only
|
|
1052
|
+
# appear where 'inline' may" rule and, like it, is only an
|
|
1053
|
+
# optimization hint (see include/stdnoreturn.h) so it is recorded
|
|
1054
|
+
# only for the object-declarator check below and otherwise dropped.
|
|
1055
|
+
# C11 permits repeating a function specifier, so a second
|
|
1056
|
+
# "_Noreturn" here simply re-sets the same flag.
|
|
1057
|
+
error_at(tok, "'_Noreturn' is not allowed here") unless allow_storage_class
|
|
1058
|
+
noreturn_p = true
|
|
1059
|
+
advance
|
|
1060
|
+
elsif tok.type == :keyword && DECL_SPECIFIER_KEYWORDS.include?(tok.value)
|
|
1061
|
+
error_at(tok, "two or more data types in declaration specifiers") if composite
|
|
1062
|
+
specs << advance.value
|
|
1063
|
+
elsif tok.keyword?("struct") || tok.keyword?("union")
|
|
1064
|
+
error_at(tok, "two or more data types in declaration specifiers") if composite || !specs.empty?
|
|
1065
|
+
composite = parse_struct_or_union_specifier
|
|
1066
|
+
elsif tok.keyword?("enum")
|
|
1067
|
+
error_at(tok, "two or more data types in declaration specifiers") if composite || !specs.empty?
|
|
1068
|
+
composite = parse_enum_specifier
|
|
1069
|
+
elsif tok.keyword?("__attribute__")
|
|
1070
|
+
# A GNU attribute may open the specifier run or sit between
|
|
1071
|
+
# specifiers (position a): "__attribute__((const)) int f(...)",
|
|
1072
|
+
# "int __attribute__((unused)) x;". None affects an object's type, so
|
|
1073
|
+
# the collected attributes are only kept for the caller's sake (the
|
|
1074
|
+
# init attributes, where this context admits them at all).
|
|
1075
|
+
attributes.concat(
|
|
1076
|
+
parse_attribute_specifiers(init_attributes: allow_init_attributes ? :allow : :reject)
|
|
1077
|
+
)
|
|
1078
|
+
elsif composite.nil? && specs.empty? && tok.type == :ident && typedef_name?(tok.value)
|
|
1079
|
+
composite, typedef_const = lookup_ordinary(tok.value).value
|
|
1080
|
+
advance
|
|
1081
|
+
else
|
|
1082
|
+
break
|
|
1083
|
+
end
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1086
|
+
# A "const" typedef name ("typedef const int ci; ci x;") contributes its
|
|
1087
|
+
# const to the declaration, OR-ed with any const written here directly.
|
|
1088
|
+
spec_info = DeclSpecInfo.new(storage: storage, const: const_p || typedef_const,
|
|
1089
|
+
inline_p: inline_p, noreturn_p: noreturn_p, attributes: attributes,
|
|
1090
|
+
alignas: alignas)
|
|
1091
|
+
base = if composite
|
|
1092
|
+
composite
|
|
1093
|
+
else
|
|
1094
|
+
error_at(start_tok, "expected type specifier") if specs.empty?
|
|
1095
|
+
normalize_type_specifiers(specs, start_tok)
|
|
1096
|
+
end
|
|
1097
|
+
# A qualifier-spelled "_Atomic" qualifies whatever the run resolved to,
|
|
1098
|
+
# so its admissibility is settled here, once that type is known. The
|
|
1099
|
+
# parenthesized spelling checked its own operand in
|
|
1100
|
+
# #parse_atomic_type_specifier, where the type-name's own token locates
|
|
1101
|
+
# the diagnostic.
|
|
1102
|
+
reject_unsupported_atomic_type(base, atomic_tok) if atomic_tok
|
|
1103
|
+
[base, spec_info]
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
# alignment-specifier = "_Alignas" "(" (type-name | constant-expression) ")"
|
|
1107
|
+
# (6.7.5). The type-name spelling asks for that type's own boundary, the
|
|
1108
|
+
# expression spelling for the folded value; the two are told apart exactly
|
|
1109
|
+
# as sizeof tells its operands apart, by whether a type-specifier opens the
|
|
1110
|
+
# parentheses. A request of zero "has no effect" (6.7.5p3) and so yields
|
|
1111
|
+
# nil, and any other non-power-of-two is a constraint violation gcc words
|
|
1112
|
+
# the same way an aligned(N) attribute's is. Returns an Alignas or nil.
|
|
1113
|
+
def parse_alignment_specifier
|
|
1114
|
+
alignas_tok = advance # "_Alignas"
|
|
1115
|
+
expect_punct("(")
|
|
1116
|
+
value = if type_specifier?(peek)
|
|
1117
|
+
alignment_of_type_name(alignas_tok)
|
|
1118
|
+
else
|
|
1119
|
+
evaluate_constant_expression(parse_conditional_expression,
|
|
1120
|
+
"'_Alignas' operand is not an integer constant",
|
|
1121
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
1122
|
+
end
|
|
1123
|
+
expect_punct(")")
|
|
1124
|
+
return nil if value.zero?
|
|
1125
|
+
|
|
1126
|
+
unless value.positive? && (value & (value - 1)).zero?
|
|
1127
|
+
error_at(alignas_tok, "requested alignment '#{value}' is not a positive power of 2")
|
|
1128
|
+
end
|
|
1129
|
+
Alignas.new(alignment: value, token: alignas_tok)
|
|
1130
|
+
end
|
|
1131
|
+
|
|
1132
|
+
# The boundary the "_Alignas ( type-name )" spelling asks for: the written
|
|
1133
|
+
# type's own alignment, read here at parse time (the expression spelling's
|
|
1134
|
+
# value is available just as early, so both reach the declarator as a plain
|
|
1135
|
+
# Integer). A type with no alignment to speak of — void, a function, or an
|
|
1136
|
+
# aggregate whose body this unit has not seen — is rejected the way
|
|
1137
|
+
# _Alignof rejects the same operands rather than reaching Type's "incomplete
|
|
1138
|
+
# struct has no alignment" guard.
|
|
1139
|
+
def alignment_of_type_name(alignas_tok)
|
|
1140
|
+
type = parse_type_name
|
|
1141
|
+
unless alignment_known?(type)
|
|
1142
|
+
error_at(alignas_tok, "invalid application of '_Alignas' to an incomplete type")
|
|
1143
|
+
end
|
|
1144
|
+
type.alignment
|
|
1145
|
+
end
|
|
1146
|
+
|
|
1147
|
+
# Whether `type` has a boundary that can be read right now. Void and a
|
|
1148
|
+
# function type have none at all, and an aggregate this unit has not
|
|
1149
|
+
# defined (directly or as an array's element) has none *yet* — asking any
|
|
1150
|
+
# of them for #alignment would trip Type's own guard.
|
|
1151
|
+
def alignment_known?(type)
|
|
1152
|
+
return false if type.void? || type.function?
|
|
1153
|
+
return type.complete? if type.struct?
|
|
1154
|
+
return alignment_known?(type.element) if type.array?
|
|
1155
|
+
|
|
1156
|
+
true
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
# The stronger of two alignment requests from one specifier run, either of
|
|
1160
|
+
# which may be nil (no request). The larger boundary wins; on a tie the
|
|
1161
|
+
# earlier token is kept, so a diagnostic points at the first spelling.
|
|
1162
|
+
def stronger_alignas(current, addition)
|
|
1163
|
+
return current if addition.nil?
|
|
1164
|
+
return addition if current.nil?
|
|
1165
|
+
|
|
1166
|
+
addition.alignment > current.alignment ? addition : current
|
|
1167
|
+
end
|
|
1168
|
+
|
|
1169
|
+
# Rejects an _Alignas written where 6.7.5p2 forbids one, naming the
|
|
1170
|
+
# construct that refused it ("typedef", "parameter 'x'", ...). gcc's
|
|
1171
|
+
# wording, which names the same five constructs.
|
|
1172
|
+
def reject_alignas(alignas, what)
|
|
1173
|
+
return if alignas.nil?
|
|
1174
|
+
|
|
1175
|
+
error_at(alignas.token, "alignment specified for #{what}")
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
# Enforces 6.7.5p4: an _Alignas may raise a declaration's boundary but
|
|
1179
|
+
# never lower it, so a request weaker than the declared type's own
|
|
1180
|
+
# alignment is a constraint violation rather than a silently ignored one.
|
|
1181
|
+
# Returns the requested boundary (an Integer), or nil when nothing was
|
|
1182
|
+
# asked for. `what` names the declarator in the diagnostic (gcc's wording:
|
|
1183
|
+
# "'x'" for a named one, "unnamed field" for an anonymous member).
|
|
1184
|
+
def alignas_boundary(alignas, type, what)
|
|
1185
|
+
return nil if alignas.nil?
|
|
1186
|
+
|
|
1187
|
+
# An incomplete declared type has no boundary to compare against; such a
|
|
1188
|
+
# declarator is refused for being incomplete downstream, so the check is
|
|
1189
|
+
# skipped rather than tripping Type's guard here.
|
|
1190
|
+
if alignment_known?(type) && alignas.alignment < type.alignment
|
|
1191
|
+
error_at(alignas.token, "'_Alignas' specifiers cannot reduce alignment of #{what}")
|
|
1192
|
+
end
|
|
1193
|
+
alignas.alignment
|
|
1194
|
+
end
|
|
1195
|
+
|
|
1196
|
+
# Whether the "_Atomic" at `peek` opens the parenthesized
|
|
1197
|
+
# atomic-type-specifier "_Atomic ( type-name )" rather than standing as a
|
|
1198
|
+
# bare type qualifier. C11 6.7.2.4 spells the two identically up to the
|
|
1199
|
+
# "(", and the grammar separates them by what follows it: a type-name
|
|
1200
|
+
# makes it the specifier, anything else leaves the "_Atomic" a qualifier
|
|
1201
|
+
# of the surrounding declaration ("_Atomic (*p)" qualifies the pointee).
|
|
1202
|
+
def atomic_type_specifier?
|
|
1203
|
+
peek_ahead(1)&.punct?("(") && !peek_ahead(2).nil? && type_specifier?(peek_ahead(2))
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
# atomic-type-specifier = "_Atomic" "(" type-name ")" (6.7.2.4), the
|
|
1207
|
+
# "_Atomic" not yet consumed. The type-name is an ordinary one, so it may
|
|
1208
|
+
# itself be a pointer or a typedef name ("_Atomic(const upb_ArenaRef *)"
|
|
1209
|
+
# is how upb spells one), and it goes through the same admissibility check
|
|
1210
|
+
# the qualifier spelling does.
|
|
1211
|
+
def parse_atomic_type_specifier
|
|
1212
|
+
keyword_tok = advance # "_Atomic"
|
|
1213
|
+
# The type-name nests a full declarator, which may nest further
|
|
1214
|
+
# specifiers, so the shared recursion counter bounds it here just as it
|
|
1215
|
+
# bounds a struct body.
|
|
1216
|
+
with_nesting_guard(keyword_tok, "_Atomic type specifier") do
|
|
1217
|
+
expect_punct("(")
|
|
1218
|
+
type_tok = peek
|
|
1219
|
+
type = parse_type_name
|
|
1220
|
+
expect_punct(")")
|
|
1221
|
+
reject_unsupported_atomic_type(type, type_tok)
|
|
1222
|
+
type
|
|
1223
|
+
end
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
# The object widths a plain machine access is indivisible at on both
|
|
1227
|
+
# targets: one naturally aligned load or store instruction covers each of
|
|
1228
|
+
# them, and #reject_unsupported_atomic_type admits an _Atomic type only at
|
|
1229
|
+
# these widths. Wider than 8 there is no such instruction on either
|
|
1230
|
+
# baseline ISA rubycc emits for (x86-64 without cmpxchg16b, armv8-a
|
|
1231
|
+
# without LSE), so an _Atomic 16-byte object would be a plainly
|
|
1232
|
+
# non-atomic one.
|
|
1233
|
+
ATOMIC_TYPE_WIDTHS = [1, 2, 4, 8].freeze
|
|
1234
|
+
|
|
1235
|
+
# Rejects an `_Atomic T` this subset cannot honestly represent.
|
|
1236
|
+
#
|
|
1237
|
+
# rubycc compiles `_Atomic T` as plain `T`: same layout, same ABI. That is
|
|
1238
|
+
# a measurement, not an assumption — gcc's sizeof and _Alignof for
|
|
1239
|
+
# `_Atomic(T)` equal those of `T` for every integer, floating and pointer
|
|
1240
|
+
# type (verified type by type in test/test_header_abi.rb's STDATOMIC
|
|
1241
|
+
# spec) — but it holds only for the types listed there. It fails for an
|
|
1242
|
+
# aggregate: gcc raises a power-of-two-sized struct's alignment to its
|
|
1243
|
+
# size under _Atomic (measured: a 2-byte struct goes from _Alignof 1 to 2,
|
|
1244
|
+
# a 16-byte one from 8 to 16), and an aggregate of any other size is not
|
|
1245
|
+
# lock-free at all, so gcc routes it through libatomic's locked path.
|
|
1246
|
+
# Compiling either as a plain struct would silently drop both the layout
|
|
1247
|
+
# and the atomicity, so an aggregate is refused here instead.
|
|
1248
|
+
#
|
|
1249
|
+
# The same reasoning bounds the widths: 16-byte scalars (`__int128`, and
|
|
1250
|
+
# `long double` on a target that has one) do share `T`'s layout, but no
|
|
1251
|
+
# single instruction accesses them on the ISA baselines rubycc emits, so
|
|
1252
|
+
# they are refused too. C11 6.7.2.4p3 already forbids `_Atomic` on an
|
|
1253
|
+
# array or a function type, and gcc diagnoses the array form
|
|
1254
|
+
# ("'_Atomic'-qualified array type", measured), so those get their own
|
|
1255
|
+
# message.
|
|
1256
|
+
def reject_unsupported_atomic_type(type, tok)
|
|
1257
|
+
if type.array? || type.function?
|
|
1258
|
+
error_at(tok, "'_Atomic' cannot be applied to #{type.array? ? "an array" : "a function"} type")
|
|
1259
|
+
end
|
|
1260
|
+
# "_Atomic void" names no object at all — the only way to write it is
|
|
1261
|
+
# "_Atomic void *", where the qualifier lands on a pointee nothing ever
|
|
1262
|
+
# loads — so gcc accepts it (measured) and so does this, leaving the
|
|
1263
|
+
# existing void-object rules to refuse a real "_Atomic void v;".
|
|
1264
|
+
return if type.void?
|
|
1265
|
+
return if (type.arithmetic? || type.pointer?) && ATOMIC_TYPE_WIDTHS.include?(type.size)
|
|
1266
|
+
|
|
1267
|
+
error_at(tok, "'_Atomic' is not supported on '#{type}': this subset applies it only to " \
|
|
1268
|
+
"integer, floating and pointer types of #{ATOMIC_TYPE_WIDTHS.join(", ")} bytes")
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
# Collapses a multiset of integer type-specifier keywords (in any order:
|
|
1272
|
+
# "unsigned long", "long unsigned int", "long long int", ...) into a
|
|
1273
|
+
# single Rubycc::Type per 6.7.2. `void` and `_Bool` stand alone;
|
|
1274
|
+
# signed/unsigned choose the signedness; short/long (up to two longs, LP64
|
|
1275
|
+
# folding "long long" onto "long") and int/char choose the width, with a
|
|
1276
|
+
# bare "signed"/"unsigned" meaning int. Every ill-formed combination
|
|
1277
|
+
# ("short char", "long short", "signed unsigned", ...) is a diagnostic.
|
|
1278
|
+
def normalize_type_specifiers(specs, tok)
|
|
1279
|
+
counts = Hash.new(0)
|
|
1280
|
+
specs.each { |s| counts[s] += 1 }
|
|
1281
|
+
|
|
1282
|
+
return normalize_standalone(Type::Void, "void", specs, tok) if counts["void"].positive?
|
|
1283
|
+
return normalize_standalone(Type::Bool, "_Bool", specs, tok) if counts["_Bool"].positive?
|
|
1284
|
+
return normalize_standalone(Type::Float, "float", specs, tok) if counts["float"].positive?
|
|
1285
|
+
# `double` stands alone or pairs with a single `long` ("long double",
|
|
1286
|
+
# treated as `double` here); any other keyword, a second `double` or a
|
|
1287
|
+
# second `long` is an ill-formed combination.
|
|
1288
|
+
if counts["double"].positive?
|
|
1289
|
+
non_long = specs.reject { |s| s == "long" }
|
|
1290
|
+
unless non_long == ["double"] && counts["long"] <= 1
|
|
1291
|
+
error_at(tok, "cannot combine 'double' with other type specifiers")
|
|
1292
|
+
end
|
|
1293
|
+
return Type::Double
|
|
1294
|
+
end
|
|
1295
|
+
|
|
1296
|
+
# `__int128` (a GNU keyword) stands alone or pairs with a single
|
|
1297
|
+
# `signed`/`unsigned`, in any order ("unsigned __int128", "__int128
|
|
1298
|
+
# unsigned", "signed __int128"); no width keyword may join it. Its
|
|
1299
|
+
# signedness follows the same rule the standard integers use — a bare
|
|
1300
|
+
# `__int128` is signed, `unsigned` makes it unsigned.
|
|
1301
|
+
if counts["__int128"].positive?
|
|
1302
|
+
error_at(tok, "duplicate '__int128'") if counts["__int128"] > 1
|
|
1303
|
+
non_sign = specs.reject { |s| s == "signed" || s == "unsigned" }
|
|
1304
|
+
unless non_sign == ["__int128"]
|
|
1305
|
+
error_at(tok, "cannot combine '__int128' with other type specifiers")
|
|
1306
|
+
end
|
|
1307
|
+
if counts["signed"].positive? && counts["unsigned"].positive?
|
|
1308
|
+
error_at(tok, "both 'signed' and 'unsigned' in declaration specifiers")
|
|
1309
|
+
end
|
|
1310
|
+
return counts["unsigned"].positive? ? Type::UInt128 : Type::Int128
|
|
1311
|
+
end
|
|
1312
|
+
|
|
1313
|
+
signed = counts["signed"].positive?
|
|
1314
|
+
unsigned = counts["unsigned"].positive?
|
|
1315
|
+
short = counts["short"].positive?
|
|
1316
|
+
long = counts["long"]
|
|
1317
|
+
%w[signed unsigned short int char].each do |kw|
|
|
1318
|
+
error_at(tok, "duplicate '#{kw}'") if counts[kw] > 1
|
|
1319
|
+
end
|
|
1320
|
+
error_at(tok, "both 'signed' and 'unsigned' in declaration specifiers") if signed && unsigned
|
|
1321
|
+
error_at(tok, "more than two 'long's in declaration specifiers") if long > 2
|
|
1322
|
+
|
|
1323
|
+
if counts["char"].positive?
|
|
1324
|
+
if short || long.positive? || counts["int"].positive?
|
|
1325
|
+
error_at(tok, "both 'char' and a size specifier in declaration specifiers")
|
|
1326
|
+
end
|
|
1327
|
+
# The three character types are distinct: "unsigned char" and "signed
|
|
1328
|
+
# char" name their own fixed-signedness types, while a bare "char"
|
|
1329
|
+
# takes the target's plain-char instance (see #initialize).
|
|
1330
|
+
return Type::UChar if unsigned
|
|
1331
|
+
return Type::SChar if signed
|
|
1332
|
+
|
|
1333
|
+
return @plain_char
|
|
1334
|
+
end
|
|
1335
|
+
|
|
1336
|
+
error_at(tok, "both 'short' and 'long' in declaration specifiers") if short && long.positive?
|
|
1337
|
+
|
|
1338
|
+
if short
|
|
1339
|
+
unsigned ? Type::UShort : Type::Short
|
|
1340
|
+
elsif long.positive?
|
|
1341
|
+
unsigned ? Type::ULong : Type::Long
|
|
1342
|
+
else
|
|
1343
|
+
unsigned ? Type::UInt : Type::Int
|
|
1344
|
+
end
|
|
1345
|
+
end
|
|
1346
|
+
|
|
1347
|
+
# `void` and `_Bool` cannot combine with any other type-specifier keyword;
|
|
1348
|
+
# each must be the whole list.
|
|
1349
|
+
def normalize_standalone(type, keyword, specs, tok)
|
|
1350
|
+
unless specs == [keyword]
|
|
1351
|
+
error_at(tok, "cannot combine '#{keyword}' with other type specifiers")
|
|
1352
|
+
end
|
|
1353
|
+
type
|
|
1354
|
+
end
|
|
1355
|
+
|
|
1356
|
+
# struct-or-union-specifier: a "struct" or "union" keyword (the two differ
|
|
1357
|
+
# only in the aggregate's `kind` and thus its layout), an optional tag,
|
|
1358
|
+
# and an optional "{ ... }" body. Three shapes result:
|
|
1359
|
+
# * "struct tag { ... }" / "struct { ... }" — a definition; the tagged
|
|
1360
|
+
# one is registered (or completed) in the current tag scope, an
|
|
1361
|
+
# anonymous one is a fresh unnamed type. #parse_struct_body lays it out.
|
|
1362
|
+
# * "struct tag" — a reference; resolved through the tag scopes, or, when
|
|
1363
|
+
# the tag is unknown, forward-declared as an incomplete aggregate in
|
|
1364
|
+
# the current scope (so "struct node;" and a pointer to a
|
|
1365
|
+
# not-yet-defined tag both work — the union spellings behave alike).
|
|
1366
|
+
def parse_struct_or_union_specifier
|
|
1367
|
+
keyword_tok = advance # "struct" or "union"
|
|
1368
|
+
kind = keyword_tok.value == "union" ? :union : :struct
|
|
1369
|
+
# A struct/union body may hold members whose own type is a further
|
|
1370
|
+
# struct/union definition ("struct { struct { ... } a; } b;"), which
|
|
1371
|
+
# recurses back here through #parse_struct_body; guarding at the keyword
|
|
1372
|
+
# bounds that nesting on the shared counter.
|
|
1373
|
+
with_nesting_guard(keyword_tok, "type definition") do
|
|
1374
|
+
# A GNU attribute may sit right after the keyword, before the tag or "{"
|
|
1375
|
+
# (position b): "struct __attribute__((aligned(8))) S { ... }". Only its
|
|
1376
|
+
# aligned/packed carry layout meaning, and only on a definition.
|
|
1377
|
+
leading_attrs = parse_attribute_specifiers
|
|
1378
|
+
tag_tok = peek.type == :ident ? advance : nil
|
|
1379
|
+
tag = tag_tok&.value
|
|
1380
|
+
|
|
1381
|
+
if peek.punct?("{")
|
|
1382
|
+
struct_type = tag ? define_struct_tag(tag, kind, keyword_tok) : Type::StructType.new(nil, kind: kind)
|
|
1383
|
+
raw_members = parse_struct_body(kind, keyword_tok)
|
|
1384
|
+
# A second attribute run may follow the closing "}" (position c),
|
|
1385
|
+
# before the declarator list or ";"; the two runs combine on the layout.
|
|
1386
|
+
trailing_attrs = parse_attribute_specifiers
|
|
1387
|
+
aligned, packed = resolve_layout_attributes(leading_attrs + trailing_attrs)
|
|
1388
|
+
# A packed aggregate that also carries a bit-field would need bit-level
|
|
1389
|
+
# packing across storage units this subset does not model, so the
|
|
1390
|
+
# combination is rejected rather than laid out wrongly (Step 28 C2).
|
|
1391
|
+
if packed && raw_members.any? { |triple| triple[2] }
|
|
1392
|
+
error_at(keyword_tok, "packed bit-fields are not supported")
|
|
1393
|
+
end
|
|
1394
|
+
struct_type.define(raw_members, packed: packed, aligned: aligned,
|
|
1395
|
+
unnamed_bitfields_align: @unnamed_bitfields_align)
|
|
1396
|
+
struct_type
|
|
1397
|
+
elsif tag
|
|
1398
|
+
reference_struct_tag(tag, kind, tag_tok)
|
|
1399
|
+
else
|
|
1400
|
+
error_at(keyword_tok, "expected identifier or '{' after '#{keyword_tok.value}'")
|
|
1401
|
+
end
|
|
1402
|
+
end
|
|
1403
|
+
end
|
|
1404
|
+
|
|
1405
|
+
# Consumes a run of GNU __attribute__ specifiers (each
|
|
1406
|
+
# "__attribute__ ( ( attribute-list ) )", ISO C23's attribute-specifier
|
|
1407
|
+
# sequence spelled the GNU way), returning the collected Attributes for the
|
|
1408
|
+
# caller to interpret. A caller that gives attributes no meaning (most
|
|
1409
|
+
# positions) simply discards the result. `__attribute__` is a keyword here,
|
|
1410
|
+
# so it never collides with an ordinary identifier. Nothing is consumed
|
|
1411
|
+
# when no attribute is present.
|
|
1412
|
+
#
|
|
1413
|
+
# `init_attributes` guards the one attribute family whose absence cannot be
|
|
1414
|
+
# noticed: a discarded constructor/destructor leaves a program that links
|
|
1415
|
+
# and runs but never initializes itself. It defaults to :reject, so a
|
|
1416
|
+
# position not explicitly taught to claim them diagnoses instead of
|
|
1417
|
+
# dropping; only the file-scope declaration positions pass :allow.
|
|
1418
|
+
def parse_attribute_specifiers(init_attributes: :reject)
|
|
1419
|
+
attributes = []
|
|
1420
|
+
while peek.keyword?("__attribute__")
|
|
1421
|
+
advance # "__attribute__"
|
|
1422
|
+
expect_punct("(")
|
|
1423
|
+
expect_punct("(")
|
|
1424
|
+
parse_attribute_list(attributes)
|
|
1425
|
+
expect_punct(")")
|
|
1426
|
+
expect_punct(")")
|
|
1427
|
+
end
|
|
1428
|
+
reject_init_attributes(attributes) unless init_attributes == :allow
|
|
1429
|
+
attributes
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
# Refuses a constructor/destructor attribute written where this parser
|
|
1433
|
+
# cannot act on it (a struct/union specifier, a member, a parameter, a
|
|
1434
|
+
# type-name, a typedef name, a block-scope declaration, a file-scope
|
|
1435
|
+
# object). Any of those would otherwise be dropped without a trace.
|
|
1436
|
+
def reject_init_attributes(attributes)
|
|
1437
|
+
attributes.each do |attr|
|
|
1438
|
+
next unless INIT_ATTRIBUTES.key?(attr.name)
|
|
1439
|
+
|
|
1440
|
+
error_at(attr.token,
|
|
1441
|
+
"'#{attr.name}' attribute is only accepted on a file-scope function declaration")
|
|
1442
|
+
end
|
|
1443
|
+
end
|
|
1444
|
+
|
|
1445
|
+
# Records the .init_array / .fini_array registration `attributes` ask for
|
|
1446
|
+
# under the function's name. Both a prototype and the definition may carry
|
|
1447
|
+
# them, in either order — gcc accepts "static void f(void)
|
|
1448
|
+
# __attribute__((constructor)); static void f(void) { }" and the reverse —
|
|
1449
|
+
# so the table is keyed by name and matched against the definitions once
|
|
1450
|
+
# the whole unit is parsed (see AST::Program#init_attributes). A name that
|
|
1451
|
+
# is only declared here registers nothing, since the array slot belongs to
|
|
1452
|
+
# the object that defines the function; gcc emits nothing for it either.
|
|
1453
|
+
#
|
|
1454
|
+
# Repeating an attribute is fine as long as it asks for the same priority.
|
|
1455
|
+
# gcc silently keeps the first of two conflicting ones; that quietly runs
|
|
1456
|
+
# the initializers in an order the source did not ask for, so it is a
|
|
1457
|
+
# diagnostic here instead.
|
|
1458
|
+
def register_init_attributes(name, attributes)
|
|
1459
|
+
attributes.each do |attr|
|
|
1460
|
+
kind = INIT_ATTRIBUTES[attr.name]
|
|
1461
|
+
next unless kind
|
|
1462
|
+
|
|
1463
|
+
priority = attr.argument || DEFAULT_INIT_PRIORITY
|
|
1464
|
+
record = @init_attributes[name] ||= AST::InitAttributes.new(constructor: nil, destructor: nil)
|
|
1465
|
+
previous = record.public_send(kind)
|
|
1466
|
+
if previous && previous != priority
|
|
1467
|
+
error_at(attr.token, "conflicting '#{attr.name}' priorities for '#{name}' " \
|
|
1468
|
+
"(#{previous} and #{priority})")
|
|
1469
|
+
end
|
|
1470
|
+
@init_attributes[name] = record.with(kind => priority)
|
|
1471
|
+
end
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
def register_visibility_attributes(name, attributes)
|
|
1475
|
+
attributes.each do |attribute|
|
|
1476
|
+
next unless attribute.name == "visibility"
|
|
1477
|
+
|
|
1478
|
+
@visibility_attributes[name] = attribute.argument
|
|
1479
|
+
end
|
|
1480
|
+
end
|
|
1481
|
+
|
|
1482
|
+
# attribute-list: a comma-separated sequence of attributes, possibly empty
|
|
1483
|
+
# ("__attribute__(())") and admitting empty elements ("__attribute__((,))",
|
|
1484
|
+
# which gcc allows), each appended to `attributes` as a [name, argument]
|
|
1485
|
+
# pair (argument is the folded aligned value, or nil).
|
|
1486
|
+
def parse_attribute_list(attributes)
|
|
1487
|
+
loop do
|
|
1488
|
+
parse_attribute(attributes) unless peek.punct?(",") || peek.punct?(")")
|
|
1489
|
+
break unless peek.punct?(",")
|
|
1490
|
+
|
|
1491
|
+
advance # ","
|
|
1492
|
+
end
|
|
1493
|
+
end
|
|
1494
|
+
|
|
1495
|
+
# One attribute: an attribute-token (an identifier, or a keyword — gcc
|
|
1496
|
+
# spells several attributes with keywords, e.g. "__attribute__((const))")
|
|
1497
|
+
# optionally followed by a parenthesized argument clause. Its name is
|
|
1498
|
+
# normalized (see #normalize_attribute_name) and paired with the folded
|
|
1499
|
+
# argument value #parse_attribute_arguments returns (meaningful only for
|
|
1500
|
+
# "aligned" and the init attributes; nil otherwise).
|
|
1501
|
+
def parse_attribute(attributes)
|
|
1502
|
+
name_tok = peek
|
|
1503
|
+
unless name_tok.type == :ident || name_tok.type == :keyword
|
|
1504
|
+
error_at(name_tok, "expected attribute name")
|
|
1505
|
+
end
|
|
1506
|
+
advance
|
|
1507
|
+
name = normalize_attribute_name(name_tok.value)
|
|
1508
|
+
argument = peek.punct?("(") ? parse_attribute_arguments(name) : nil
|
|
1509
|
+
attributes << Attribute.new(name: name, argument: argument, token: name_tok)
|
|
1510
|
+
end
|
|
1511
|
+
|
|
1512
|
+
# An attribute's parenthesized argument clause. "aligned(N)" and
|
|
1513
|
+
# "constructor(N)" / "destructor(N)" each carry a single integer
|
|
1514
|
+
# constant-expression that must be folded and range-checked here, so they
|
|
1515
|
+
# are parsed for real; every other attribute's arguments (bare identifiers,
|
|
1516
|
+
# string literals, comma-separated integers such as "format(printf, 1, 2)")
|
|
1517
|
+
# are accepted and discarded, so its balanced parentheses are skipped
|
|
1518
|
+
# verbatim. Returns the folded value, or nil for any other attribute.
|
|
1519
|
+
def parse_attribute_arguments(name)
|
|
1520
|
+
return parse_aligned_argument if name == "aligned"
|
|
1521
|
+
return parse_init_priority_argument(name) if INIT_ATTRIBUTES.key?(name)
|
|
1522
|
+
return parse_visibility_argument if name == "visibility"
|
|
1523
|
+
|
|
1524
|
+
skip_balanced_parentheses && nil
|
|
1525
|
+
end
|
|
1526
|
+
|
|
1527
|
+
def parse_visibility_argument
|
|
1528
|
+
advance # "("
|
|
1529
|
+
tok = peek
|
|
1530
|
+
unless %i[string ident keyword].include?(tok.type)
|
|
1531
|
+
error_at(tok, "visibility attribute requires a string or identifier argument")
|
|
1532
|
+
end
|
|
1533
|
+
value = tok.value.to_s
|
|
1534
|
+
advance
|
|
1535
|
+
expect_punct(")")
|
|
1536
|
+
unless %w[default hidden internal protected].include?(value)
|
|
1537
|
+
error_at(tok, "unknown visibility '#{value}'")
|
|
1538
|
+
end
|
|
1539
|
+
value.to_sym
|
|
1540
|
+
end
|
|
1541
|
+
|
|
1542
|
+
def parse_aligned_argument
|
|
1543
|
+
expr = parse_parenthesized_constant
|
|
1544
|
+
value = evaluate_constant_expression(expr, "'aligned' attribute argument is not an integer constant",
|
|
1545
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
1546
|
+
unless value.positive? && (value & (value - 1)).zero?
|
|
1547
|
+
error_at(expr.token, "requested alignment '#{value}' is not a positive power of 2")
|
|
1548
|
+
end
|
|
1549
|
+
value
|
|
1550
|
+
end
|
|
1551
|
+
|
|
1552
|
+
# The run-order number of a constructor/destructor. The window and its
|
|
1553
|
+
# wording follow gcc's measured behavior (see MAX_INIT_PRIORITY); the
|
|
1554
|
+
# 0..100 range gcc reserves for the implementation is accepted here, since
|
|
1555
|
+
# gcc only warns about it and this compiler has no warning channel.
|
|
1556
|
+
def parse_init_priority_argument(name)
|
|
1557
|
+
expr = parse_parenthesized_constant
|
|
1558
|
+
value = evaluate_constant_expression(expr, "'#{name}' attribute argument is not an integer constant",
|
|
1559
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
1560
|
+
unless value.between?(MIN_INIT_PRIORITY, MAX_INIT_PRIORITY)
|
|
1561
|
+
error_at(expr.token, "#{name} priorities must be integers from " \
|
|
1562
|
+
"#{MIN_INIT_PRIORITY} to #{MAX_INIT_PRIORITY} inclusive")
|
|
1563
|
+
end
|
|
1564
|
+
value
|
|
1565
|
+
end
|
|
1566
|
+
|
|
1567
|
+
# "( constant-expression )" — an attribute argument clause holding exactly
|
|
1568
|
+
# one expression, returned unfolded for the caller to evaluate under its
|
|
1569
|
+
# own diagnostic.
|
|
1570
|
+
def parse_parenthesized_constant
|
|
1571
|
+
advance # "("
|
|
1572
|
+
expr = parse_conditional_expression
|
|
1573
|
+
expect_punct(")")
|
|
1574
|
+
expr
|
|
1575
|
+
end
|
|
1576
|
+
|
|
1577
|
+
# Skips a balanced-parenthesis token run (an attribute argument clause we
|
|
1578
|
+
# give no meaning), from the opening "(" through its matching ")". Returns
|
|
1579
|
+
# true so #parse_attribute_arguments can chain it with "&& nil".
|
|
1580
|
+
def skip_balanced_parentheses
|
|
1581
|
+
expect_punct("(")
|
|
1582
|
+
depth = 1
|
|
1583
|
+
until depth.zero?
|
|
1584
|
+
tok = peek
|
|
1585
|
+
error_at(tok, "unterminated attribute argument list") if tok.eof?
|
|
1586
|
+
depth += 1 if tok.punct?("(")
|
|
1587
|
+
depth -= 1 if tok.punct?(")")
|
|
1588
|
+
advance
|
|
1589
|
+
end
|
|
1590
|
+
true
|
|
1591
|
+
end
|
|
1592
|
+
|
|
1593
|
+
# Normalizes a GNU attribute name: a "__name__" spelling collapses to
|
|
1594
|
+
# "name" — exactly one leading and one trailing "__" stripped when both are
|
|
1595
|
+
# present — so "__aligned__" and "aligned" name the same attribute. A name
|
|
1596
|
+
# underscored on only one side, or too short to carry both pairs, is left
|
|
1597
|
+
# as written.
|
|
1598
|
+
def normalize_attribute_name(name)
|
|
1599
|
+
if name.start_with?("__") && name.end_with?("__") && name.length > 4
|
|
1600
|
+
name[2..-3]
|
|
1601
|
+
else
|
|
1602
|
+
name
|
|
1603
|
+
end
|
|
1604
|
+
end
|
|
1605
|
+
|
|
1606
|
+
# Reduces a struct/union specifier's collected attributes to the layout
|
|
1607
|
+
# override StructType#define takes: [aligned, packed]. `aligned` is the
|
|
1608
|
+
# largest power-of-two boundary any "aligned" attribute asked for (a bare
|
|
1609
|
+
# "aligned" with no argument meaning BIGGEST_ALIGNMENT), or nil when none
|
|
1610
|
+
# appeared; `packed` is whether any "packed" attribute was present. Every
|
|
1611
|
+
# unrecognized attribute has already been discarded, so only these two
|
|
1612
|
+
# remain to interpret.
|
|
1613
|
+
def resolve_layout_attributes(attributes)
|
|
1614
|
+
aligned = nil
|
|
1615
|
+
packed = false
|
|
1616
|
+
attributes.each do |attr|
|
|
1617
|
+
case attr.name
|
|
1618
|
+
when "aligned"
|
|
1619
|
+
value = attr.argument || BIGGEST_ALIGNMENT
|
|
1620
|
+
aligned = value if aligned.nil? || value > aligned
|
|
1621
|
+
when "packed"
|
|
1622
|
+
packed = true
|
|
1623
|
+
end
|
|
1624
|
+
end
|
|
1625
|
+
[aligned, packed]
|
|
1626
|
+
end
|
|
1627
|
+
|
|
1628
|
+
# Consumes any run of leading "__extension__" markers (a GNU keyword that
|
|
1629
|
+
# only silences pedantic diagnostics). Used wherever a declaration may be
|
|
1630
|
+
# prefixed by one; the unary-expression prefix form is handled separately
|
|
1631
|
+
# in #parse_cast_expression.
|
|
1632
|
+
def skip_extension_markers
|
|
1633
|
+
advance while peek.keyword?("__extension__")
|
|
1634
|
+
end
|
|
1635
|
+
|
|
1636
|
+
# Whether the token `offset` tokens ahead of a run of "__extension__"
|
|
1637
|
+
# markers opens a declaration, so block-item and for-init can tell a
|
|
1638
|
+
# "__extension__ int x;" declaration from a "__extension__ expr;"
|
|
1639
|
+
# expression statement without committing to either first.
|
|
1640
|
+
def extension_prefixes_declaration?
|
|
1641
|
+
return false unless peek.keyword?("__extension__")
|
|
1642
|
+
|
|
1643
|
+
offset = 1
|
|
1644
|
+
offset += 1 while peek_ahead(offset)&.keyword?("__extension__")
|
|
1645
|
+
following = peek_ahead(offset)
|
|
1646
|
+
!following.nil? && (type_specifier?(following) || following.keyword?("_Static_assert"))
|
|
1647
|
+
end
|
|
1648
|
+
|
|
1649
|
+
# enum-specifier (6.7.2.2): "enum identifier? { enumerator-list ,? }"
|
|
1650
|
+
# defines the enumeration (registering the tag, if named, and every
|
|
1651
|
+
# enumerator as an int constant in the current ordinary scope), while
|
|
1652
|
+
# "enum identifier" references a previously defined enum tag. Either way an
|
|
1653
|
+
# enum object is an int, so the specifier resolves to Type::Int and no
|
|
1654
|
+
# dedicated enum type exists. Unlike a struct, an enum has no incomplete
|
|
1655
|
+
# form: a reference to a tag with no visible definition is an error on the
|
|
1656
|
+
# spot, since an int-sized object cannot be laid out from an unknown set of
|
|
1657
|
+
# constants.
|
|
1658
|
+
def parse_enum_specifier
|
|
1659
|
+
enum_tok = advance # "enum"
|
|
1660
|
+
tag_tok = peek.type == :ident ? advance : nil
|
|
1661
|
+
tag = tag_tok&.value
|
|
1662
|
+
|
|
1663
|
+
if peek.punct?("{")
|
|
1664
|
+
register_enum_tag(tag, tag_tok) if tag
|
|
1665
|
+
parse_enum_body
|
|
1666
|
+
Type::Int
|
|
1667
|
+
elsif tag
|
|
1668
|
+
resolve_enum_tag(tag, tag_tok)
|
|
1669
|
+
else
|
|
1670
|
+
error_at(enum_tok, "expected identifier or '{' after 'enum'")
|
|
1671
|
+
end
|
|
1672
|
+
end
|
|
1673
|
+
|
|
1674
|
+
# Registers an enum tag being defined in the current scope. A name already
|
|
1675
|
+
# taken there by a *complete* enum is a redefinition; one taken by a struct
|
|
1676
|
+
# tag is the wrong kind of tag (struct, union and enum share one namespace).
|
|
1677
|
+
# A tag already forward-declared incomplete in this scope (an EnumType, from
|
|
1678
|
+
# "enum E *p;") is completed here: the marker becomes an EnumTag, so later
|
|
1679
|
+
# "enum E" references resolve to int. Earlier pointer references keep the
|
|
1680
|
+
# incomplete EnumType they captured, which stays valid as a pointer target.
|
|
1681
|
+
def register_enum_tag(tag, token)
|
|
1682
|
+
existing = @tag_scopes.last[tag]
|
|
1683
|
+
if existing
|
|
1684
|
+
if existing.is_a?(EnumTag)
|
|
1685
|
+
error_at(token, "redefinition of 'enum #{tag}'")
|
|
1686
|
+
elsif !existing.is_a?(Type::EnumType)
|
|
1687
|
+
error_at(token, "'#{tag}' defined as wrong kind of tag")
|
|
1688
|
+
else
|
|
1689
|
+
# An earlier forward reference ("enum efoo;", or a prototype's
|
|
1690
|
+
# "enum efoo" return type) captured this incomplete EnumType. Complete
|
|
1691
|
+
# it in place so that captured object now answers as the int an enum
|
|
1692
|
+
# object is — the reference and this definition then agree on the type.
|
|
1693
|
+
existing.complete!
|
|
1694
|
+
end
|
|
1695
|
+
end
|
|
1696
|
+
@tag_scopes.last[tag] = EnumTag.new(tag)
|
|
1697
|
+
end
|
|
1698
|
+
|
|
1699
|
+
# Resolves a bare "enum tag" reference (innermost scope outward). A defined
|
|
1700
|
+
# tag (an EnumTag) resolves to Type::Int, since an enum object is an int; a
|
|
1701
|
+
# tag bound to a struct is the wrong kind of tag. A tag with no visible
|
|
1702
|
+
# binding is forward-declared incomplete — mirroring an incomplete struct —
|
|
1703
|
+
# so "enum E *p;" names a pointer to an as-yet-undefined enum; a later
|
|
1704
|
+
# in-scope forward reference reuses that same incomplete EnumType. The
|
|
1705
|
+
# generator rejects an incomplete enum wherever a size or arithmetic is
|
|
1706
|
+
# actually required.
|
|
1707
|
+
def resolve_enum_tag(tag, token)
|
|
1708
|
+
@tag_scopes.reverse_each do |scope|
|
|
1709
|
+
found = scope[tag]
|
|
1710
|
+
next unless found
|
|
1711
|
+
|
|
1712
|
+
return Type::Int if found.is_a?(EnumTag)
|
|
1713
|
+
return found if found.is_a?(Type::EnumType)
|
|
1714
|
+
|
|
1715
|
+
error_at(token, "'#{tag}' defined as wrong kind of tag")
|
|
1716
|
+
end
|
|
1717
|
+
incomplete = Type::EnumType.new(tag)
|
|
1718
|
+
@tag_scopes.last[tag] = incomplete
|
|
1719
|
+
incomplete
|
|
1720
|
+
end
|
|
1721
|
+
|
|
1722
|
+
# Parses "{ enumerator-list ,? }" (the enumerator-list must be non-empty).
|
|
1723
|
+
# Each enumerator takes the previous value plus one, the first being 0,
|
|
1724
|
+
# unless it names an explicit "= constant"; the folded value is bound as an
|
|
1725
|
+
# int enum constant in the current ordinary scope. A trailing comma before
|
|
1726
|
+
# "}" is allowed (C99).
|
|
1727
|
+
def parse_enum_body
|
|
1728
|
+
expect_punct("{")
|
|
1729
|
+
next_value = 0
|
|
1730
|
+
loop do
|
|
1731
|
+
name_tok = expect_ident
|
|
1732
|
+
value = next_value
|
|
1733
|
+
if peek.punct?("=")
|
|
1734
|
+
advance # "="
|
|
1735
|
+
expr = parse_conditional_expression
|
|
1736
|
+
value = evaluate_constant_expression(expr, "enumerator value is not an integer constant",
|
|
1737
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
1738
|
+
end
|
|
1739
|
+
declare_enum_constant(name_tok, value)
|
|
1740
|
+
next_value = value + 1
|
|
1741
|
+
break unless peek.punct?(",")
|
|
1742
|
+
|
|
1743
|
+
advance # ","
|
|
1744
|
+
break if peek.punct?("}") # trailing comma ends the list
|
|
1745
|
+
end
|
|
1746
|
+
expect_punct("}")
|
|
1747
|
+
end
|
|
1748
|
+
|
|
1749
|
+
# Binds an enumerator's name to its value as an int constant in the current
|
|
1750
|
+
# ordinary scope. A name already bound there — by another enumerator or by
|
|
1751
|
+
# a variable — is a redefinition.
|
|
1752
|
+
def declare_enum_constant(name_tok, value)
|
|
1753
|
+
if @ordinary_scopes.last.key?(name_tok.value)
|
|
1754
|
+
error_at(name_tok, "redefinition of '#{name_tok.value}'")
|
|
1755
|
+
end
|
|
1756
|
+
@ordinary_scopes.last[name_tok.value] = OrdinaryName.new(:enum, value)
|
|
1757
|
+
end
|
|
1758
|
+
|
|
1759
|
+
# Resolves the tag being *defined* to the StructType #parse_struct_body
|
|
1760
|
+
# will lay out. A tag already declared in the *current* scope is reused
|
|
1761
|
+
# (completing an earlier "struct tag;" forward declaration or the
|
|
1762
|
+
# in-progress self-reference), unless it is already complete, which makes
|
|
1763
|
+
# the second body a redefinition. A tag already taken by a differing kind
|
|
1764
|
+
# (an enum, or the other of struct/union) is the wrong kind of tag. An
|
|
1765
|
+
# unknown tag is created incomplete and registered up front — before its
|
|
1766
|
+
# body is parsed — so a member that points back at the same tag ("struct
|
|
1767
|
+
# node *next;") resolves to this very object.
|
|
1768
|
+
def define_struct_tag(tag, kind, token)
|
|
1769
|
+
existing = @tag_scopes.last[tag]
|
|
1770
|
+
if existing
|
|
1771
|
+
reject_wrong_tag_kind(existing, kind, tag, token)
|
|
1772
|
+
error_at(token, "redefinition of '#{tag_keyword(kind)} #{tag}'") if existing.complete?
|
|
1773
|
+
return existing
|
|
1774
|
+
end
|
|
1775
|
+
struct_type = Type::StructType.new(tag, kind: kind)
|
|
1776
|
+
@tag_scopes.last[tag] = struct_type
|
|
1777
|
+
struct_type
|
|
1778
|
+
end
|
|
1779
|
+
|
|
1780
|
+
# Resolves a bare "struct tag" reference. An in-scope tag (searched
|
|
1781
|
+
# innermost outward) is returned as is — complete or not — provided it is
|
|
1782
|
+
# the same kind of aggregate; a tag bound to an enum or the other of
|
|
1783
|
+
# struct/union is the wrong kind of tag. An unknown tag is forward-declared:
|
|
1784
|
+
# a fresh incomplete aggregate of this kind is registered in the current
|
|
1785
|
+
# scope, so "struct node;" introduces the tag and "struct node *p;" names a
|
|
1786
|
+
# pointer to an as-yet-undefined struct.
|
|
1787
|
+
def reference_struct_tag(tag, kind, token)
|
|
1788
|
+
@tag_scopes.reverse_each do |scope|
|
|
1789
|
+
found = scope[tag]
|
|
1790
|
+
next unless found
|
|
1791
|
+
|
|
1792
|
+
reject_wrong_tag_kind(found, kind, tag, token)
|
|
1793
|
+
return found
|
|
1794
|
+
end
|
|
1795
|
+
struct_type = Type::StructType.new(tag, kind: kind)
|
|
1796
|
+
@tag_scopes.last[tag] = struct_type
|
|
1797
|
+
struct_type
|
|
1798
|
+
end
|
|
1799
|
+
|
|
1800
|
+
# Rejects a tag whose existing binding disagrees with the kind now written
|
|
1801
|
+
# for it: struct, union and enum share one namespace (6.7.2.3), so "union
|
|
1802
|
+
# S" against a "struct S", or either against an "enum S", is the wrong kind
|
|
1803
|
+
# of tag. An enum binding is an EnumTag (a defined enum) or a Type::EnumType
|
|
1804
|
+
# (an incomplete, forward-declared one); a struct/union binding is a
|
|
1805
|
+
# StructType told apart by #union?.
|
|
1806
|
+
def reject_wrong_tag_kind(existing, kind, tag, token)
|
|
1807
|
+
wrong = existing.is_a?(EnumTag) || existing.is_a?(Type::EnumType) ||
|
|
1808
|
+
existing.union? != (kind == :union)
|
|
1809
|
+
error_at(token, "'#{tag}' defined as wrong kind of tag") if wrong
|
|
1810
|
+
end
|
|
1811
|
+
|
|
1812
|
+
# The keyword spelling for an aggregate kind, for diagnostics.
|
|
1813
|
+
def tag_keyword(kind)
|
|
1814
|
+
kind == :union ? "union" : "struct"
|
|
1815
|
+
end
|
|
1816
|
+
|
|
1817
|
+
# Parses a struct/union's "{ struct-declaration+ }" body, returning the
|
|
1818
|
+
# raw [name, Type] member pairs the caller hands to StructType#define
|
|
1819
|
+
# (deferred so an attribute after "}" can still steer the layout). A
|
|
1820
|
+
# struct-declaration is either a type-specifier
|
|
1821
|
+
# followed by one or more comma-separated declarators (each contributing a
|
|
1822
|
+
# "*" run and an optional array suffix), just like a local declaration but
|
|
1823
|
+
# with no initializer, or — for an anonymous member (C11 6.7.2.1p13) — a
|
|
1824
|
+
# tagless struct/union specifier with no declarator at all. A named member
|
|
1825
|
+
# may not be void, an incomplete aggregate by value, or a duplicate name;
|
|
1826
|
+
# a pointer to an incomplete struct (the self-referential case) is fine,
|
|
1827
|
+
# since a pointer is always complete. `seen` tracks every member name
|
|
1828
|
+
# visible from this body, folding in the names an anonymous member exposes
|
|
1829
|
+
# transparently, so a collision through one is diagnosed like any other.
|
|
1830
|
+
def parse_struct_body(kind, keyword_tok)
|
|
1831
|
+
expect_punct("{")
|
|
1832
|
+
raw_members = []
|
|
1833
|
+
seen = {}
|
|
1834
|
+
# Tracks a flexible array member as the body is read (ISO C 6.7.2.1p18):
|
|
1835
|
+
# `token` is the FAM's name once seen, so any further member declared
|
|
1836
|
+
# after it is diagnosed (a FAM must be the struct's last member), and
|
|
1837
|
+
# `others` counts the ordinary members, so a struct whose *only* member
|
|
1838
|
+
# is a FAM is rejected. `kind` lets a FAM in a union be rejected.
|
|
1839
|
+
flex = { kind: kind, token: nil, others: 0 }
|
|
1840
|
+
until peek.punct?("}")
|
|
1841
|
+
# GCC accepts an empty declaration in an aggregate body. Generated C
|
|
1842
|
+
# commonly reaches it when a declaration macro already supplies `;`
|
|
1843
|
+
# and the call site supplies another one (libev's VARx is one such
|
|
1844
|
+
# case). It contributes no member and must not be mistaken for a
|
|
1845
|
+
# declarator-less anonymous member.
|
|
1846
|
+
if peek.punct?(";")
|
|
1847
|
+
advance
|
|
1848
|
+
next
|
|
1849
|
+
end
|
|
1850
|
+
|
|
1851
|
+
spec_tok = peek
|
|
1852
|
+
# An _Alignas among a member declaration's specifiers belongs to every
|
|
1853
|
+
# declarator it introduces, exactly as the base type does, so it is
|
|
1854
|
+
# carried alongside it rather than folded into the type.
|
|
1855
|
+
member_base, member_spec = parse_declaration_specifiers(allow_storage_class: false)
|
|
1856
|
+
alignas = member_spec.alignas
|
|
1857
|
+
if peek.punct?(";")
|
|
1858
|
+
parse_anonymous_member(member_base, spec_tok, raw_members, seen, flex, alignas)
|
|
1859
|
+
else
|
|
1860
|
+
parse_member_declarators(member_base, spec_tok, raw_members, seen, flex, alignas)
|
|
1861
|
+
end
|
|
1862
|
+
expect_punct(";")
|
|
1863
|
+
end
|
|
1864
|
+
expect_punct("}")
|
|
1865
|
+
if flex[:token] && flex[:others].zero?
|
|
1866
|
+
error_at(flex[:token], "flexible array member '#{flex[:token].value}' in a struct with no other members")
|
|
1867
|
+
end
|
|
1868
|
+
raw_members
|
|
1869
|
+
end
|
|
1870
|
+
|
|
1871
|
+
# A struct-declaration with no declarator. It is well-formed only as an
|
|
1872
|
+
# anonymous member — a tagless struct/union specifier (its type is an
|
|
1873
|
+
# aggregate with no tag); a tagged specifier standing alone ("struct Inner
|
|
1874
|
+
# {...};" or "struct Inner;" inside a body) or any other bare type
|
|
1875
|
+
# declares nothing and is rejected. The member is recorded with a nil name
|
|
1876
|
+
# and its inner type; every name it exposes transparently is added to
|
|
1877
|
+
# `seen` so a later member cannot shadow one of them.
|
|
1878
|
+
def parse_anonymous_member(member_base, spec_tok, raw_members, seen, flex, alignas = nil)
|
|
1879
|
+
reject_member_after_flexible_array(flex, spec_tok)
|
|
1880
|
+
unless member_base.struct? && member_base.tag.nil?
|
|
1881
|
+
error_at(spec_tok, "declaration does not declare anything")
|
|
1882
|
+
end
|
|
1883
|
+
transparent_member_names(member_base).each do |name|
|
|
1884
|
+
error_at(spec_tok, "duplicate member '#{name}'") if seen.key?(name)
|
|
1885
|
+
seen[name] = true
|
|
1886
|
+
end
|
|
1887
|
+
flex[:others] += 1
|
|
1888
|
+
raw_members << [nil, member_base, nil, alignas_boundary(alignas, member_base, "unnamed field")]
|
|
1889
|
+
end
|
|
1890
|
+
|
|
1891
|
+
# The comma-separated struct-declarators sharing `member_base`. Each is
|
|
1892
|
+
# either a declarator naming a member (a "*" run, an array suffix, or a
|
|
1893
|
+
# function-pointer shape such as "int (*handler)(int)"), optionally followed
|
|
1894
|
+
# by ": constant-expression" to make it a bit-field, or a bare
|
|
1895
|
+
# ": constant-expression" with no declarator — an unnamed bit-field that
|
|
1896
|
+
# shapes the layout but declares nothing (6.7.2.1). A member may not be a
|
|
1897
|
+
# bare function; a pointer to one is fine. Each named member is checked for
|
|
1898
|
+
# a duplicate against `seen` (which already holds any transparently exposed
|
|
1899
|
+
# names) and then added to it. Every recorded entry is
|
|
1900
|
+
# [name, Type, bit_width, alignas], bit_width nil for a plain member and
|
|
1901
|
+
# alignas the boundary an _Alignas asked for (nil for none).
|
|
1902
|
+
def parse_member_declarators(member_base, spec_tok, raw_members, seen, flex, alignas = nil)
|
|
1903
|
+
loop do
|
|
1904
|
+
reject_member_after_flexible_array(flex, spec_tok)
|
|
1905
|
+
if peek.punct?(":")
|
|
1906
|
+
advance # ":"
|
|
1907
|
+
# A bit-field has no address of its own to align, so 6.7.5p2 forbids
|
|
1908
|
+
# an _Alignas on one.
|
|
1909
|
+
reject_alignas(alignas, "bit-field")
|
|
1910
|
+
# An unnamed bit-field declares no member, so it does not satisfy the
|
|
1911
|
+
# "a FAM needs another named member" rule (flex[:others] untouched).
|
|
1912
|
+
raw_members << [nil, member_base, parse_bitfield_width(member_base, spec_tok)]
|
|
1913
|
+
else
|
|
1914
|
+
parse_named_member(member_base, raw_members, seen, flex, alignas)
|
|
1915
|
+
end
|
|
1916
|
+
break unless peek.punct?(",")
|
|
1917
|
+
|
|
1918
|
+
advance
|
|
1919
|
+
end
|
|
1920
|
+
end
|
|
1921
|
+
|
|
1922
|
+
# One named struct-declarator: a declarator, then either a ": width"
|
|
1923
|
+
# bit-field tail or a plain member. A named bit-field of zero width is a
|
|
1924
|
+
# constraint violation (6.7.2.1p3, "only an unnamed member may be
|
|
1925
|
+
# zero-width"). A plain member may not be a function, void, or an
|
|
1926
|
+
# incomplete aggregate by value.
|
|
1927
|
+
def parse_named_member(member_base, raw_members, seen, flex, alignas = nil)
|
|
1928
|
+
# A trailing "[]" (an incomplete array) is admitted here so the last
|
|
1929
|
+
# member may be a flexible array member; #reject_flexible_array_member
|
|
1930
|
+
# then enforces the 6.7.2.1p18 constraints (struct only, and never
|
|
1931
|
+
# followed by another member — see #reject_member_after_flexible_array).
|
|
1932
|
+
name_tok, type, params = parse_declarator(member_base, allow_incomplete_array: true,
|
|
1933
|
+
allow_zero_length_array: true)
|
|
1934
|
+
# A member is never a function definition, so an identifier list on one
|
|
1935
|
+
# ("struct s { int m(a, b); };") names types that never arrive. The
|
|
1936
|
+
# "declared as a function" refusal below would also catch it, but only
|
|
1937
|
+
# after the declarator had been read as a plain "int m()".
|
|
1938
|
+
reject_identifier_list(params)
|
|
1939
|
+
if peek.punct?(":")
|
|
1940
|
+
advance # ":"
|
|
1941
|
+
reject_alignas(alignas, "bit-field '#{name_tok.value}'")
|
|
1942
|
+
width = parse_bitfield_width(type, name_tok)
|
|
1943
|
+
error_at(name_tok, "named bit-field '#{name_tok.value}' has zero width") if width.zero?
|
|
1944
|
+
register_member_name(name_tok, seen)
|
|
1945
|
+
flex[:others] += 1
|
|
1946
|
+
raw_members << [name_tok.value, type, width]
|
|
1947
|
+
else
|
|
1948
|
+
# A GNU attribute may trail a member declarator (position f):
|
|
1949
|
+
# "int m __attribute__((packed));". Accepted and discarded — a
|
|
1950
|
+
# member-level packed/aligned has no effect on this subset's layout
|
|
1951
|
+
# (only a whole-struct attribute steers #layout_struct, and only an
|
|
1952
|
+
# _Alignas raises a single member's boundary).
|
|
1953
|
+
parse_attribute_specifiers
|
|
1954
|
+
error_at(name_tok, "field '#{name_tok.value}' declared as a function") if type.function?
|
|
1955
|
+
reject_void_type(type, name_tok)
|
|
1956
|
+
reject_incomplete_member(type, name_tok)
|
|
1957
|
+
register_member_name(name_tok, seen)
|
|
1958
|
+
if type.array? && type.incomplete?
|
|
1959
|
+
reject_flexible_array_member(type, name_tok, flex)
|
|
1960
|
+
flex[:token] = name_tok
|
|
1961
|
+
else
|
|
1962
|
+
flex[:others] += 1
|
|
1963
|
+
end
|
|
1964
|
+
raw_members << [name_tok.value, type, nil,
|
|
1965
|
+
alignas_boundary(alignas, type, "'#{name_tok.value}'")]
|
|
1966
|
+
end
|
|
1967
|
+
end
|
|
1968
|
+
|
|
1969
|
+
# Rejects a member declared after a flexible array member: a FAM must be
|
|
1970
|
+
# the struct's last member (6.7.2.1p18), so anything that follows it — a
|
|
1971
|
+
# further declarator in the same list ("int f[], g;"), a later declaration,
|
|
1972
|
+
# or an anonymous member — is a constraint violation reported at the FAM's
|
|
1973
|
+
# own name. Does nothing until a FAM has actually been seen.
|
|
1974
|
+
def reject_member_after_flexible_array(flex, _anchor)
|
|
1975
|
+
return unless flex[:token]
|
|
1976
|
+
|
|
1977
|
+
error_at(flex[:token],
|
|
1978
|
+
"flexible array member '#{flex[:token].value}' must be the last member of the struct")
|
|
1979
|
+
end
|
|
1980
|
+
|
|
1981
|
+
# Enforces the two constraints a flexible array member must satisfy at the
|
|
1982
|
+
# point it is declared (6.7.2.1p18): it is legal only in a struct, never a
|
|
1983
|
+
# union, and only when the element type is complete — an "[]" of an
|
|
1984
|
+
# incomplete struct has no element size to index. The "must be last" and
|
|
1985
|
+
# "needs another member" rules are enforced by the surrounding body parse,
|
|
1986
|
+
# which alone sees the whole member sequence.
|
|
1987
|
+
def reject_flexible_array_member(type, name_tok, flex)
|
|
1988
|
+
if flex[:kind] == :union
|
|
1989
|
+
error_at(name_tok, "flexible array member '#{name_tok.value}' not allowed in union")
|
|
1990
|
+
end
|
|
1991
|
+
if type.element.struct? && !type.element.complete?
|
|
1992
|
+
error_at(name_tok, "flexible array member '#{name_tok.value}' has incomplete element type")
|
|
1993
|
+
end
|
|
1994
|
+
end
|
|
1995
|
+
|
|
1996
|
+
# Records a member name in `seen`, diagnosing a collision with a name
|
|
1997
|
+
# already visible in this body (a directly declared member or one an
|
|
1998
|
+
# anonymous member exposes transparently).
|
|
1999
|
+
def register_member_name(name_tok, seen)
|
|
2000
|
+
error_at(name_tok, "duplicate member '#{name_tok.value}'") if seen.key?(name_tok.value)
|
|
2001
|
+
seen[name_tok.value] = true
|
|
2002
|
+
end
|
|
2003
|
+
|
|
2004
|
+
# Parses and validates a bit-field's ": constant-expression" width, the ":"
|
|
2005
|
+
# already consumed. `type` is the field's declared type and `anchor` the
|
|
2006
|
+
# token a diagnostic points at. The type must be an integer type, and the
|
|
2007
|
+
# width a non-negative integer constant no wider than that type (6.7.2.1p4).
|
|
2008
|
+
def parse_bitfield_width(type, anchor)
|
|
2009
|
+
unless type.integer?
|
|
2010
|
+
error_at(anchor, "bit-field has non-integral type '#{type}'")
|
|
2011
|
+
end
|
|
2012
|
+
expr = parse_conditional_expression
|
|
2013
|
+
width = evaluate_constant_expression(expr, "bit-field width is not an integer constant",
|
|
2014
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
2015
|
+
error_at(expr.token, "negative width in bit-field") if width.negative?
|
|
2016
|
+
error_at(expr.token, "width of bit-field exceeds its type") if width > type.size * 8
|
|
2017
|
+
width
|
|
2018
|
+
end
|
|
2019
|
+
|
|
2020
|
+
# Every member name an anonymous member exposes to its enclosing
|
|
2021
|
+
# aggregate: its own named members, plus (recursively) the names its own
|
|
2022
|
+
# anonymous members expose. `struct_type` is already laid out here, so its
|
|
2023
|
+
# members are known.
|
|
2024
|
+
def transparent_member_names(struct_type)
|
|
2025
|
+
struct_type.members.flat_map do |m|
|
|
2026
|
+
if m.name.nil? && m.type.struct?
|
|
2027
|
+
transparent_member_names(m.type)
|
|
2028
|
+
else
|
|
2029
|
+
[m.name]
|
|
2030
|
+
end
|
|
2031
|
+
end
|
|
2032
|
+
end
|
|
2033
|
+
|
|
2034
|
+
# Rejects a struct member declared with an incomplete struct type by
|
|
2035
|
+
# value (a whole "struct node" inside "struct node", or before the tag is
|
|
2036
|
+
# defined): its size is unknown, so the layout could not place the fields
|
|
2037
|
+
# after it. An array of such a type is rejected for the same reason; a
|
|
2038
|
+
# pointer to it is allowed.
|
|
2039
|
+
def reject_incomplete_member(type, token)
|
|
2040
|
+
incomplete = (type.struct? && !type.complete?) ||
|
|
2041
|
+
(type.array? && type.element.struct? && !type.element.complete?)
|
|
2042
|
+
error_at(token, "field '#{token.value}' has incomplete type") if incomplete
|
|
2043
|
+
end
|
|
2044
|
+
|
|
2045
|
+
# Whether `token` opens a declaration, letting block-item and for-init tell
|
|
2046
|
+
# a declaration from a statement, and the cast/sizeof parsers tell a
|
|
2047
|
+
# type-name from a parenthesized expression. A declaration begins with an
|
|
2048
|
+
# integer/void type-specifier keyword, "struct"/"union"/"enum", a storage
|
|
2049
|
+
# class ("typedef"/"static"/"extern"/"register"/"auto"), a type qualifier
|
|
2050
|
+
# ("const"/"volatile"/"_Atomic"), the "inline"/"_Noreturn" function
|
|
2051
|
+
# specifiers, or a typedef name
|
|
2052
|
+
# — an identifier bound to a type in the ordinary namespace
|
|
2053
|
+
# whose innermost binding is not shadowed by a variable. The storage-class
|
|
2054
|
+
# and function-specifier keywords never open an expression, so admitting
|
|
2055
|
+
# them here only ever forwards a genuine declaration (a bare "static x;"
|
|
2056
|
+
# then fails in the specifier parse, where it belongs).
|
|
2057
|
+
def type_specifier?(token)
|
|
2058
|
+
if token.type == :keyword
|
|
2059
|
+
return DECL_SPECIFIER_KEYWORDS.include?(token.value) ||
|
|
2060
|
+
STORAGE_CLASS_KEYWORDS.include?(token.value) ||
|
|
2061
|
+
token.value == "struct" || token.value == "union" ||
|
|
2062
|
+
token.value == "enum" ||
|
|
2063
|
+
token.value == "const" || token.value == "volatile" ||
|
|
2064
|
+
token.value == "_Atomic" ||
|
|
2065
|
+
# An alignment-specifier opens a declaration too ("_Alignas(16)
|
|
2066
|
+
# char buf[64];"), and never an expression, so block-item and
|
|
2067
|
+
# for-init must not read one as a statement.
|
|
2068
|
+
token.value == "_Alignas" ||
|
|
2069
|
+
token.value == "inline" || token.value == "_Noreturn" ||
|
|
2070
|
+
# A leading GNU attribute opens a declaration too
|
|
2071
|
+
# ("__attribute__((unused)) int x;"), so block-item and
|
|
2072
|
+
# for-init recognize it as one rather than a statement.
|
|
2073
|
+
token.value == "__attribute__"
|
|
2074
|
+
end
|
|
2075
|
+
token.type == :ident && typedef_name?(token.value)
|
|
2076
|
+
end
|
|
2077
|
+
|
|
2078
|
+
# Rejects `type` when it denotes a bare void or an array of void: this
|
|
2079
|
+
# subset only allows "void" as a function's return type or as the target
|
|
2080
|
+
# of a pointer ("void *", "void **", ...), so a void variable, global,
|
|
2081
|
+
# array element or (non-pointer) parameter is an error.
|
|
2082
|
+
def reject_void_type(type, token)
|
|
2083
|
+
return unless type.void? || (type.array? && type.element.void?)
|
|
2084
|
+
|
|
2085
|
+
error_at(token, "variable or field declared void")
|
|
2086
|
+
end
|
|
2087
|
+
|
|
2088
|
+
def parse_function_definition(name, return_type, params, return_tok, storage, variadic)
|
|
2089
|
+
# A definition, unlike a prototype, must name each parameter so its
|
|
2090
|
+
# value can be bound in the body.
|
|
2091
|
+
params.each do |param|
|
|
2092
|
+
error_at(param.token, "parameter name omitted") if param.name.nil?
|
|
2093
|
+
end
|
|
2094
|
+
expect_punct("{")
|
|
2095
|
+
# The body is a block, so it owns a tag scope and an ordinary scope: a
|
|
2096
|
+
# struct or typedef defined in one function's body is invisible to the
|
|
2097
|
+
# next. The parameters live in this body scope as ordinary names, so a
|
|
2098
|
+
# parameter shadows an outer typedef of the same name inside the body.
|
|
2099
|
+
@tag_scopes.push({})
|
|
2100
|
+
@ordinary_scopes.push({})
|
|
2101
|
+
params.each { |param| declare_ordinary_name(param.name, param.type) }
|
|
2102
|
+
body = []
|
|
2103
|
+
body.concat(parse_block_item) until peek.punct?("}")
|
|
2104
|
+
@ordinary_scopes.pop
|
|
2105
|
+
@tag_scopes.pop
|
|
2106
|
+
expect_punct("}")
|
|
2107
|
+
AST::FunctionDef.new(name, return_type, params, body, return_tok, storage, variadic)
|
|
2108
|
+
end
|
|
2109
|
+
|
|
2110
|
+
# Returns [params, variadic]: an array of AST::Parameter (empty for "()" or
|
|
2111
|
+
# "(void)") and whether the list ends in a "..." variable-argument marker
|
|
2112
|
+
# (6.7.6.3). A bare "void" only means "no parameters" when it is the entire
|
|
2113
|
+
# list (followed immediately by ")"); "void *" or a later "void" parameter
|
|
2114
|
+
# falls through to parse_parameter_declaration, which rejects a non-pointer
|
|
2115
|
+
# void. A "..." is admitted only after at least one named parameter and a
|
|
2116
|
+
# comma ("int a, ..."): a lone "(...)" has no fixed parameter to anchor a
|
|
2117
|
+
# va_start on, and nothing may follow the "...".
|
|
2118
|
+
def parse_parameter_type_list
|
|
2119
|
+
return [[], false] if peek.punct?(")")
|
|
2120
|
+
if peek.keyword?("void") && peek_ahead(1)&.punct?(")")
|
|
2121
|
+
advance
|
|
2122
|
+
return [[], false]
|
|
2123
|
+
end
|
|
2124
|
+
if peek.punct?("...")
|
|
2125
|
+
error_at(peek, "ISO C requires a named parameter before '...'")
|
|
2126
|
+
end
|
|
2127
|
+
|
|
2128
|
+
params = [parse_parameter_declaration]
|
|
2129
|
+
variadic = false
|
|
2130
|
+
while peek.punct?(",")
|
|
2131
|
+
advance
|
|
2132
|
+
if peek.punct?("...")
|
|
2133
|
+
advance
|
|
2134
|
+
variadic = true
|
|
2135
|
+
# "..." terminates the list; a parameter or stray token after it
|
|
2136
|
+
# ("int a, ..., int b") is rejected here rather than left for the
|
|
2137
|
+
# caller's ")" expectation to surface as a vaguer error.
|
|
2138
|
+
error_at(peek, "'...' must be the last parameter") unless peek.punct?(")")
|
|
2139
|
+
break
|
|
2140
|
+
end
|
|
2141
|
+
params << parse_parameter_declaration
|
|
2142
|
+
end
|
|
2143
|
+
[params, variadic]
|
|
2144
|
+
end
|
|
2145
|
+
|
|
2146
|
+
# parameter-declaration = type-specifier declarator?, the declarator being
|
|
2147
|
+
# a full (possibly abstract) one whose name is optional (:optional mode)
|
|
2148
|
+
# so prototypes may omit it. The parsed type is then adjusted per 6.7.6.3
|
|
2149
|
+
# (an array becomes a pointer to its element, a function a pointer to
|
|
2150
|
+
# itself), so "int a[10]" is "int *a" and "int g(int)" is "int (*g)(int)".
|
|
2151
|
+
# An unnamed parameter is located by its type-specifier keyword for
|
|
2152
|
+
# diagnostics.
|
|
2153
|
+
def parse_parameter_declaration
|
|
2154
|
+
type_tok = peek
|
|
2155
|
+
# A parameter's specifiers admit const/volatile but not a storage class
|
|
2156
|
+
# or inline (allow_storage_class: false) — except `register`, the one
|
|
2157
|
+
# storage class 6.7.6.3p2 permits on a parameter, which is consumed and
|
|
2158
|
+
# ignored. Only its const survives.
|
|
2159
|
+
base_type, spec_info = parse_declaration_specifiers(allow_storage_class: false, allow_register: true)
|
|
2160
|
+
# A parameter's array declarator adjusts to a pointer (6.7.6.3p7), so an
|
|
2161
|
+
# empty "[]" is admitted here just as it is for an external declaration's
|
|
2162
|
+
# incomplete array; #adjust_parameter_type resolves it below.
|
|
2163
|
+
name_tok, type, params, pointer_quals =
|
|
2164
|
+
parse_declarator(base_type, name_mode: :optional, allow_incomplete_array: true)
|
|
2165
|
+
# A parameter that is itself a function declarator ("int f(int g(a, b))")
|
|
2166
|
+
# is a declaration, not the definition of g, so its identifier list has
|
|
2167
|
+
# no types to come.
|
|
2168
|
+
reject_identifier_list(params)
|
|
2169
|
+
# A parameter's boundary is the calling convention's to choose, not the
|
|
2170
|
+
# declaration's, so 6.7.5p2 forbids an _Alignas on one.
|
|
2171
|
+
reject_alignas(spec_info.alignas,
|
|
2172
|
+
name_tok ? "parameter '#{name_tok.value}'" : "parameter")
|
|
2173
|
+
# A GNU attribute may trail a parameter declarator (position e):
|
|
2174
|
+
# "int f(int x __attribute__((unused)))". Accepted and discarded; the
|
|
2175
|
+
# specifier-position form is already handled in the specifier parse.
|
|
2176
|
+
parse_attribute_specifiers
|
|
2177
|
+
type = adjust_parameter_type(type)
|
|
2178
|
+
# The const-ness is settled on the adjusted type, so "const int a[10]"
|
|
2179
|
+
# (a pointer to const int after adjustment) yields a non-const parameter,
|
|
2180
|
+
# while "int * const a" stays a const pointer parameter.
|
|
2181
|
+
const = declarator_object_const(type, spec_info.const, pointer_quals)
|
|
2182
|
+
reject_void_type(type, name_tok || type_tok)
|
|
2183
|
+
if name_tok
|
|
2184
|
+
AST::Parameter.new(name_tok.value, type, name_tok, const)
|
|
2185
|
+
else
|
|
2186
|
+
AST::Parameter.new(nil, type, type_tok, const)
|
|
2187
|
+
end
|
|
2188
|
+
end
|
|
2189
|
+
|
|
2190
|
+
# Returns an array of nodes: a declaration expands to one VariableDecl
|
|
2191
|
+
# per init-declarator, while a statement always yields exactly one node.
|
|
2192
|
+
def parse_block_item
|
|
2193
|
+
# A block-scope "_Static_assert(expr, "msg");" is a declaration that
|
|
2194
|
+
# binds nothing; it is checked and flattened away like a bare tag decl.
|
|
2195
|
+
return parse_static_assert if peek.keyword?("_Static_assert")
|
|
2196
|
+
|
|
2197
|
+
# A "__extension__" prefixing a declaration ("__extension__ int x;") is
|
|
2198
|
+
# discarded here; a "__extension__" prefixing an expression statement is
|
|
2199
|
+
# left for #parse_cast_expression, which binds it like a cast prefix.
|
|
2200
|
+
if extension_prefixes_declaration?
|
|
2201
|
+
skip_extension_markers
|
|
2202
|
+
return parse_static_assert if peek.keyword?("_Static_assert")
|
|
2203
|
+
|
|
2204
|
+
return parse_declaration
|
|
2205
|
+
end
|
|
2206
|
+
|
|
2207
|
+
if type_specifier?(peek)
|
|
2208
|
+
parse_declaration
|
|
2209
|
+
else
|
|
2210
|
+
[parse_statement]
|
|
2211
|
+
end
|
|
2212
|
+
end
|
|
2213
|
+
|
|
2214
|
+
def parse_declaration
|
|
2215
|
+
base_type, spec_info = parse_declaration_specifiers(allow_storage_class: true)
|
|
2216
|
+
|
|
2217
|
+
# A bare "struct point { ... };" (or "struct node;", or a tag-only "enum
|
|
2218
|
+
# E { ... };") inside a block just declares or defines the tag, adding no
|
|
2219
|
+
# local; it yields no items.
|
|
2220
|
+
if peek.punct?(";")
|
|
2221
|
+
advance
|
|
2222
|
+
return []
|
|
2223
|
+
end
|
|
2224
|
+
|
|
2225
|
+
# A local typedef binds names as types in this block's scope; like a
|
|
2226
|
+
# file-scope typedef it yields no items.
|
|
2227
|
+
return parse_typedef_declaration(base_type, spec_info) if spec_info.storage == :typedef
|
|
2228
|
+
|
|
2229
|
+
decls = [parse_init_declarator(base_type, spec_info)]
|
|
2230
|
+
while peek.punct?(",")
|
|
2231
|
+
advance
|
|
2232
|
+
decls << parse_init_declarator(base_type, spec_info)
|
|
2233
|
+
end
|
|
2234
|
+
expect_punct(";")
|
|
2235
|
+
decls
|
|
2236
|
+
end
|
|
2237
|
+
|
|
2238
|
+
# A typedef declaration: a run of comma-separated declarators sharing
|
|
2239
|
+
# `base_type`, each binding its name as a type (its "*" run and array
|
|
2240
|
+
# suffix applied) in the current ordinary scope. A typedef declarator may
|
|
2241
|
+
# not have an initializer (6.7.1); the declaration itself contributes no
|
|
2242
|
+
# AST node, so this returns an empty run.
|
|
2243
|
+
def parse_typedef_declaration(base_type, spec_info)
|
|
2244
|
+
loop do
|
|
2245
|
+
name_tok, type, params, pointer_quals = parse_declarator(base_type)
|
|
2246
|
+
# A typedef names a type, never a function this unit defines, so an
|
|
2247
|
+
# identifier list ("typedef int F(a, b);") could not be a definition.
|
|
2248
|
+
reject_identifier_list(params)
|
|
2249
|
+
parse_attribute_specifiers # position d: a trailing attribute on the typedef name
|
|
2250
|
+
# A typedef declares a type, not an object, so there is nothing for an
|
|
2251
|
+
# _Alignas to align (6.7.5p2).
|
|
2252
|
+
reject_alignas(spec_info.alignas, "typedef '#{name_tok.value}'")
|
|
2253
|
+
if peek.punct?("=")
|
|
2254
|
+
error_at(peek, "typedef '#{name_tok.value}' must not be initialized")
|
|
2255
|
+
end
|
|
2256
|
+
# A typedef of a const-qualified object type remembers that const so a
|
|
2257
|
+
# later use ("typedef const int ci; ci x;") makes x const; the same
|
|
2258
|
+
# top-level rule applies, so "typedef const int *cp;" (a pointer to
|
|
2259
|
+
# const) is not itself const.
|
|
2260
|
+
const = declarator_object_const(type, spec_info.const, pointer_quals)
|
|
2261
|
+
declare_typedef_name(name_tok, type, const)
|
|
2262
|
+
break unless peek.punct?(",")
|
|
2263
|
+
|
|
2264
|
+
advance # ","
|
|
2265
|
+
end
|
|
2266
|
+
expect_punct(";")
|
|
2267
|
+
[]
|
|
2268
|
+
end
|
|
2269
|
+
|
|
2270
|
+
def parse_init_declarator(base_type, spec_info)
|
|
2271
|
+
name_tok, type, params, pointer_quals = parse_declarator(base_type, allow_incomplete_array: true)
|
|
2272
|
+
# A block-scope declarator declares; a definition never nests (see the
|
|
2273
|
+
# nested-function refusal below), so an identifier list here supplies no
|
|
2274
|
+
# types either.
|
|
2275
|
+
reject_identifier_list(params)
|
|
2276
|
+
parse_attribute_specifiers # position d: a trailing attribute on this local declarator
|
|
2277
|
+
reject_void_type(type, name_tok)
|
|
2278
|
+
# A body here would be a *nested function definition* — a GNU extension,
|
|
2279
|
+
# not the block-scope function *declaration* 6.2.2p5 blesses (which ends
|
|
2280
|
+
# at the ";" and only names an external function). It needs a trampoline
|
|
2281
|
+
# to capture the enclosing frame, is out of scope for this compiler, and
|
|
2282
|
+
# would otherwise surface as a bare "expected ';'" that says nothing about
|
|
2283
|
+
# why. "inline"/"_Noreturn" ride on a function declarator legitimately
|
|
2284
|
+
# (6.7.4), so the object-only specifier check is skipped for one.
|
|
2285
|
+
if type.function?
|
|
2286
|
+
if peek.punct?("{")
|
|
2287
|
+
error_at(name_tok, "nested function definitions are not supported")
|
|
2288
|
+
end
|
|
2289
|
+
# A function reserves no object to align (6.7.5p2).
|
|
2290
|
+
reject_alignas(spec_info.alignas, "function '#{name_tok.value}'")
|
|
2291
|
+
else
|
|
2292
|
+
reject_object_specifiers(name_tok, spec_info)
|
|
2293
|
+
end
|
|
2294
|
+
const = declarator_object_const(type, spec_info.const, pointer_quals)
|
|
2295
|
+
initializer = nil
|
|
2296
|
+
if peek.punct?("=")
|
|
2297
|
+
if spec_info.storage == :extern
|
|
2298
|
+
error_at(name_tok, "'#{name_tok.value}' has both 'extern' and initializer")
|
|
2299
|
+
end
|
|
2300
|
+
advance # "="
|
|
2301
|
+
initializer = parse_initializer
|
|
2302
|
+
# A structural initializer (a brace list, or a string for a char array)
|
|
2303
|
+
# fixes the object's type — completing an inferred "[]" bound — and is
|
|
2304
|
+
# validated for shape here, so a later stage sees a finished type.
|
|
2305
|
+
if InitializerResolver.structural?(type, initializer)
|
|
2306
|
+
type = InitializerResolver.resolve(type, initializer,
|
|
2307
|
+
static_storage: spec_info.storage == :static).type
|
|
2308
|
+
end
|
|
2309
|
+
elsif type.array? && type.length.nil? && spec_info.storage != :extern
|
|
2310
|
+
# A block-scope `extern T a[];` references a file-scope array defined
|
|
2311
|
+
# elsewhere, an incomplete type that unit completes (6.7.6.2p1, 6.9.2),
|
|
2312
|
+
# so it is kept as-is. A non-extern `int a[];` in a block has no
|
|
2313
|
+
# initializer to complete it and no tentative-definition rule at block
|
|
2314
|
+
# scope, so it stays a diagnostic (gcc rejects it likewise).
|
|
2315
|
+
error_at(name_tok, "array size missing in '#{name_tok.value}'")
|
|
2316
|
+
end
|
|
2317
|
+
declare_ordinary_name(name_tok.value, type)
|
|
2318
|
+
# The boundary is settled against the *finished* type, so an inferred
|
|
2319
|
+
# "[]" bound is already in place when the "cannot reduce" check runs.
|
|
2320
|
+
AST::VariableDecl.new(name_tok.value, type, initializer, name_tok, const, spec_info.storage,
|
|
2321
|
+
alignas_boundary(spec_info.alignas, type, "'#{name_tok.value}'"))
|
|
2322
|
+
end
|
|
2323
|
+
|
|
2324
|
+
# Rejects the declaration specifiers that may sit on a function but not on
|
|
2325
|
+
# an object: "inline" or "_Noreturn" on a variable or global is ill-formed
|
|
2326
|
+
# (both are function specifiers, 6.7.4). Storage classes are already
|
|
2327
|
+
# admitted here (recorded for Phase B), so only these two are caught.
|
|
2328
|
+
# Shared by the local and file-scope object declarators.
|
|
2329
|
+
def reject_object_specifiers(name_tok, spec_info)
|
|
2330
|
+
error_at(name_tok, "variable '#{name_tok.value}' declared 'inline'") if spec_info.inline_p
|
|
2331
|
+
return unless spec_info.noreturn_p
|
|
2332
|
+
|
|
2333
|
+
error_at(name_tok, "variable '#{name_tok.value}' declared '_Noreturn'")
|
|
2334
|
+
end
|
|
2335
|
+
|
|
2336
|
+
# Whether the object a declarator declares is top-level const-qualified,
|
|
2337
|
+
# the only qualification M1 tracks. With no pointer/array/function
|
|
2338
|
+
# derivation the specifier's const applies directly ("const int x"); an
|
|
2339
|
+
# array likewise takes the specifier const (M1 treats the whole array
|
|
2340
|
+
# variable as const rather than only its elements, a deliberate
|
|
2341
|
+
# simplification); a pointer is const only when its outermost level bears
|
|
2342
|
+
# the qualifier ("int * const p" is const, "const int *p" is not); a
|
|
2343
|
+
# function type is never a const object. `pointer_quals` is the declarator's
|
|
2344
|
+
# leading "*" run, one const flag per level, so its last entry is the
|
|
2345
|
+
# outermost pointer — empty (a pointer built inside parentheses) reads as
|
|
2346
|
+
# not const, a tolerated M1 gap for "int (* const p)[3]".
|
|
2347
|
+
def declarator_object_const(type, specifier_const, pointer_quals)
|
|
2348
|
+
return pointer_quals.last || false if type.pointer?
|
|
2349
|
+
return false if type.function?
|
|
2350
|
+
|
|
2351
|
+
specifier_const
|
|
2352
|
+
end
|
|
2353
|
+
|
|
2354
|
+
# A file- or block-scope "_Static_assert ( constant-expression ,
|
|
2355
|
+
# string-literal ) ;" (6.7.10). The expression is folded like any other
|
|
2356
|
+
# constant-expression, with the same parse-time "sizeof <expression>"
|
|
2357
|
+
# resolution an array bound gets (#fold_time_sizeof) — asserting a size
|
|
2358
|
+
# relation over an expression is the idiom's main use (ruby.h's
|
|
2359
|
+
# RBIMPL_STATIC_ASSERT(…, sizeof *ptr == sizeof(size_t))). A zero value
|
|
2360
|
+
# fails the assertion, quoting the message the way gcc does. It declares
|
|
2361
|
+
# nothing, so — like a bare tag declaration or a typedef — it returns an
|
|
2362
|
+
# empty run of declarations.
|
|
2363
|
+
def parse_static_assert
|
|
2364
|
+
keyword_tok = advance # "_Static_assert"
|
|
2365
|
+
expect_punct("(")
|
|
2366
|
+
expr = parse_conditional_expression
|
|
2367
|
+
value = evaluate_constant_expression(expr, "static assertion expression is not an integer constant",
|
|
2368
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
2369
|
+
expect_punct(",")
|
|
2370
|
+
message_tok = peek
|
|
2371
|
+
error_at(message_tok, "expected string literal in '_Static_assert'") unless message_tok.type == :string
|
|
2372
|
+
advance
|
|
2373
|
+
expect_punct(")")
|
|
2374
|
+
expect_punct(";")
|
|
2375
|
+
error_at(keyword_tok, "static assertion failed: \"#{message_tok.value}\"") if value.zero?
|
|
2376
|
+
[]
|
|
2377
|
+
end
|
|
2378
|
+
|
|
2379
|
+
# initializer = assignment-expression | "{" initializer-list ","? "}"
|
|
2380
|
+
# (6.7.9). A "{" opens a brace list; anything else is a single assignment
|
|
2381
|
+
# expression (a scalar's value, or a whole string literal for a char
|
|
2382
|
+
# array). The resolver later matches the shape against the object's type.
|
|
2383
|
+
def parse_initializer
|
|
2384
|
+
return parse_initializer_list if peek.punct?("{")
|
|
2385
|
+
|
|
2386
|
+
parse_assignment_expression
|
|
2387
|
+
end
|
|
2388
|
+
|
|
2389
|
+
# initializer-list = designation? initializer ("," designation? initializer)*
|
|
2390
|
+
# with an optional trailing comma before "}". Each element becomes an
|
|
2391
|
+
# InitItem pairing its (possibly empty) designator chain with its value,
|
|
2392
|
+
# which may itself be a nested brace list.
|
|
2393
|
+
def parse_initializer_list
|
|
2394
|
+
brace_tok = expect_punct("{")
|
|
2395
|
+
with_nesting_guard(brace_tok, "initializer") do
|
|
2396
|
+
items = []
|
|
2397
|
+
until peek.punct?("}")
|
|
2398
|
+
designators = parse_designation
|
|
2399
|
+
value = parse_initializer
|
|
2400
|
+
items << AST::InitItem.new(designators, value)
|
|
2401
|
+
break unless peek.punct?(",")
|
|
2402
|
+
|
|
2403
|
+
advance # ","
|
|
2404
|
+
end
|
|
2405
|
+
expect_punct("}")
|
|
2406
|
+
AST::InitializerList.new(items, brace_tok)
|
|
2407
|
+
end
|
|
2408
|
+
end
|
|
2409
|
+
|
|
2410
|
+
# designation = designator+ "=", where designator is "[" constant-expression
|
|
2411
|
+
# "]" or "." identifier (6.7.9). Returns the designator chain, or an empty
|
|
2412
|
+
# array when the next element is positional (no leading "[" or "."). An
|
|
2413
|
+
# array designator's index is folded to a Ruby Integer on the spot, like an
|
|
2414
|
+
# array bound.
|
|
2415
|
+
def parse_designation
|
|
2416
|
+
return [] unless peek.punct?("[") || peek.punct?(".")
|
|
2417
|
+
|
|
2418
|
+
designators = []
|
|
2419
|
+
loop do
|
|
2420
|
+
if peek.punct?("[")
|
|
2421
|
+
bracket_tok = advance # "["
|
|
2422
|
+
expr = parse_conditional_expression
|
|
2423
|
+
index = evaluate_constant_expression(expr, "array designator is not an integer constant",
|
|
2424
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
2425
|
+
expect_punct("]")
|
|
2426
|
+
designators << AST::ArrayDesignator.new(index, bracket_tok)
|
|
2427
|
+
elsif peek.punct?(".")
|
|
2428
|
+
dot_tok = advance # "."
|
|
2429
|
+
name_tok = expect_ident
|
|
2430
|
+
designators << AST::MemberDesignator.new(name_tok.value, dot_tok)
|
|
2431
|
+
else
|
|
2432
|
+
break
|
|
2433
|
+
end
|
|
2434
|
+
end
|
|
2435
|
+
expect_punct("=")
|
|
2436
|
+
designators
|
|
2437
|
+
end
|
|
2438
|
+
|
|
2439
|
+
# Parses a full declarator (6.7.6) and applies it to `base`, returning
|
|
2440
|
+
# [name_token_or_nil, type, function_params]. The declarator is read
|
|
2441
|
+
# syntactically and turned into a proc that wraps `base` inside-out (see
|
|
2442
|
+
# #parse_declarator_builder); `type` is that proc applied to `base`, and
|
|
2443
|
+
# `function_params` is the parameter list of the function suffix attached
|
|
2444
|
+
# directly to the declared name when the result is a function type (a
|
|
2445
|
+
# function definition or prototype needs those Parameter objects), nil
|
|
2446
|
+
# otherwise.
|
|
2447
|
+
#
|
|
2448
|
+
# `name_mode` governs the identifier: :required in an ordinary declaration
|
|
2449
|
+
# (a missing name is an error), :optional in a parameter (the name may be
|
|
2450
|
+
# omitted), or :forbidden in a type-name (a cast or sizeof, which never
|
|
2451
|
+
# names anything). `allow_incomplete_array` admits a trailing "[]" whose
|
|
2452
|
+
# length an initializer will infer. `allow_zero_length_array` is threaded
|
|
2453
|
+
# only for struct members, where the GNU `[0]` extension is valid.
|
|
2454
|
+
# Returns [name_token_or_nil, type, function_params, pointer_quals], the
|
|
2455
|
+
# last being the declarator's leading "*" run as a list of per-level const
|
|
2456
|
+
# flags (see #parse_pointer_qualifiers) so an object declarator can settle
|
|
2457
|
+
# its top-level const-ness (see #declarator_object_const). Callers that do
|
|
2458
|
+
# not need the qualifiers simply ignore the trailing value.
|
|
2459
|
+
def parse_declarator(base, name_mode: :required, allow_incomplete_array: false,
|
|
2460
|
+
allow_zero_length_array: false)
|
|
2461
|
+
name_tok, build, function_params, pointer_quals =
|
|
2462
|
+
parse_declarator_builder(name_mode: name_mode,
|
|
2463
|
+
allow_incomplete_array: allow_incomplete_array,
|
|
2464
|
+
allow_zero_length_array: allow_zero_length_array)
|
|
2465
|
+
[name_tok, build.call(base), function_params, pointer_quals]
|
|
2466
|
+
end
|
|
2467
|
+
|
|
2468
|
+
# declarator = pointer? direct-declarator. Parses the leading "*" run and
|
|
2469
|
+
# the direct-declarator, returning [name_token, build, function_params]
|
|
2470
|
+
# where `build` maps a base type to the declared type. The pointer prefix
|
|
2471
|
+
# is the outermost derivation textually but binds looser than the postfix
|
|
2472
|
+
# "()"/"[]", so it wraps the *base* first (becoming the innermost target,
|
|
2473
|
+
# e.g. the return or element type) and the direct-declarator's suffixes
|
|
2474
|
+
# then wrap that — which is exactly why "int *f(int)" is a function
|
|
2475
|
+
# returning "int *" while "int (*f)(int)" is a pointer to a function.
|
|
2476
|
+
def parse_declarator_builder(name_mode:, allow_incomplete_array:, allow_zero_length_array:)
|
|
2477
|
+
# A parenthesized declarator recurses back here through
|
|
2478
|
+
# #parse_declarator_core, so guarding this entry bounds "int
|
|
2479
|
+
# ((((x))))"-style nesting (and the matching build-lambda recursion,
|
|
2480
|
+
# which can only run as deep as the syntactic nesting that survived).
|
|
2481
|
+
with_nesting_guard(peek, "declarator") do
|
|
2482
|
+
# A GNU attribute may open a declarator ("int (__attribute__((packed))
|
|
2483
|
+
# *p)"), including the nested declarator inside a "(...)"; it qualifies
|
|
2484
|
+
# nothing this subset models, so it is accepted and discarded here just
|
|
2485
|
+
# as at every other declarator position.
|
|
2486
|
+
parse_attribute_specifiers
|
|
2487
|
+
pointer_quals = parse_pointer_qualifiers
|
|
2488
|
+
name_tok, direct_build, function_params =
|
|
2489
|
+
parse_direct_declarator(name_mode: name_mode,
|
|
2490
|
+
allow_incomplete_array: allow_incomplete_array,
|
|
2491
|
+
allow_zero_length_array: allow_zero_length_array)
|
|
2492
|
+
build = lambda do |base|
|
|
2493
|
+
type = base
|
|
2494
|
+
pointer_quals.each { type = Type::Pointer.new(type) }
|
|
2495
|
+
direct_build.call(type)
|
|
2496
|
+
end
|
|
2497
|
+
[name_tok, build, function_params, pointer_quals]
|
|
2498
|
+
end
|
|
2499
|
+
end
|
|
2500
|
+
|
|
2501
|
+
# A declarator's "*" run, each star optionally followed by a type-qualifier
|
|
2502
|
+
# list ("int * const p", "char * const * volatile q"). Returns one boolean
|
|
2503
|
+
# per star, true when that pointer level is const-qualified; "volatile" and
|
|
2504
|
+
# "_Atomic" are accepted and ignored, since M1 carries no qualified types.
|
|
2505
|
+
# The list is in
|
|
2506
|
+
# textual order, so the first star wraps the base first (the innermost
|
|
2507
|
+
# pointer) and the last is the outermost — the level that qualifies the
|
|
2508
|
+
# declared object.
|
|
2509
|
+
def parse_pointer_qualifiers
|
|
2510
|
+
quals = []
|
|
2511
|
+
while consume_punct("*")
|
|
2512
|
+
const_here = false
|
|
2513
|
+
loop do
|
|
2514
|
+
if peek.keyword?("const")
|
|
2515
|
+
const_here = true
|
|
2516
|
+
advance
|
|
2517
|
+
elsif peek.keyword?("volatile")
|
|
2518
|
+
advance
|
|
2519
|
+
elsif peek.keyword?("_Atomic")
|
|
2520
|
+
# "_Atomic" on this pointer level ("int * _Atomic p"): it qualifies
|
|
2521
|
+
# the pointer itself, which is one of the widths
|
|
2522
|
+
# ATOMIC_TYPE_WIDTHS admits whatever it points at, so there is
|
|
2523
|
+
# nothing to refuse and it is dropped like "volatile".
|
|
2524
|
+
advance
|
|
2525
|
+
elsif peek.keyword?("__attribute__")
|
|
2526
|
+
# A GNU attribute may follow a pointer's "*" ("int * __attribute__
|
|
2527
|
+
# ((x)) p", "int (ATTR *)(void)"); it qualifies nothing modeled
|
|
2528
|
+
# here, so it is accepted and discarded like the other qualifiers.
|
|
2529
|
+
parse_attribute_specifiers
|
|
2530
|
+
elsif restrict_qualifier?(peek)
|
|
2531
|
+
# A "restrict" (or "__restrict"/"__restrict__") qualifier on this
|
|
2532
|
+
# pointer level: carries no semantics in this subset, so consumed
|
|
2533
|
+
# and dropped, exactly as "volatile" is.
|
|
2534
|
+
advance
|
|
2535
|
+
else
|
|
2536
|
+
break
|
|
2537
|
+
end
|
|
2538
|
+
end
|
|
2539
|
+
quals << const_here
|
|
2540
|
+
end
|
|
2541
|
+
quals
|
|
2542
|
+
end
|
|
2543
|
+
|
|
2544
|
+
# Whether `tok` is one of the recognized "restrict" spellings — an ordinary
|
|
2545
|
+
# identifier, since none is a keyword here (see RESTRICT_SPELLINGS).
|
|
2546
|
+
def restrict_qualifier?(tok)
|
|
2547
|
+
tok.type == :ident && RESTRICT_SPELLINGS.include?(tok.value)
|
|
2548
|
+
end
|
|
2549
|
+
|
|
2550
|
+
# direct-declarator = (identifier | "(" declarator ")") suffix*, where a
|
|
2551
|
+
# suffix is a "[" size? "]" array or a "(" parameter-type-list? ")"
|
|
2552
|
+
# function. Returns [name_token, build, function_params].
|
|
2553
|
+
#
|
|
2554
|
+
# The core is a parenthesized declarator when a "(" is followed by a token
|
|
2555
|
+
# that opens a declarator (see #paren_starts_declarator?), an identifier
|
|
2556
|
+
# when one is present and the mode admits a name, or empty (an abstract
|
|
2557
|
+
# declarator's or an unnamed parameter's missing name). The suffixes bind
|
|
2558
|
+
# tighter than the pointer prefix and than an enclosing paren's suffix, so
|
|
2559
|
+
# `build` applies them to the base before the core — and, since a later
|
|
2560
|
+
# suffix binds tighter than an earlier one ("a[2][3]"), in reverse textual
|
|
2561
|
+
# order.
|
|
2562
|
+
#
|
|
2563
|
+
# `function_params` reports the parameter list of the function suffix
|
|
2564
|
+
# attached directly to the name: it is this level's first suffix when the
|
|
2565
|
+
# core is the identifier (or is absent), but the *inner* declarator's when
|
|
2566
|
+
# the core is parenthesized, so a name buried inside parentheses still
|
|
2567
|
+
# surfaces the suffix that makes it a function ("int (*g(int a))(int b)"
|
|
2568
|
+
# reports "int a", g's own parameters, not "int b").
|
|
2569
|
+
def parse_direct_declarator(name_mode:, allow_incomplete_array:, allow_zero_length_array:)
|
|
2570
|
+
name_tok, core_build, inner_params =
|
|
2571
|
+
parse_declarator_core(name_mode: name_mode,
|
|
2572
|
+
allow_incomplete_array: allow_incomplete_array,
|
|
2573
|
+
allow_zero_length_array: allow_zero_length_array)
|
|
2574
|
+
|
|
2575
|
+
suffixes = []
|
|
2576
|
+
loop do
|
|
2577
|
+
if peek.punct?("[")
|
|
2578
|
+
suffixes << parse_array_suffix(allow_incomplete: allow_incomplete_array,
|
|
2579
|
+
allow_zero_length: allow_zero_length_array)
|
|
2580
|
+
elsif peek.punct?("(")
|
|
2581
|
+
suffixes << parse_function_suffix
|
|
2582
|
+
else
|
|
2583
|
+
break
|
|
2584
|
+
end
|
|
2585
|
+
end
|
|
2586
|
+
|
|
2587
|
+
build = lambda do |base|
|
|
2588
|
+
type = base
|
|
2589
|
+
suffixes.reverse_each { |suffix| type = apply_declarator_suffix(suffix, type) }
|
|
2590
|
+
core_build.call(type)
|
|
2591
|
+
end
|
|
2592
|
+
|
|
2593
|
+
# A parenthesized core forwards the buried name's own function suffix;
|
|
2594
|
+
# every other core takes this level's outermost (first textual) suffix.
|
|
2595
|
+
function_params =
|
|
2596
|
+
if inner_params != :none
|
|
2597
|
+
inner_params
|
|
2598
|
+
elsif suffixes.first&.first == :function
|
|
2599
|
+
suffixes.first[1]
|
|
2600
|
+
end
|
|
2601
|
+
reject_unsurfaced_identifier_lists(suffixes, function_params)
|
|
2602
|
+
[name_tok, build, function_params]
|
|
2603
|
+
end
|
|
2604
|
+
|
|
2605
|
+
# Refuses an identifier list written on a suffix that is not the one making
|
|
2606
|
+
# the declared name a function — "int (*g)(a, b);", where the list sits on
|
|
2607
|
+
# the pointer's own suffix, or a second suffix on the same declarator. Only
|
|
2608
|
+
# the surfaced suffix can ever be a definition's parameter list, and only
|
|
2609
|
+
# that one reaches #reject_identifier_list through `function_params`; the
|
|
2610
|
+
# rest would otherwise be quietly read as an empty parameter list, since
|
|
2611
|
+
# that is the placeholder type #apply_declarator_suffix builds for them.
|
|
2612
|
+
def reject_unsurfaced_identifier_lists(suffixes, function_params)
|
|
2613
|
+
suffixes.each do |suffix|
|
|
2614
|
+
next unless suffix[1].is_a?(IdentifierList)
|
|
2615
|
+
next if suffix[1].equal?(function_params)
|
|
2616
|
+
|
|
2617
|
+
reject_identifier_list(suffix[1])
|
|
2618
|
+
end
|
|
2619
|
+
end
|
|
2620
|
+
|
|
2621
|
+
# The core of a direct-declarator, returning [name_token, build,
|
|
2622
|
+
# inner_params]. `inner_params` is the parenthesized inner declarator's
|
|
2623
|
+
# function_params when the core is "( declarator )", or the sentinel :none
|
|
2624
|
+
# when the core is an identifier or empty (so #parse_direct_declarator
|
|
2625
|
+
# knows whether to forward a buried name's suffix or read its own).
|
|
2626
|
+
#
|
|
2627
|
+
# `allow_incomplete_array` is forwarded into a parenthesized inner
|
|
2628
|
+
# declarator: the parentheses are only grouping, so the array buried in
|
|
2629
|
+
# "int (*fp[])(void) = { ... }" is the object's own array and its "[]" is
|
|
2630
|
+
# deducible from the initializer exactly as a bare "int fp[] = { ... }"
|
|
2631
|
+
# would be. Dropping the flag here rejected such declarators (6.7.6.3).
|
|
2632
|
+
def parse_declarator_core(name_mode:, allow_incomplete_array:, allow_zero_length_array:)
|
|
2633
|
+
if peek.punct?("(") && paren_starts_declarator?
|
|
2634
|
+
advance # "("
|
|
2635
|
+
name_tok, build, inner_params =
|
|
2636
|
+
parse_declarator_builder(name_mode: name_mode,
|
|
2637
|
+
allow_incomplete_array: allow_incomplete_array,
|
|
2638
|
+
allow_zero_length_array: allow_zero_length_array)
|
|
2639
|
+
expect_punct(")")
|
|
2640
|
+
[name_tok, build, inner_params]
|
|
2641
|
+
elsif peek.type == :ident && name_mode != :forbidden
|
|
2642
|
+
name_tok = advance
|
|
2643
|
+
[name_tok, ->(base) { base }, :none]
|
|
2644
|
+
elsif name_mode == :required
|
|
2645
|
+
error_at(peek, "expected identifier")
|
|
2646
|
+
else
|
|
2647
|
+
# An abstract declarator or an unnamed parameter: no core, so the type
|
|
2648
|
+
# is whatever the suffixes and pointer prefix make of the base.
|
|
2649
|
+
[nil, ->(base) { base }, :none]
|
|
2650
|
+
end
|
|
2651
|
+
end
|
|
2652
|
+
|
|
2653
|
+
# Whether a "(" at the core position opens a parenthesized declarator
|
|
2654
|
+
# rather than a function suffix's parameter list. It does exactly when the
|
|
2655
|
+
# following token begins a declarator — a "*", a "[", a nested "(", or an
|
|
2656
|
+
# identifier that is not a typedef name (a declared or redundantly
|
|
2657
|
+
# parenthesized name) — which is what disambiguates "int (*f)(int)" (a
|
|
2658
|
+
# parenthesized "*f") from the abstract "int (int)" (a function taking an
|
|
2659
|
+
# int). A type-specifier, a typedef name or a ")" after the "(" instead
|
|
2660
|
+
# opens a parameter list.
|
|
2661
|
+
def paren_starts_declarator?
|
|
2662
|
+
# A GNU attribute may sit right after the "(" and before the inner
|
|
2663
|
+
# declarator ("int (__attribute__((packed)) *p)(void)"); look past it so
|
|
2664
|
+
# the token that actually decides — a "*", "[", "(" or a plain
|
|
2665
|
+
# identifier — is the one classified. A parameter list whose first
|
|
2666
|
+
# parameter opens with an attribute ("(__attribute__((x)) int a)") still
|
|
2667
|
+
# resolves correctly: past the attribute sits a type-specifier, which is
|
|
2668
|
+
# none of those, so it stays a parameter list.
|
|
2669
|
+
nxt = @tokens[index_after_attributes(@pos + 1)]
|
|
2670
|
+
return false if nxt.nil?
|
|
2671
|
+
return true if nxt.punct?("*") || nxt.punct?("[") || nxt.punct?("(")
|
|
2672
|
+
|
|
2673
|
+
nxt.type == :ident && !typedef_name?(nxt.value)
|
|
2674
|
+
end
|
|
2675
|
+
|
|
2676
|
+
# The token index just past any run of "__attribute__ (( ... ))" specifiers
|
|
2677
|
+
# starting at `index`, matching parentheses so an argument list of any
|
|
2678
|
+
# shape is skipped whole. Used only for lookahead (nothing is consumed):
|
|
2679
|
+
# #paren_starts_declarator? peers past an attribute to the token that
|
|
2680
|
+
# classifies a "(". Returns `index` unchanged when no attribute is present.
|
|
2681
|
+
def index_after_attributes(index)
|
|
2682
|
+
while @tokens[index]&.keyword?("__attribute__")
|
|
2683
|
+
index += 1
|
|
2684
|
+
depth = 0
|
|
2685
|
+
loop do
|
|
2686
|
+
tok = @tokens[index]
|
|
2687
|
+
break if tok.nil? || tok.eof?
|
|
2688
|
+
|
|
2689
|
+
index += 1
|
|
2690
|
+
if tok.punct?("(")
|
|
2691
|
+
depth += 1
|
|
2692
|
+
elsif tok.punct?(")")
|
|
2693
|
+
depth -= 1
|
|
2694
|
+
break if depth.zero?
|
|
2695
|
+
end
|
|
2696
|
+
end
|
|
2697
|
+
end
|
|
2698
|
+
index
|
|
2699
|
+
end
|
|
2700
|
+
|
|
2701
|
+
# A direct-declarator's array suffix "[" size? "]". A bracketed length is
|
|
2702
|
+
# a constant-expression (6.6) folded to a positive Ruby Integer. A zero
|
|
2703
|
+
# bound is accepted only for a struct member as the GNU zero-length-array
|
|
2704
|
+
# extension; it has the same zero-size trailing-member layout as a
|
|
2705
|
+
# flexible array while retaining a complete array type. When
|
|
2706
|
+
# `allow_incomplete` is set (a variable or global with an initializer),
|
|
2707
|
+
# empty brackets "[]" leave the length nil for the initializer resolver to
|
|
2708
|
+
# infer (6.7.9p22); everywhere else "[]" is an error. Returns a suffix
|
|
2709
|
+
# descriptor [:array, length, bracket_token] applied later by
|
|
2710
|
+
# #apply_declarator_suffix.
|
|
2711
|
+
def parse_array_suffix(allow_incomplete:, allow_zero_length:)
|
|
2712
|
+
bracket_tok = advance # "["
|
|
2713
|
+
# A parameter's array declarator may carry type qualifiers and/or
|
|
2714
|
+
# "static" inside the brackets (6.7.6.3p7): they qualify the pointer the
|
|
2715
|
+
# parameter adjusts to, and "static" is an optimization hint. This subset
|
|
2716
|
+
# adjusts a parameter array to an *unqualified* pointer, so these are
|
|
2717
|
+
# parsed and discarded. They are accepted in any array declarator here,
|
|
2718
|
+
# not only a parameter's — a mild over-acceptance of a strict-conformance
|
|
2719
|
+
# error this subset does not otherwise diagnose.
|
|
2720
|
+
skip_array_qualifiers
|
|
2721
|
+
if peek.punct?("]")
|
|
2722
|
+
error_at(bracket_tok, "array size must be an integer constant") unless allow_incomplete
|
|
2723
|
+
advance # "]"
|
|
2724
|
+
length = nil
|
|
2725
|
+
elsif peek.punct?("*") && peek_ahead(1)&.punct?("]")
|
|
2726
|
+
# "[*]" is an unspecified-size (VLA) array bound in a function
|
|
2727
|
+
# prototype (6.7.6.2p4); treated like "[]", an incomplete array the
|
|
2728
|
+
# parameter adjustment turns into a pointer.
|
|
2729
|
+
error_at(bracket_tok, "'[*]' not allowed in this context") unless allow_incomplete
|
|
2730
|
+
advance # "*"
|
|
2731
|
+
advance # "]"
|
|
2732
|
+
length = nil
|
|
2733
|
+
else
|
|
2734
|
+
expr = parse_conditional_expression
|
|
2735
|
+
length = evaluate_constant_expression(expr, "array size must be an integer constant",
|
|
2736
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
2737
|
+
expect_punct("]")
|
|
2738
|
+
error_at(expr.token, "array size must be positive") if length.negative? ||
|
|
2739
|
+
(length.zero? && !allow_zero_length)
|
|
2740
|
+
end
|
|
2741
|
+
[:array, length, bracket_tok]
|
|
2742
|
+
end
|
|
2743
|
+
|
|
2744
|
+
# Consumes the qualifier/"static" run allowed at the start of a parameter's
|
|
2745
|
+
# array declarator brackets (6.7.6.3p7), in any order ("static const 5",
|
|
2746
|
+
# "const static 5"). All are discarded: this subset neither qualifies the
|
|
2747
|
+
# adjusted pointer nor acts on the "static" size hint. "restrict" appears
|
|
2748
|
+
# here in its identifier spellings (see #restrict_qualifier?).
|
|
2749
|
+
def skip_array_qualifiers
|
|
2750
|
+
loop do
|
|
2751
|
+
if peek.keyword?("const") || peek.keyword?("volatile") ||
|
|
2752
|
+
peek.keyword?("_Atomic") || peek.keyword?("static")
|
|
2753
|
+
advance
|
|
2754
|
+
elsif restrict_qualifier?(peek)
|
|
2755
|
+
advance
|
|
2756
|
+
else
|
|
2757
|
+
break
|
|
2758
|
+
end
|
|
2759
|
+
end
|
|
2760
|
+
end
|
|
2761
|
+
|
|
2762
|
+
# A direct-declarator's function suffix: "(" parameter-type-list? ")", or
|
|
2763
|
+
# the old-style "(" identifier-list ")". The parameters are parsed (and
|
|
2764
|
+
# array/function ones adjusted, see #parse_parameter_declaration) here so
|
|
2765
|
+
# the suffix can both build the function type and, when it belongs to a
|
|
2766
|
+
# real function, hand its Parameter objects back for the body. Returns
|
|
2767
|
+
# [:function, params, paren_token, variadic], `params` being either the
|
|
2768
|
+
# Parameter array of a prototype or an IdentifierList; the variadic flag
|
|
2769
|
+
# carries a trailing "..." forward to #apply_declarator_suffix so it lands
|
|
2770
|
+
# on the FunctionType.
|
|
2771
|
+
def parse_function_suffix
|
|
2772
|
+
paren_tok = advance # "("
|
|
2773
|
+
return [:function, parse_identifier_list(paren_tok), paren_tok, false] if identifier_list_ahead?
|
|
2774
|
+
|
|
2775
|
+
params, variadic = parse_parameter_type_list
|
|
2776
|
+
expect_punct(")")
|
|
2777
|
+
[:function, params, paren_tok, variadic]
|
|
2778
|
+
end
|
|
2779
|
+
|
|
2780
|
+
# Whether the just-opened "(" holds an identifier-list rather than a
|
|
2781
|
+
# parameter-type-list. A parameter declaration always begins with a
|
|
2782
|
+
# type-specifier — a keyword, or an identifier bound as a typedef name — so
|
|
2783
|
+
# a plain identifier at this position can only be a parameter *name*, which
|
|
2784
|
+
# is the old-style form. The empty "()" is neither: it stays the
|
|
2785
|
+
# no-parameter list it has always been here (C calls it an empty identifier
|
|
2786
|
+
# list, so "int f() { }" is an old-style definition of a function with no
|
|
2787
|
+
# parameters, which is the same thing this subset already builds).
|
|
2788
|
+
def identifier_list_ahead?
|
|
2789
|
+
peek.type == :ident && !typedef_name?(peek.value)
|
|
2790
|
+
end
|
|
2791
|
+
|
|
2792
|
+
# identifier-list = identifier ("," identifier)*, closed by the ")".
|
|
2793
|
+
# Repeating a name would leave the definition with two parameters of the
|
|
2794
|
+
# same name and no way to refer to either, so it is refused here rather
|
|
2795
|
+
# than at the binding.
|
|
2796
|
+
def parse_identifier_list(paren_tok)
|
|
2797
|
+
names = []
|
|
2798
|
+
loop do
|
|
2799
|
+
name_tok = peek
|
|
2800
|
+
error_at(name_tok, "expected identifier") unless name_tok.type == :ident
|
|
2801
|
+
if names.any? { |seen| seen.value == name_tok.value }
|
|
2802
|
+
error_at(name_tok, "duplicate parameter name '#{name_tok.value}'")
|
|
2803
|
+
end
|
|
2804
|
+
names << advance
|
|
2805
|
+
break unless peek.punct?(",")
|
|
2806
|
+
|
|
2807
|
+
advance # ","
|
|
2808
|
+
end
|
|
2809
|
+
expect_punct(")")
|
|
2810
|
+
IdentifierList.new(names, paren_tok)
|
|
2811
|
+
end
|
|
2812
|
+
|
|
2813
|
+
# Wraps `inner` in one declarator suffix, enforcing the constraints a
|
|
2814
|
+
# function or array derivation cannot satisfy (6.7.6.3): a function's
|
|
2815
|
+
# return type may be neither a function nor an array, and an array's
|
|
2816
|
+
# element may not be a function. A multidimensional array is an array whose
|
|
2817
|
+
# element is itself an array ("int a[2][13]" is a 2-element array of
|
|
2818
|
+
# "int[13]"); the suffixes are applied innermost-first (see
|
|
2819
|
+
# #parse_direct_declarator's reverse_each), so the inner dimension is a
|
|
2820
|
+
# complete array by the time the outer wraps it. Only that inner element
|
|
2821
|
+
# array may not be incomplete -- "int a[2][]" has element type "int[]" of
|
|
2822
|
+
# unknown stride (6.7.6.2p1) -- while the outermost dimension may still be
|
|
2823
|
+
# "[]" (deduced from an initializer or adjusted away on a parameter). The
|
|
2824
|
+
# suffix's own token (the "(" or "[") locates any diagnostic.
|
|
2825
|
+
def apply_declarator_suffix(suffix, inner)
|
|
2826
|
+
kind, data, tok, variadic = suffix
|
|
2827
|
+
if kind == :function
|
|
2828
|
+
error_at(tok, "function returning a function is not allowed") if inner.function?
|
|
2829
|
+
error_at(tok, "function returning an array is not allowed") if inner.array?
|
|
2830
|
+
# An identifier list carries no types yet — the declaration-list that
|
|
2831
|
+
# follows the declarator supplies them — so the type built here is a
|
|
2832
|
+
# placeholder with no parameters, which
|
|
2833
|
+
# #parse_old_style_function_definition replaces once they are known.
|
|
2834
|
+
# It matches what an empty "()" builds, so a declarator that never
|
|
2835
|
+
# reaches a definition still has a usable (if arity-less) type.
|
|
2836
|
+
params = data.is_a?(IdentifierList) ? [] : data.map(&:type)
|
|
2837
|
+
Type::FunctionType.new(inner, params, variadic)
|
|
2838
|
+
else
|
|
2839
|
+
error_at(tok, "array of functions is not allowed") if inner.function?
|
|
2840
|
+
error_at(tok, "array has incomplete element type") if inner.array? && inner.incomplete?
|
|
2841
|
+
# A struct ending in a flexible array member has no fixed size, so it
|
|
2842
|
+
# cannot be an array element (6.7.2.1p18; its stride is unknown).
|
|
2843
|
+
if inner.struct? && inner.flexible_array_member?
|
|
2844
|
+
error_at(tok, "array type has a struct with a flexible array member as its element")
|
|
2845
|
+
end
|
|
2846
|
+
Type::Array.new(inner, data)
|
|
2847
|
+
end
|
|
2848
|
+
end
|
|
2849
|
+
|
|
2850
|
+
# A parameter's declared type after the adjustments of 6.7.6.3: an array
|
|
2851
|
+
# parameter is adjusted to a pointer to its element ("int a[10]" is
|
|
2852
|
+
# "int *a") and a function parameter to a pointer to that function
|
|
2853
|
+
# ("int g(int)" is "int (*g)(int)"), so a call passes an address in either
|
|
2854
|
+
# case. Every other type is left as written.
|
|
2855
|
+
def adjust_parameter_type(type)
|
|
2856
|
+
if type.array?
|
|
2857
|
+
Type::Pointer.new(type.element)
|
|
2858
|
+
elsif type.function?
|
|
2859
|
+
Type::Pointer.new(type)
|
|
2860
|
+
else
|
|
2861
|
+
type
|
|
2862
|
+
end
|
|
2863
|
+
end
|
|
2864
|
+
|
|
2865
|
+
# Consumes and reports a punctuator when it is next, leaving the stream
|
|
2866
|
+
# untouched otherwise; lets the "*" run read one star at a time.
|
|
2867
|
+
def consume_punct(str)
|
|
2868
|
+
return false unless peek.punct?(str)
|
|
2869
|
+
|
|
2870
|
+
advance
|
|
2871
|
+
true
|
|
2872
|
+
end
|
|
2873
|
+
|
|
2874
|
+
def parse_statement
|
|
2875
|
+
if peek.keyword?("return")
|
|
2876
|
+
parse_return
|
|
2877
|
+
elsif peek.keyword?("if")
|
|
2878
|
+
parse_selection_statement
|
|
2879
|
+
elsif peek.keyword?("switch")
|
|
2880
|
+
parse_switch_statement
|
|
2881
|
+
elsif peek.keyword?("case")
|
|
2882
|
+
parse_case_statement
|
|
2883
|
+
elsif peek.keyword?("default")
|
|
2884
|
+
parse_default_statement
|
|
2885
|
+
elsif peek.keyword?("while")
|
|
2886
|
+
parse_while_statement
|
|
2887
|
+
elsif peek.keyword?("do")
|
|
2888
|
+
parse_do_while_statement
|
|
2889
|
+
elsif peek.keyword?("for")
|
|
2890
|
+
parse_for_statement
|
|
2891
|
+
elsif peek.keyword?("break")
|
|
2892
|
+
parse_break_statement
|
|
2893
|
+
elsif peek.keyword?("continue")
|
|
2894
|
+
parse_continue_statement
|
|
2895
|
+
elsif peek.keyword?("goto")
|
|
2896
|
+
parse_goto_statement
|
|
2897
|
+
elsif peek.keyword?("__asm__")
|
|
2898
|
+
parse_asm_statement
|
|
2899
|
+
elsif peek.punct?("{")
|
|
2900
|
+
parse_compound_statement
|
|
2901
|
+
# A bare identifier immediately followed by ":" opens a labeled
|
|
2902
|
+
# statement (a goto target); this two-token lookahead is what tells it
|
|
2903
|
+
# apart from an expression-statement that merely begins with a name.
|
|
2904
|
+
elsif peek.type == :ident && peek_ahead(1)&.punct?(":")
|
|
2905
|
+
parse_labeled_statement
|
|
2906
|
+
else
|
|
2907
|
+
parse_expression_statement
|
|
2908
|
+
end
|
|
2909
|
+
end
|
|
2910
|
+
|
|
2911
|
+
# A control-flow statement's body, parsed one nesting level deeper. The
|
|
2912
|
+
# body of an unbraced `if`/`while`/`do`/`for`/label recurses straight
|
|
2913
|
+
# back into #parse_statement, which would otherwise let a chain like
|
|
2914
|
+
# "if(1)if(1)..." recurse without ever passing through the block guard
|
|
2915
|
+
# and exhaust the Ruby stack (a SystemStackError the driver cannot
|
|
2916
|
+
# report as a diagnostic).
|
|
2917
|
+
def parse_nested_statement(token)
|
|
2918
|
+
with_nesting_guard(token, "statement") { parse_statement }
|
|
2919
|
+
end
|
|
2920
|
+
|
|
2921
|
+
# "return;" (a void return, `expr` nil) or "return expression;"; whether
|
|
2922
|
+
# a void function may omit the value (and a non-void one may not) is the
|
|
2923
|
+
# generator's job.
|
|
2924
|
+
def parse_return
|
|
2925
|
+
ret_tok = advance # "return"
|
|
2926
|
+
expr = peek.punct?(";") ? nil : parse_expression
|
|
2927
|
+
expect_punct(";")
|
|
2928
|
+
AST::Return.new(expr, ret_tok)
|
|
2929
|
+
end
|
|
2930
|
+
|
|
2931
|
+
# "else" binds to the nearest preceding "if": since the else clause is
|
|
2932
|
+
# consumed eagerly by the innermost recursive call, dangling-else
|
|
2933
|
+
# resolves the standard C way without extra bookkeeping.
|
|
2934
|
+
def parse_selection_statement
|
|
2935
|
+
if_tok = advance # "if"
|
|
2936
|
+
expect_punct("(")
|
|
2937
|
+
condition = parse_expression
|
|
2938
|
+
expect_punct(")")
|
|
2939
|
+
then_stmt = parse_nested_statement(if_tok)
|
|
2940
|
+
else_stmt = nil
|
|
2941
|
+
if peek.keyword?("else")
|
|
2942
|
+
else_tok = advance
|
|
2943
|
+
else_stmt = parse_nested_statement(else_tok)
|
|
2944
|
+
end
|
|
2945
|
+
AST::If.new(condition, then_stmt, else_stmt, if_tok)
|
|
2946
|
+
end
|
|
2947
|
+
|
|
2948
|
+
def parse_while_statement
|
|
2949
|
+
while_tok = advance # "while"
|
|
2950
|
+
expect_punct("(")
|
|
2951
|
+
condition = parse_expression
|
|
2952
|
+
expect_punct(")")
|
|
2953
|
+
body = parse_nested_statement(while_tok)
|
|
2954
|
+
AST::While.new(condition, body, while_tok)
|
|
2955
|
+
end
|
|
2956
|
+
|
|
2957
|
+
def parse_do_while_statement
|
|
2958
|
+
do_tok = advance # "do"
|
|
2959
|
+
body = parse_nested_statement(do_tok)
|
|
2960
|
+
expect_keyword("while")
|
|
2961
|
+
expect_punct("(")
|
|
2962
|
+
condition = parse_expression
|
|
2963
|
+
expect_punct(")")
|
|
2964
|
+
expect_punct(";")
|
|
2965
|
+
AST::DoWhile.new(body, condition, do_tok)
|
|
2966
|
+
end
|
|
2967
|
+
|
|
2968
|
+
def parse_for_statement
|
|
2969
|
+
for_tok = advance # "for"
|
|
2970
|
+
expect_punct("(")
|
|
2971
|
+
# C99 gives the for-loop's own parentheses a scope, so a tag, a typedef
|
|
2972
|
+
# or a variable declared in clause-1 is visible only through the loop.
|
|
2973
|
+
@tag_scopes.push({})
|
|
2974
|
+
@ordinary_scopes.push({})
|
|
2975
|
+
init = parse_for_init
|
|
2976
|
+
condition = peek.punct?(";") ? nil : parse_expression
|
|
2977
|
+
expect_punct(";")
|
|
2978
|
+
step = peek.punct?(")") ? nil : parse_expression
|
|
2979
|
+
expect_punct(")")
|
|
2980
|
+
body = parse_nested_statement(for_tok)
|
|
2981
|
+
@ordinary_scopes.pop
|
|
2982
|
+
@tag_scopes.pop
|
|
2983
|
+
AST::For.new(init, condition, step, body, for_tok)
|
|
2984
|
+
end
|
|
2985
|
+
|
|
2986
|
+
# Parses the for-loop's first clause, consuming its trailing ";" (a
|
|
2987
|
+
# declaration already does so; the other two branches do it explicitly).
|
|
2988
|
+
def parse_for_init
|
|
2989
|
+
if type_specifier?(peek)
|
|
2990
|
+
parse_declaration
|
|
2991
|
+
elsif peek.punct?(";")
|
|
2992
|
+
advance
|
|
2993
|
+
nil
|
|
2994
|
+
else
|
|
2995
|
+
expr = parse_expression
|
|
2996
|
+
expect_punct(";")
|
|
2997
|
+
expr
|
|
2998
|
+
end
|
|
2999
|
+
end
|
|
3000
|
+
|
|
3001
|
+
def parse_break_statement
|
|
3002
|
+
break_tok = advance # "break"
|
|
3003
|
+
expect_punct(";")
|
|
3004
|
+
AST::Break.new(break_tok)
|
|
3005
|
+
end
|
|
3006
|
+
|
|
3007
|
+
def parse_continue_statement
|
|
3008
|
+
continue_tok = advance # "continue"
|
|
3009
|
+
expect_punct(";")
|
|
3010
|
+
AST::Continue.new(continue_tok)
|
|
3011
|
+
end
|
|
3012
|
+
|
|
3013
|
+
# "goto identifier;": an unconditional jump to a label defined elsewhere
|
|
3014
|
+
# in the same function. Only the target's name is captured here; whether
|
|
3015
|
+
# it names a defined label is the generator's check, since the label may
|
|
3016
|
+
# appear textually after the goto (a forward jump).
|
|
3017
|
+
def parse_goto_statement
|
|
3018
|
+
goto_tok = advance # "goto"
|
|
3019
|
+
name_tok = expect_ident
|
|
3020
|
+
expect_punct(";")
|
|
3021
|
+
AST::Goto.new(name_tok.value, goto_tok)
|
|
3022
|
+
end
|
|
3023
|
+
|
|
3024
|
+
# A GNU inline-assembly statement (DESIGN R7): only the degenerate barrier
|
|
3025
|
+
# form is supported, spelled `__asm__` (never `asm`/`__asm`). The grammar
|
|
3026
|
+
# is `__asm__ volatile* "(" template (":" section)* ")" ";"`, "volatile"
|
|
3027
|
+
# admitting its GNU "__volatile"/"__volatile__" spellings too (both lex to
|
|
3028
|
+
# the same keyword token, see LexemeReader::KEYWORD_ALIASES). The template
|
|
3029
|
+
# must be an (adjacent run of) empty string literal(s); a non-empty one, or
|
|
3030
|
+
# any real operand in the output/input sections, is diagnosed. The clobber
|
|
3031
|
+
# section's strings ("memory", "cc", ...) are accepted and discarded.
|
|
3032
|
+
# Nothing is lowered — see AST::InlineAsm.
|
|
3033
|
+
def parse_asm_statement
|
|
3034
|
+
asm_tok = advance # "__asm__"
|
|
3035
|
+
# Any number of volatile qualifiers.
|
|
3036
|
+
advance while peek.keyword?("volatile")
|
|
3037
|
+
expect_punct("(")
|
|
3038
|
+
parse_asm_template(asm_tok)
|
|
3039
|
+
parse_asm_operand_sections(asm_tok) if peek.punct?(":")
|
|
3040
|
+
expect_punct(")")
|
|
3041
|
+
expect_punct(";")
|
|
3042
|
+
AST::InlineAsm.new(asm_tok)
|
|
3043
|
+
end
|
|
3044
|
+
|
|
3045
|
+
# The assembly template: one or more adjacent string literals, whose
|
|
3046
|
+
# concatenation must be empty. A non-empty template names real instructions
|
|
3047
|
+
# this backend cannot emit, so it is rejected at the keyword.
|
|
3048
|
+
def parse_asm_template(asm_tok)
|
|
3049
|
+
tok = peek
|
|
3050
|
+
error_at(tok, "expected string literal in inline assembly") unless tok.type == :string
|
|
3051
|
+
empty = true
|
|
3052
|
+
while peek.type == :string
|
|
3053
|
+
empty &&= peek.value.empty?
|
|
3054
|
+
advance
|
|
3055
|
+
end
|
|
3056
|
+
error_at(asm_tok, "non-empty inline assembly is not supported") unless empty
|
|
3057
|
+
end
|
|
3058
|
+
|
|
3059
|
+
# The ":"-separated sections after the template. By position the first is
|
|
3060
|
+
# the output operands and the second the input operands, both of which must
|
|
3061
|
+
# be empty (a real operand is unsupported); the third and any later section
|
|
3062
|
+
# is a clobber list of string literals, accepted and discarded.
|
|
3063
|
+
def parse_asm_operand_sections(asm_tok)
|
|
3064
|
+
section = 0
|
|
3065
|
+
while peek.punct?(":")
|
|
3066
|
+
advance # ":"
|
|
3067
|
+
if section < 2
|
|
3068
|
+
parse_asm_empty_operand_section(asm_tok)
|
|
3069
|
+
else
|
|
3070
|
+
parse_asm_clobbers(asm_tok)
|
|
3071
|
+
end
|
|
3072
|
+
section += 1
|
|
3073
|
+
end
|
|
3074
|
+
end
|
|
3075
|
+
|
|
3076
|
+
# An output/input operand section, which must be empty: the next token ends
|
|
3077
|
+
# the section (":" for the next one, ")" for the whole construct). Anything
|
|
3078
|
+
# else is an operand expression this subset does not support.
|
|
3079
|
+
def parse_asm_empty_operand_section(asm_tok)
|
|
3080
|
+
return if peek.punct?(":") || peek.punct?(")")
|
|
3081
|
+
|
|
3082
|
+
error_at(peek, "inline assembly operands are not supported")
|
|
3083
|
+
end
|
|
3084
|
+
|
|
3085
|
+
# A clobber section: a comma-separated list of string literals (or empty).
|
|
3086
|
+
# The names are discarded — this backend never reorders, so a clobber
|
|
3087
|
+
# constrains nothing.
|
|
3088
|
+
def parse_asm_clobbers(_asm_tok)
|
|
3089
|
+
return if peek.punct?(":") || peek.punct?(")")
|
|
3090
|
+
|
|
3091
|
+
loop do
|
|
3092
|
+
tok = peek
|
|
3093
|
+
unless tok.type == :string
|
|
3094
|
+
error_at(tok, "expected string literal in inline assembly clobber list")
|
|
3095
|
+
end
|
|
3096
|
+
advance
|
|
3097
|
+
break unless peek.punct?(",")
|
|
3098
|
+
|
|
3099
|
+
advance # ","
|
|
3100
|
+
end
|
|
3101
|
+
end
|
|
3102
|
+
|
|
3103
|
+
# "switch (expression) statement": the controlling expression and the body
|
|
3104
|
+
# in which case/default labels sit. The body is one statement (typically a
|
|
3105
|
+
# compound-statement); the parser does not check that any case is present
|
|
3106
|
+
# or well-placed — the generator collects the labels and diagnoses misuse.
|
|
3107
|
+
def parse_switch_statement
|
|
3108
|
+
switch_tok = advance # "switch"
|
|
3109
|
+
expect_punct("(")
|
|
3110
|
+
control = parse_expression
|
|
3111
|
+
expect_punct(")")
|
|
3112
|
+
body = parse_nested_statement(switch_tok)
|
|
3113
|
+
AST::Switch.new(control, body, switch_tok)
|
|
3114
|
+
end
|
|
3115
|
+
|
|
3116
|
+
# "case constant-expression : statement". The case constant is parsed as
|
|
3117
|
+
# a conditional-expression — constant-expression's production (6.6) — and
|
|
3118
|
+
# folded to a Ruby Integer on the spot; the labeled statement follows the
|
|
3119
|
+
# colon. A conditional operand's own ":" (as in "case 1 ? 2 : 3:") is
|
|
3120
|
+
# consumed by conditional-expression itself, leaving exactly the label's
|
|
3121
|
+
# ":" for #expect_punct here. Whether this case sits inside a switch, and
|
|
3122
|
+
# whether its value is unique, is left to the generator.
|
|
3123
|
+
def parse_case_statement
|
|
3124
|
+
case_tok = advance # "case"
|
|
3125
|
+
expr = parse_conditional_expression
|
|
3126
|
+
value = evaluate_constant_expression(expr, "case label does not reduce to an integer constant",
|
|
3127
|
+
sizeof_expr: method(:fold_time_sizeof))
|
|
3128
|
+
expect_punct(":")
|
|
3129
|
+
body = parse_nested_statement(case_tok)
|
|
3130
|
+
AST::Case.new(value, body, case_tok)
|
|
3131
|
+
end
|
|
3132
|
+
|
|
3133
|
+
# "default : statement": the fall-through label of a switch, carrying no
|
|
3134
|
+
# constant. At most one may appear per switch, which the generator checks.
|
|
3135
|
+
def parse_default_statement
|
|
3136
|
+
default_tok = advance # "default"
|
|
3137
|
+
expect_punct(":")
|
|
3138
|
+
body = parse_nested_statement(default_tok)
|
|
3139
|
+
AST::Default.new(body, default_tok)
|
|
3140
|
+
end
|
|
3141
|
+
|
|
3142
|
+
# "identifier : statement": a labeled statement, the target of a goto. The
|
|
3143
|
+
# identifier and its ":" have already been confirmed by the two-token
|
|
3144
|
+
# lookahead in #parse_statement; the prefixed statement follows.
|
|
3145
|
+
def parse_labeled_statement
|
|
3146
|
+
name_tok = advance # identifier
|
|
3147
|
+
advance # ":"
|
|
3148
|
+
body = parse_nested_statement(name_tok)
|
|
3149
|
+
AST::Label.new(name_tok.value, body, name_tok)
|
|
3150
|
+
end
|
|
3151
|
+
|
|
3152
|
+
def parse_compound_statement
|
|
3153
|
+
brace_tok = expect_punct("{")
|
|
3154
|
+
with_nesting_guard(brace_tok, "block") do
|
|
3155
|
+
# A nested block introduces its own tag and ordinary scopes, mirroring
|
|
3156
|
+
# its variable scope: a struct, an enum constant or a typedef defined
|
|
3157
|
+
# here shadows an outer one and is gone at "}".
|
|
3158
|
+
@tag_scopes.push({})
|
|
3159
|
+
@ordinary_scopes.push({})
|
|
3160
|
+
items = []
|
|
3161
|
+
items.concat(parse_block_item) until peek.punct?("}")
|
|
3162
|
+
@ordinary_scopes.pop
|
|
3163
|
+
@tag_scopes.pop
|
|
3164
|
+
expect_punct("}")
|
|
3165
|
+
AST::Block.new(items, brace_tok)
|
|
3166
|
+
end
|
|
3167
|
+
end
|
|
3168
|
+
|
|
3169
|
+
def parse_expression_statement
|
|
3170
|
+
tok = peek
|
|
3171
|
+
if tok.punct?(";")
|
|
3172
|
+
advance
|
|
3173
|
+
AST::EmptyStmt.new(tok)
|
|
3174
|
+
else
|
|
3175
|
+
expr = parse_expression
|
|
3176
|
+
expect_punct(";")
|
|
3177
|
+
AST::ExpressionStmt.new(expr, tok)
|
|
3178
|
+
end
|
|
3179
|
+
end
|
|
3180
|
+
|
|
3181
|
+
# expression = assignment-expression ("," assignment-expression)*: the
|
|
3182
|
+
# comma operator, left-associative. Each left operand is evaluated for its
|
|
3183
|
+
# side effects and discarded; the last operand's value and type are the
|
|
3184
|
+
# whole expression's. Every context where a comma is a *separator* rather
|
|
3185
|
+
# than the operator (a call's arguments, a run of declarators, a global
|
|
3186
|
+
# initializer) bypasses this and calls #parse_assignment_expression
|
|
3187
|
+
# directly, so those commas keep their meaning; only the contexts that
|
|
3188
|
+
# take a full expression (a parenthesized expression, a subscript, an
|
|
3189
|
+
# expression-statement, the for-clauses, a control condition, a return,
|
|
3190
|
+
# the middle of "?:") reach the comma operator here.
|
|
3191
|
+
def parse_expression
|
|
3192
|
+
node = parse_assignment_expression
|
|
3193
|
+
while peek.punct?(",")
|
|
3194
|
+
tok = advance
|
|
3195
|
+
node = AST::Comma.new(node, parse_assignment_expression, tok)
|
|
3196
|
+
end
|
|
3197
|
+
node
|
|
3198
|
+
end
|
|
3199
|
+
|
|
3200
|
+
# Right-associative: "a = b = c" parses as "a = (b = c)"; likewise for
|
|
3201
|
+
# the compound-assignment operators. The right operand recurses back here,
|
|
3202
|
+
# so a long "a = b = c = ..." chain deepens through this method rather than
|
|
3203
|
+
# through #parse_cast_expression (which has already returned by the time the
|
|
3204
|
+
# "=" is seen); it therefore carries its own nesting guard.
|
|
3205
|
+
def parse_assignment_expression
|
|
3206
|
+
with_nesting_guard(peek, "expression") do
|
|
3207
|
+
node = parse_conditional_expression
|
|
3208
|
+
tok = peek
|
|
3209
|
+
if tok.punct?("=")
|
|
3210
|
+
advance
|
|
3211
|
+
error_at(tok, "expression is not assignable") unless assignable?(node)
|
|
3212
|
+
AST::Assignment.new(node, parse_assignment_expression, tok)
|
|
3213
|
+
elsif (op = tok.type == :punct ? COMPOUND_ASSIGNMENT_OPERATORS[tok.value] : nil)
|
|
3214
|
+
advance
|
|
3215
|
+
error_at(tok, "expression is not assignable") unless assignable?(node)
|
|
3216
|
+
AST::CompoundAssignment.new(op, node, parse_assignment_expression, tok)
|
|
3217
|
+
else
|
|
3218
|
+
node
|
|
3219
|
+
end
|
|
3220
|
+
end
|
|
3221
|
+
end
|
|
3222
|
+
|
|
3223
|
+
# Syntactically, only a variable reference, a subscript "e[i]", a struct
|
|
3224
|
+
# member access "e.m"/"e->m" or a dereference "*expr" can appear on the
|
|
3225
|
+
# left of "=" (or "++"/"--", or a compound-assignment operator). Whether
|
|
3226
|
+
# the target's type is actually assignable (e.g. not an array) is checked
|
|
3227
|
+
# later by the generator.
|
|
3228
|
+
def assignable?(node)
|
|
3229
|
+
node.is_a?(AST::VariableRef) ||
|
|
3230
|
+
node.is_a?(AST::Subscript) ||
|
|
3231
|
+
node.is_a?(AST::MemberAccess) ||
|
|
3232
|
+
(node.is_a?(AST::Unary) && node.op == :deref)
|
|
3233
|
+
end
|
|
3234
|
+
|
|
3235
|
+
# "?:" is right-associative: "a ? b : c ? d : e" parses as
|
|
3236
|
+
# "a ? b : (c ? d : e)". The middle operand is a full expression (not a
|
|
3237
|
+
# conditional-expression), per ISO C, so a bare assignment may appear
|
|
3238
|
+
# there without parentheses.
|
|
3239
|
+
# Both arms recurse — the "then" through #parse_expression and the "else"
|
|
3240
|
+
# directly — so a "a ? b : c ? d : ..." chain deepens through this method,
|
|
3241
|
+
# above where #parse_cast_expression's guard would catch it; it is guarded
|
|
3242
|
+
# here on the shared counter.
|
|
3243
|
+
def parse_conditional_expression
|
|
3244
|
+
with_nesting_guard(peek, "expression") do
|
|
3245
|
+
node = parse_logical_or_expression
|
|
3246
|
+
if peek.punct?("?")
|
|
3247
|
+
question_tok = advance
|
|
3248
|
+
then_expr = parse_expression
|
|
3249
|
+
expect_punct(":")
|
|
3250
|
+
else_expr = parse_conditional_expression
|
|
3251
|
+
AST::Conditional.new(node, then_expr, else_expr, question_tok)
|
|
3252
|
+
else
|
|
3253
|
+
node
|
|
3254
|
+
end
|
|
3255
|
+
end
|
|
3256
|
+
end
|
|
3257
|
+
|
|
3258
|
+
def parse_logical_or_expression
|
|
3259
|
+
node = parse_logical_and_expression
|
|
3260
|
+
while peek.punct?("||")
|
|
3261
|
+
tok = advance
|
|
3262
|
+
node = AST::LogicalOr.new(node, parse_logical_and_expression, tok)
|
|
3263
|
+
end
|
|
3264
|
+
node
|
|
3265
|
+
end
|
|
3266
|
+
|
|
3267
|
+
def parse_logical_and_expression
|
|
3268
|
+
node = parse_inclusive_or_expression
|
|
3269
|
+
while peek.punct?("&&")
|
|
3270
|
+
tok = advance
|
|
3271
|
+
node = AST::LogicalAnd.new(node, parse_inclusive_or_expression, tok)
|
|
3272
|
+
end
|
|
3273
|
+
node
|
|
3274
|
+
end
|
|
3275
|
+
|
|
3276
|
+
# The three bitwise tiers sit between logical-AND and equality, in ISO C
|
|
3277
|
+
# order (inclusive-OR loosest, then exclusive-OR, then AND). The binary
|
|
3278
|
+
# "&" is recognized only here, between two operands; a "&" that opens a
|
|
3279
|
+
# unary-expression is the address-of operator, parsed far deeper, so the
|
|
3280
|
+
# two never collide (and the lexer has already split off "&&" and "&=").
|
|
3281
|
+
def parse_inclusive_or_expression
|
|
3282
|
+
parse_left_associative(INCLUSIVE_OR_OPERATORS) { parse_exclusive_or_expression }
|
|
3283
|
+
end
|
|
3284
|
+
|
|
3285
|
+
def parse_exclusive_or_expression
|
|
3286
|
+
parse_left_associative(EXCLUSIVE_OR_OPERATORS) { parse_and_expression }
|
|
3287
|
+
end
|
|
3288
|
+
|
|
3289
|
+
def parse_and_expression
|
|
3290
|
+
parse_left_associative(AND_OPERATORS) { parse_equality_expression }
|
|
3291
|
+
end
|
|
3292
|
+
|
|
3293
|
+
def parse_equality_expression
|
|
3294
|
+
parse_left_associative(EQUALITY_OPERATORS) { parse_relational_expression }
|
|
3295
|
+
end
|
|
3296
|
+
|
|
3297
|
+
def parse_relational_expression
|
|
3298
|
+
parse_left_associative(RELATIONAL_OPERATORS) { parse_shift_expression }
|
|
3299
|
+
end
|
|
3300
|
+
|
|
3301
|
+
# shift-expression sits between relational and additive, so "1 << 2 + 3"
|
|
3302
|
+
# shifts by 5 (additive binds tighter) while "1 + 2 << 3" adds first
|
|
3303
|
+
# (shift is looser than additive but tighter than relational).
|
|
3304
|
+
def parse_shift_expression
|
|
3305
|
+
parse_left_associative(SHIFT_OPERATORS) { parse_additive_expression }
|
|
3306
|
+
end
|
|
3307
|
+
|
|
3308
|
+
def parse_additive_expression
|
|
3309
|
+
parse_left_associative(ADDITIVE_OPERATORS) { parse_multiplicative_expression }
|
|
3310
|
+
end
|
|
3311
|
+
|
|
3312
|
+
def parse_multiplicative_expression
|
|
3313
|
+
parse_left_associative(MULTIPLICATIVE_OPERATORS) { parse_cast_expression }
|
|
3314
|
+
end
|
|
3315
|
+
|
|
3316
|
+
# cast-expression = "(" type-name ")" cast-expression | unary-expression.
|
|
3317
|
+
# A "(" begins a cast only when a type-specifier follows it; otherwise it
|
|
3318
|
+
# is an ordinary parenthesized expression, left for unary-expression (and
|
|
3319
|
+
# finally primary-expression) to consume. #type_specifier? settles the
|
|
3320
|
+
# choice with a single token of lookahead — a type keyword or a typedef
|
|
3321
|
+
# name after "(" — so "(int)x" and "(T)x" are casts while "(x)(y)", x
|
|
3322
|
+
# being neither, is a call.
|
|
3323
|
+
# This is the single choke point every deepening expression form re-enters
|
|
3324
|
+
# exactly once per nesting level — a parenthesized "( expression )" (via
|
|
3325
|
+
# primary-expression), a "!"/"-"/"*"/... unary chain, a "( type-name )"
|
|
3326
|
+
# cast chain, a "?:" arm, a subscript or a call argument all descend back
|
|
3327
|
+
# through here — so guarding it alone bounds the depth of the whole
|
|
3328
|
+
# expression grammar with no double counting.
|
|
3329
|
+
def parse_cast_expression
|
|
3330
|
+
with_nesting_guard(peek, "expression") do
|
|
3331
|
+
# A "__extension__" prefix (a GNU marker with no semantic effect) binds
|
|
3332
|
+
# like a cast operator: it is consumed here and the cast-expression it
|
|
3333
|
+
# governs is parsed in its place ("__extension__ x", "y = __extension__ z").
|
|
3334
|
+
if peek.keyword?("__extension__")
|
|
3335
|
+
advance
|
|
3336
|
+
parse_cast_expression
|
|
3337
|
+
elsif peek.punct?("(") && peek_ahead(1) && type_specifier?(peek_ahead(1))
|
|
3338
|
+
paren_tok = advance # "("
|
|
3339
|
+
# An unsized "[]" is admitted here so a compound literal can infer its
|
|
3340
|
+
# bound ("(int[]){1,2,3}"); a plain cast to that incomplete type is
|
|
3341
|
+
# rejected below, once the following "{" (or its absence) settles the
|
|
3342
|
+
# two forms apart.
|
|
3343
|
+
type = parse_type_name(allow_incomplete_array: true)
|
|
3344
|
+
expect_punct(")")
|
|
3345
|
+
# A "{" after "( type-name )" opens a compound literal (6.5.2.5),
|
|
3346
|
+
# not a cast: "( type-name ) { initializer-list }" builds an unnamed
|
|
3347
|
+
# object of that type. It is a postfix-expression, so any trailing
|
|
3348
|
+
# postfix suffix ("(json_frame){...}.type") binds to it. Every other
|
|
3349
|
+
# token keeps the ordinary cast reading "( type-name ) cast-expr".
|
|
3350
|
+
if peek.punct?("{")
|
|
3351
|
+
parse_postfix_suffixes(parse_compound_literal(type, paren_tok))
|
|
3352
|
+
else
|
|
3353
|
+
if type.array? && type.length.nil?
|
|
3354
|
+
error_at(paren_tok, "array size missing in cast to array type")
|
|
3355
|
+
end
|
|
3356
|
+
AST::Cast.new(type, parse_cast_expression, paren_tok)
|
|
3357
|
+
end
|
|
3358
|
+
else
|
|
3359
|
+
parse_unary_expression
|
|
3360
|
+
end
|
|
3361
|
+
end
|
|
3362
|
+
end
|
|
3363
|
+
|
|
3364
|
+
# Generic left-associative binary parser: the block parses one operand
|
|
3365
|
+
# at the next-tighter precedence tier; `operator_table` maps the
|
|
3366
|
+
# punctuators of this tier to AST operators.
|
|
3367
|
+
def parse_left_associative(operator_table)
|
|
3368
|
+
node = yield
|
|
3369
|
+
loop do
|
|
3370
|
+
tok = peek
|
|
3371
|
+
ast_op = tok.type == :punct ? operator_table[tok.value] : nil
|
|
3372
|
+
return node unless ast_op
|
|
3373
|
+
|
|
3374
|
+
advance
|
|
3375
|
+
node = AST::Binary.new(ast_op, node, yield, tok)
|
|
3376
|
+
end
|
|
3377
|
+
end
|
|
3378
|
+
|
|
3379
|
+
# The unary tier recurses through several forms that never pass through
|
|
3380
|
+
# #parse_cast_expression — "sizeof sizeof ... x" recurses back here, and a
|
|
3381
|
+
# prefix "++"/"--" likewise — so a chain of them would escape a guard placed
|
|
3382
|
+
# only on the cast tier. Guarding the unary entry catches those, and the
|
|
3383
|
+
# "!"/"-"/... operators (which do recurse through the cast tier) as well.
|
|
3384
|
+
def parse_unary_expression
|
|
3385
|
+
with_nesting_guard(peek, "expression") do
|
|
3386
|
+
if peek.keyword?("sizeof")
|
|
3387
|
+
parse_sizeof
|
|
3388
|
+
elsif peek.keyword?("_Alignof")
|
|
3389
|
+
parse_alignof
|
|
3390
|
+
elsif peek.keyword?("__builtin_va_start")
|
|
3391
|
+
parse_va_start
|
|
3392
|
+
elsif peek.keyword?("__builtin_va_arg")
|
|
3393
|
+
parse_va_arg
|
|
3394
|
+
elsif peek.keyword?("__builtin_va_end")
|
|
3395
|
+
parse_va_end
|
|
3396
|
+
elsif peek.keyword?("__builtin_va_copy")
|
|
3397
|
+
parse_va_copy
|
|
3398
|
+
elsif peek.keyword?("__builtin_expect")
|
|
3399
|
+
parse_builtin_expect
|
|
3400
|
+
elsif peek.keyword?("__builtin_alloca")
|
|
3401
|
+
parse_builtin_alloca
|
|
3402
|
+
elsif peek.keyword?("__builtin_offsetof")
|
|
3403
|
+
parse_builtin_offsetof
|
|
3404
|
+
elsif peek.keyword?("__builtin_constant_p")
|
|
3405
|
+
parse_builtin_constant_p
|
|
3406
|
+
elsif peek.keyword?("__builtin_choose_expr")
|
|
3407
|
+
parse_builtin_choose_expr
|
|
3408
|
+
elsif peek.keyword?("__builtin_ctz")
|
|
3409
|
+
parse_builtin_bit_scan(:forward, 4)
|
|
3410
|
+
elsif peek.keyword?("__builtin_ctzll")
|
|
3411
|
+
parse_builtin_bit_scan(:forward, 8)
|
|
3412
|
+
elsif peek.keyword?("__builtin_clz")
|
|
3413
|
+
parse_builtin_bit_scan(:reverse, 4)
|
|
3414
|
+
elsif peek.keyword?("__builtin_clzll")
|
|
3415
|
+
parse_builtin_bit_scan(:reverse, 8)
|
|
3416
|
+
elsif peek.keyword?("__builtin_unreachable")
|
|
3417
|
+
parse_builtin_unreachable
|
|
3418
|
+
elsif peek.keyword?("__builtin_memcpy")
|
|
3419
|
+
parse_builtin_memcpy
|
|
3420
|
+
elsif peek.type == :keyword && OVERFLOW_BUILTINS.key?(peek.value)
|
|
3421
|
+
parse_builtin_overflow
|
|
3422
|
+
elsif peek.type == :keyword && ATOMIC_BUILTINS.key?(peek.value)
|
|
3423
|
+
parse_builtin_atomic
|
|
3424
|
+
elsif peek.type == :keyword && SYNC_BUILTINS.key?(peek.value)
|
|
3425
|
+
parse_builtin_sync
|
|
3426
|
+
elsif peek.punct?("+")
|
|
3427
|
+
advance # unary + is a no-op; fold it away
|
|
3428
|
+
parse_cast_expression
|
|
3429
|
+
elsif peek.punct?("-")
|
|
3430
|
+
op_tok = advance
|
|
3431
|
+
AST::Unary.new(:neg, parse_cast_expression, op_tok)
|
|
3432
|
+
elsif peek.punct?("!")
|
|
3433
|
+
op_tok = advance
|
|
3434
|
+
AST::Unary.new(:not, parse_cast_expression, op_tok)
|
|
3435
|
+
elsif peek.punct?("~")
|
|
3436
|
+
parse_bitwise_not
|
|
3437
|
+
elsif peek.punct?("&")
|
|
3438
|
+
op_tok = advance
|
|
3439
|
+
AST::Unary.new(:addr, parse_cast_expression, op_tok)
|
|
3440
|
+
elsif peek.punct?("*")
|
|
3441
|
+
op_tok = advance
|
|
3442
|
+
AST::Unary.new(:deref, parse_cast_expression, op_tok)
|
|
3443
|
+
elsif peek.punct?("++") || peek.punct?("--")
|
|
3444
|
+
parse_prefix_inc_dec
|
|
3445
|
+
else
|
|
3446
|
+
parse_postfix_expression
|
|
3447
|
+
end
|
|
3448
|
+
end
|
|
3449
|
+
end
|
|
3450
|
+
|
|
3451
|
+
# "~x" is the one's-complement of an arithmetic operand. Rather than carry
|
|
3452
|
+
# a dedicated bitwise-not through the IR, it is desugared here to the
|
|
3453
|
+
# exclusive-or "x ^ -1": flipping every bit is an xor with all-ones, and
|
|
3454
|
+
# -1 is all-ones in every integer width. The generator then type-checks
|
|
3455
|
+
# and lowers it as an ordinary ":xor", so a pointer or struct operand is
|
|
3456
|
+
# rejected as an invalid binary operand exactly like "x ^ 1" would be. The
|
|
3457
|
+
# "~" token locates both the literal and the node for diagnostics.
|
|
3458
|
+
def parse_bitwise_not
|
|
3459
|
+
op_tok = advance # "~"
|
|
3460
|
+
operand = parse_cast_expression
|
|
3461
|
+
AST::Binary.new(:xor, operand, AST::IntLit.new(-1, op_tok, Type::Int), op_tok)
|
|
3462
|
+
end
|
|
3463
|
+
|
|
3464
|
+
def parse_prefix_inc_dec
|
|
3465
|
+
op_tok = advance
|
|
3466
|
+
op = op_tok.value == "++" ? :add : :sub
|
|
3467
|
+
operand = parse_unary_expression
|
|
3468
|
+
error_at(op_tok, "expression is not assignable") unless assignable?(operand)
|
|
3469
|
+
AST::IncDec.new(op, operand, true, op_tok)
|
|
3470
|
+
end
|
|
3471
|
+
|
|
3472
|
+
# "sizeof" measures either a parenthesized type-name ("sizeof(char *)")
|
|
3473
|
+
# or the result type of a unary-expression ("sizeof x", "sizeof(a)"). A
|
|
3474
|
+
# "(" right after the keyword is only a type-name when a type-specifier
|
|
3475
|
+
# ("int" or "char") follows; otherwise it is an ordinary parenthesized
|
|
3476
|
+
# operand, so it is left for unary-expression to consume.
|
|
3477
|
+
def parse_sizeof
|
|
3478
|
+
sizeof_tok = advance # "sizeof"
|
|
3479
|
+
if peek.punct?("(") && peek_ahead(1) && type_specifier?(peek_ahead(1))
|
|
3480
|
+
advance # "("
|
|
3481
|
+
type = parse_type_name
|
|
3482
|
+
expect_punct(")")
|
|
3483
|
+
AST::SizeofType.new(type, sizeof_tok)
|
|
3484
|
+
else
|
|
3485
|
+
AST::SizeofExpr.new(parse_unary_expression, sizeof_tok)
|
|
3486
|
+
end
|
|
3487
|
+
end
|
|
3488
|
+
|
|
3489
|
+
# "_Alignof ( type-name )" (6.5.3.4): the alignment of a written type. Only
|
|
3490
|
+
# the parenthesized type-name form exists — there is no operand form as
|
|
3491
|
+
# sizeof has — so the "(" and type-name are read unconditionally. The
|
|
3492
|
+
# generator folds it to a size_t constant, like sizeof of a type.
|
|
3493
|
+
def parse_alignof
|
|
3494
|
+
alignof_tok = advance # "_Alignof"
|
|
3495
|
+
expect_punct("(")
|
|
3496
|
+
type = parse_type_name
|
|
3497
|
+
expect_punct(")")
|
|
3498
|
+
AST::AlignofType.new(type, alignof_tok)
|
|
3499
|
+
end
|
|
3500
|
+
|
|
3501
|
+
# "__builtin_va_start ( assignment-expression , identifier )": the va_list
|
|
3502
|
+
# to initialize and the name of the last fixed parameter (a bare
|
|
3503
|
+
# identifier, not an expression, since the ABI locates the variable part
|
|
3504
|
+
# relative to that parameter). The generator checks the name against the
|
|
3505
|
+
# enclosing function's last named parameter.
|
|
3506
|
+
def parse_va_start
|
|
3507
|
+
keyword_tok = advance # "__builtin_va_start"
|
|
3508
|
+
expect_punct("(")
|
|
3509
|
+
ap = parse_assignment_expression
|
|
3510
|
+
expect_punct(",")
|
|
3511
|
+
name_tok = expect_ident
|
|
3512
|
+
expect_punct(")")
|
|
3513
|
+
AST::VaStart.new(ap, name_tok.value, keyword_tok)
|
|
3514
|
+
end
|
|
3515
|
+
|
|
3516
|
+
# "__builtin_va_arg ( assignment-expression , type-name )": the va_list and
|
|
3517
|
+
# the type-name the next argument is fetched as. The type-name uses the
|
|
3518
|
+
# same abstract-declarator grammar as sizeof/casts.
|
|
3519
|
+
def parse_va_arg
|
|
3520
|
+
keyword_tok = advance # "__builtin_va_arg"
|
|
3521
|
+
expect_punct("(")
|
|
3522
|
+
ap = parse_assignment_expression
|
|
3523
|
+
expect_punct(",")
|
|
3524
|
+
type = parse_type_name
|
|
3525
|
+
expect_punct(")")
|
|
3526
|
+
AST::VaArg.new(ap, type, keyword_tok)
|
|
3527
|
+
end
|
|
3528
|
+
|
|
3529
|
+
# "__builtin_va_end ( assignment-expression )": the va_list whose traversal
|
|
3530
|
+
# ends. A no-op on System V beyond the operand's type check.
|
|
3531
|
+
def parse_va_end
|
|
3532
|
+
keyword_tok = advance # "__builtin_va_end"
|
|
3533
|
+
expect_punct("(")
|
|
3534
|
+
ap = parse_assignment_expression
|
|
3535
|
+
expect_punct(")")
|
|
3536
|
+
AST::VaEnd.new(ap, keyword_tok)
|
|
3537
|
+
end
|
|
3538
|
+
|
|
3539
|
+
# "__builtin_va_copy ( assignment-expression , assignment-expression )":
|
|
3540
|
+
# the destination and source va_lists, whose state the generator copies as
|
|
3541
|
+
# a whole tag from the second to the first.
|
|
3542
|
+
def parse_va_copy
|
|
3543
|
+
keyword_tok = advance # "__builtin_va_copy"
|
|
3544
|
+
expect_punct("(")
|
|
3545
|
+
dest = parse_assignment_expression
|
|
3546
|
+
expect_punct(",")
|
|
3547
|
+
src = parse_assignment_expression
|
|
3548
|
+
expect_punct(")")
|
|
3549
|
+
AST::VaCopy.new(dest, src, keyword_tok)
|
|
3550
|
+
end
|
|
3551
|
+
|
|
3552
|
+
# "__builtin_expect ( exp , c )": exactly two arguments, parsed as an
|
|
3553
|
+
# ordinary argument list so a wrong count is reported as an arity error
|
|
3554
|
+
# rather than a bare punctuator-mismatch. The generator settles their
|
|
3555
|
+
# conversion to `long`.
|
|
3556
|
+
def parse_builtin_expect
|
|
3557
|
+
keyword_tok = advance # "__builtin_expect"
|
|
3558
|
+
expect_punct("(")
|
|
3559
|
+
args = parse_argument_expression_list
|
|
3560
|
+
expect_punct(")")
|
|
3561
|
+
unless args.size == 2
|
|
3562
|
+
error_at(keyword_tok, "'__builtin_expect' expects 2 arguments, have #{args.size}")
|
|
3563
|
+
end
|
|
3564
|
+
AST::BuiltinExpect.new(args[0], args[1], keyword_tok)
|
|
3565
|
+
end
|
|
3566
|
+
|
|
3567
|
+
# "__builtin_alloca ( n )": exactly one argument, the byte count. Like
|
|
3568
|
+
# __builtin_expect it is parsed as an argument list so a wrong count is an
|
|
3569
|
+
# arity diagnostic.
|
|
3570
|
+
def parse_builtin_alloca
|
|
3571
|
+
keyword_tok = advance # "__builtin_alloca"
|
|
3572
|
+
expect_punct("(")
|
|
3573
|
+
args = parse_argument_expression_list
|
|
3574
|
+
expect_punct(")")
|
|
3575
|
+
unless args.size == 1
|
|
3576
|
+
error_at(keyword_tok, "'__builtin_alloca' expects 1 argument, have #{args.size}")
|
|
3577
|
+
end
|
|
3578
|
+
AST::BuiltinAlloca.new(args[0], keyword_tok)
|
|
3579
|
+
end
|
|
3580
|
+
|
|
3581
|
+
# "__builtin_offsetof ( type-name , member-designator )": the aggregate
|
|
3582
|
+
# type and the member whose offset is wanted. The member-designator is a
|
|
3583
|
+
# leading member name followed by any run of ".name" and "[ expression ]"
|
|
3584
|
+
# steps (the gcc extension over a bare identifier, so "s.a.b[2].c" is
|
|
3585
|
+
# writable). The steps are collected into a designator array the constant
|
|
3586
|
+
# evaluator later walks to fold the offset; the array is never empty, since
|
|
3587
|
+
# a designator always begins with a member name.
|
|
3588
|
+
def parse_builtin_offsetof
|
|
3589
|
+
keyword_tok = advance # "__builtin_offsetof"
|
|
3590
|
+
expect_punct("(")
|
|
3591
|
+
type = parse_type_name
|
|
3592
|
+
expect_punct(",")
|
|
3593
|
+
designator = parse_member_designator
|
|
3594
|
+
expect_punct(")")
|
|
3595
|
+
AST::BuiltinOffsetof.new(type, designator, keyword_tok)
|
|
3596
|
+
end
|
|
3597
|
+
|
|
3598
|
+
# "__builtin_constant_p ( assignment-expression )": one operand, which is
|
|
3599
|
+
# never evaluated — the fold to 1/0 happens later (the constant evaluator
|
|
3600
|
+
# and the generator), so any expression at all is accepted here, including
|
|
3601
|
+
# one that references a variable or calls a function. The value is int.
|
|
3602
|
+
def parse_builtin_constant_p
|
|
3603
|
+
keyword_tok = advance # "__builtin_constant_p"
|
|
3604
|
+
expect_punct("(")
|
|
3605
|
+
expr = parse_assignment_expression
|
|
3606
|
+
expect_punct(")")
|
|
3607
|
+
AST::BuiltinConstantP.new(expr, keyword_tok)
|
|
3608
|
+
end
|
|
3609
|
+
|
|
3610
|
+
# "__builtin_choose_expr ( const-expr , expr-true , expr-false )": the
|
|
3611
|
+
# first operand is an integer constant-expression evaluated now; the whole
|
|
3612
|
+
# form is replaced at parse time by whichever of the two remaining operands
|
|
3613
|
+
# it selects (non-zero picks expr-true, zero picks expr-false), so no AST
|
|
3614
|
+
# node of its own is needed and the chosen operand's type flows through
|
|
3615
|
+
# unchanged. All three are still parsed, so a syntax error in the branch
|
|
3616
|
+
# that loses is still caught; only the winner reaches code generation. A
|
|
3617
|
+
# non-constant first operand is diagnosed.
|
|
3618
|
+
def parse_builtin_choose_expr
|
|
3619
|
+
advance # "__builtin_choose_expr"
|
|
3620
|
+
expect_punct("(")
|
|
3621
|
+
condition = parse_assignment_expression
|
|
3622
|
+
expect_punct(",")
|
|
3623
|
+
when_true = parse_assignment_expression
|
|
3624
|
+
expect_punct(",")
|
|
3625
|
+
when_false = parse_assignment_expression
|
|
3626
|
+
expect_punct(")")
|
|
3627
|
+
selector = evaluate_constant_expression(
|
|
3628
|
+
condition, "first argument to '__builtin_choose_expr' is not a constant expression",
|
|
3629
|
+
sizeof_expr: method(:fold_time_sizeof)
|
|
3630
|
+
)
|
|
3631
|
+
selector.zero? ? when_false : when_true
|
|
3632
|
+
end
|
|
3633
|
+
|
|
3634
|
+
# "__builtin_ctz/ctzll/clz/clzll ( assignment-expression )": one integer
|
|
3635
|
+
# operand whose trailing (`:forward`) or leading (`:reverse`) zero bits are
|
|
3636
|
+
# counted over `width` bytes. The generator settles the operand's integer
|
|
3637
|
+
# type check and lowers the bit scan; the result is int.
|
|
3638
|
+
def parse_builtin_bit_scan(direction, width)
|
|
3639
|
+
keyword_tok = advance # the "__builtin_ctz"/... keyword
|
|
3640
|
+
expect_punct("(")
|
|
3641
|
+
operand = parse_assignment_expression
|
|
3642
|
+
expect_punct(")")
|
|
3643
|
+
AST::BuiltinBitScan.new(operand, direction, width, keyword_tok)
|
|
3644
|
+
end
|
|
3645
|
+
|
|
3646
|
+
# "__builtin_add/sub/mul_overflow ( a , b , res )": exactly three arguments,
|
|
3647
|
+
# parsed as an ordinary argument list so a wrong count is an arity
|
|
3648
|
+
# diagnostic. The keyword decides only the operator; the operand types are
|
|
3649
|
+
# the generator's to check.
|
|
3650
|
+
def parse_builtin_overflow
|
|
3651
|
+
keyword_tok = advance # the "__builtin_..._overflow" keyword
|
|
3652
|
+
op = OVERFLOW_BUILTINS.fetch(keyword_tok.value)
|
|
3653
|
+
expect_punct("(")
|
|
3654
|
+
args = parse_argument_expression_list
|
|
3655
|
+
expect_punct(")")
|
|
3656
|
+
unless args.size == 3
|
|
3657
|
+
error_at(keyword_tok, "'#{keyword_tok.value}' expects 3 arguments, have #{args.size}")
|
|
3658
|
+
end
|
|
3659
|
+
AST::BuiltinOverflow.new(op, args, keyword_tok)
|
|
3660
|
+
end
|
|
3661
|
+
|
|
3662
|
+
# "__atomic_xxx ( ... )": one of the nine gcc atomic builtins rubycc
|
|
3663
|
+
# lowers. The keyword decides the kind and the exact argument count, both
|
|
3664
|
+
# of which ATOMIC_BUILTINS records; everything else (operand types, the
|
|
3665
|
+
# 4-or-8-byte width restriction) needs resolved types and is the
|
|
3666
|
+
# generator's to diagnose.
|
|
3667
|
+
def parse_builtin_atomic
|
|
3668
|
+
keyword_tok = advance # the "__atomic_..." keyword
|
|
3669
|
+
kind, arity = ATOMIC_BUILTINS.fetch(keyword_tok.value)
|
|
3670
|
+
expect_punct("(")
|
|
3671
|
+
args = parse_argument_expression_list
|
|
3672
|
+
expect_punct(")")
|
|
3673
|
+
unless args.size == arity
|
|
3674
|
+
error_at(keyword_tok, "'#{keyword_tok.value}' expects #{arity} arguments, have #{args.size}")
|
|
3675
|
+
end
|
|
3676
|
+
AST::BuiltinAtomic.new(kind, args, keyword_tok)
|
|
3677
|
+
end
|
|
3678
|
+
|
|
3679
|
+
# "__sync_xxx ( ... )": one of the legacy gcc atomic builtins rubycc
|
|
3680
|
+
# lowers. Shaped like #parse_builtin_atomic — SYNC_BUILTINS records the
|
|
3681
|
+
# kind and the exact argument count, and everything type-dependent is the
|
|
3682
|
+
# generator's to diagnose — but the counts here are the operand counts
|
|
3683
|
+
# alone, no memory order being part of these signatures.
|
|
3684
|
+
#
|
|
3685
|
+
# gcc lets a caller append extra arguments (the "protected variables" its
|
|
3686
|
+
# manual describes and then ignores); rubycc holds every form to its exact
|
|
3687
|
+
# arity, so a call that drifted from the intended shape is reported instead
|
|
3688
|
+
# of silently accepted.
|
|
3689
|
+
def parse_builtin_sync
|
|
3690
|
+
keyword_tok = advance # the "__sync_..." keyword
|
|
3691
|
+
kind, arity = SYNC_BUILTINS.fetch(keyword_tok.value)
|
|
3692
|
+
expect_punct("(")
|
|
3693
|
+
args = parse_argument_expression_list
|
|
3694
|
+
expect_punct(")")
|
|
3695
|
+
unless args.size == arity
|
|
3696
|
+
error_at(keyword_tok, "'#{keyword_tok.value}' expects #{arity} arguments, have #{args.size}")
|
|
3697
|
+
end
|
|
3698
|
+
AST::BuiltinSync.new(kind, args, keyword_tok)
|
|
3699
|
+
end
|
|
3700
|
+
|
|
3701
|
+
# "__builtin_unreachable ()": no operands. Lowers to no code (rubycc does
|
|
3702
|
+
# not optimize); its value is void.
|
|
3703
|
+
def parse_builtin_unreachable
|
|
3704
|
+
keyword_tok = advance # "__builtin_unreachable"
|
|
3705
|
+
expect_punct("(")
|
|
3706
|
+
expect_punct(")")
|
|
3707
|
+
AST::BuiltinUnreachable.new(keyword_tok)
|
|
3708
|
+
end
|
|
3709
|
+
|
|
3710
|
+
# "__builtin_memcpy ( dst , src , n )": rewritten to an ordinary call of
|
|
3711
|
+
# the libc function "memcpy", so it links against the C library's memcpy
|
|
3712
|
+
# like the plain call would. The generator seeds a builtin prototype for
|
|
3713
|
+
# "memcpy" (void *(void *, const void *, unsigned long)), so this compiles
|
|
3714
|
+
# even when <string.h> is not included, matching gcc's builtin.
|
|
3715
|
+
def parse_builtin_memcpy
|
|
3716
|
+
keyword_tok = advance # "__builtin_memcpy"
|
|
3717
|
+
expect_punct("(")
|
|
3718
|
+
args = parse_argument_expression_list
|
|
3719
|
+
expect_punct(")")
|
|
3720
|
+
unless args.size == 3
|
|
3721
|
+
error_at(keyword_tok, "'__builtin_memcpy' expects 3 arguments, have #{args.size}")
|
|
3722
|
+
end
|
|
3723
|
+
AST::Call.new(AST::VariableRef.new("memcpy", keyword_tok), args, keyword_tok)
|
|
3724
|
+
end
|
|
3725
|
+
|
|
3726
|
+
# member-designator = identifier ( "." identifier | "[" expression "]" )*:
|
|
3727
|
+
# the leading member name has no ".", every following member step does, and
|
|
3728
|
+
# a subscript step takes a constant-expression closed by "]". Any other
|
|
3729
|
+
# token where a "." or "[" is expected ends the designator, leaving the ")"
|
|
3730
|
+
# for the caller.
|
|
3731
|
+
def parse_member_designator
|
|
3732
|
+
first_tok = expect_ident
|
|
3733
|
+
designator = [AST::OffsetofMember.new(first_tok.value, first_tok)]
|
|
3734
|
+
loop do
|
|
3735
|
+
if peek.punct?(".")
|
|
3736
|
+
advance # "."
|
|
3737
|
+
member_tok = expect_ident
|
|
3738
|
+
designator << AST::OffsetofMember.new(member_tok.value, member_tok)
|
|
3739
|
+
elsif peek.punct?("[")
|
|
3740
|
+
bracket_tok = advance # "["
|
|
3741
|
+
index = parse_conditional_expression
|
|
3742
|
+
expect_punct("]")
|
|
3743
|
+
designator << AST::OffsetofIndex.new(index, bracket_tok)
|
|
3744
|
+
else
|
|
3745
|
+
return designator
|
|
3746
|
+
end
|
|
3747
|
+
end
|
|
3748
|
+
end
|
|
3749
|
+
|
|
3750
|
+
# type-name = type-specifier abstract-declarator?: a base type-specifier
|
|
3751
|
+
# and an abstract declarator (no name). Shared by "sizeof ( type-name )"
|
|
3752
|
+
# and the cast "( type-name )", so a function pointer, an array pointer or
|
|
3753
|
+
# a plain pointer type can be written there ("sizeof(int (*)(int))",
|
|
3754
|
+
# "(int (*)(int))p").
|
|
3755
|
+
def parse_type_name(allow_incomplete_array: false)
|
|
3756
|
+
_name_tok, type = parse_declarator(parse_type_specifier, name_mode: :forbidden,
|
|
3757
|
+
allow_incomplete_array: allow_incomplete_array)
|
|
3758
|
+
type
|
|
3759
|
+
end
|
|
3760
|
+
|
|
3761
|
+
# A compound literal "( type-name ) { initializer-list }" (6.5.2.5), the
|
|
3762
|
+
# "(" and type-name already consumed by the cast tier. The brace list is
|
|
3763
|
+
# parsed with the ordinary initializer machinery; when it structurally
|
|
3764
|
+
# fits `type` (a brace list always does, a string an aggregate char array)
|
|
3765
|
+
# the type is resolved once here so an inferred "(int[]){...}" bound is
|
|
3766
|
+
# filled in — the same completion #parse_init_declarator performs — and the
|
|
3767
|
+
# finished type rides on the node. The generator lays out the object and
|
|
3768
|
+
# re-resolves the placements.
|
|
3769
|
+
def parse_compound_literal(type, paren_tok)
|
|
3770
|
+
initializer = parse_initializer_list
|
|
3771
|
+
if InitializerResolver.structural?(type, initializer)
|
|
3772
|
+
type = InitializerResolver.resolve(type, initializer).type
|
|
3773
|
+
end
|
|
3774
|
+
AST::CompoundLiteral.new(type, initializer, paren_tok)
|
|
3775
|
+
end
|
|
3776
|
+
|
|
3777
|
+
# A postfix-expression is a primary-expression followed by any run of
|
|
3778
|
+
# postfix suffixes in source order: a call "( args )", a subscript
|
|
3779
|
+
# "[ i ]", a member access "." / "->" and a postfix "++"/"--". A call is
|
|
3780
|
+
# just another suffix, so its callee may be any postfix-expression —
|
|
3781
|
+
# "f(x)", "(*fp)(x)", "table[i](x)" and "s.fp(x)" all parse the same way,
|
|
3782
|
+
# with the AST::Call carrying the callee expression it followed.
|
|
3783
|
+
def parse_postfix_expression
|
|
3784
|
+
parse_postfix_suffixes(parse_primary_expression)
|
|
3785
|
+
end
|
|
3786
|
+
|
|
3787
|
+
# Applies any run of postfix suffixes (call, subscript, member access,
|
|
3788
|
+
# postfix "++"/"--") to an already-parsed postfix-expression head. Split
|
|
3789
|
+
# out from #parse_postfix_expression so a compound literal — which the cast
|
|
3790
|
+
# tier builds after "( type-name )" and which is itself a
|
|
3791
|
+
# postfix-expression (6.5.2p1) — can carry the same suffixes, letting
|
|
3792
|
+
# "(json_frame){...}.type" and "(int[]){1,2,3}[i]" parse.
|
|
3793
|
+
def parse_postfix_suffixes(node)
|
|
3794
|
+
loop do
|
|
3795
|
+
if peek.punct?("(")
|
|
3796
|
+
paren_tok = advance # "("
|
|
3797
|
+
args = parse_argument_expression_list
|
|
3798
|
+
expect_punct(")")
|
|
3799
|
+
node = AST::Call.new(node, args, paren_tok)
|
|
3800
|
+
elsif peek.punct?("[")
|
|
3801
|
+
bracket_tok = advance # "["
|
|
3802
|
+
index = parse_expression
|
|
3803
|
+
expect_punct("]")
|
|
3804
|
+
node = AST::Subscript.new(node, index, bracket_tok)
|
|
3805
|
+
elsif peek.punct?(".") || peek.punct?("->")
|
|
3806
|
+
op_tok = advance
|
|
3807
|
+
member_tok = expect_ident
|
|
3808
|
+
node = AST::MemberAccess.new(node, member_tok.value, op_tok.value == "->", op_tok)
|
|
3809
|
+
elsif peek.punct?("++") || peek.punct?("--")
|
|
3810
|
+
op_tok = advance
|
|
3811
|
+
op = op_tok.value == "++" ? :add : :sub
|
|
3812
|
+
error_at(op_tok, "expression is not assignable") unless assignable?(node)
|
|
3813
|
+
node = AST::IncDec.new(op, node, false, op_tok)
|
|
3814
|
+
else
|
|
3815
|
+
return node
|
|
3816
|
+
end
|
|
3817
|
+
end
|
|
3818
|
+
end
|
|
3819
|
+
|
|
3820
|
+
# Returns an array of expression nodes; empty for an argument-less "()".
|
|
3821
|
+
def parse_argument_expression_list
|
|
3822
|
+
return [] if peek.punct?(")")
|
|
3823
|
+
|
|
3824
|
+
args = [parse_assignment_expression]
|
|
3825
|
+
while peek.punct?(",")
|
|
3826
|
+
advance
|
|
3827
|
+
args << parse_assignment_expression
|
|
3828
|
+
end
|
|
3829
|
+
args
|
|
3830
|
+
end
|
|
3831
|
+
|
|
3832
|
+
def parse_primary_expression
|
|
3833
|
+
tok = peek
|
|
3834
|
+
if tok.type == :num
|
|
3835
|
+
advance
|
|
3836
|
+
AST::IntLit.new(tok.value, tok, integer_literal_type(tok.value, tok.base, tok.suffix, tok))
|
|
3837
|
+
elsif tok.type == :float
|
|
3838
|
+
advance
|
|
3839
|
+
# The suffix (from the lexer) fixes the constant's type: "f"/"F" is
|
|
3840
|
+
# float, everything else (plain, or "l"/"L" long double) is double.
|
|
3841
|
+
type = tok.suffix == "f" ? Type::Float : Type::Double
|
|
3842
|
+
AST::FloatLit.new(tok.value, type, tok)
|
|
3843
|
+
elsif tok.type == :string
|
|
3844
|
+
advance
|
|
3845
|
+
AST::StringLit.new(tok.value, tok)
|
|
3846
|
+
elsif tok.type == :ident
|
|
3847
|
+
advance
|
|
3848
|
+
# An identifier bound to an enum constant folds to its int value on the
|
|
3849
|
+
# spot, so the rest of the pipeline never sees an enumerator; one bound
|
|
3850
|
+
# to (or shadowed by) an ordinary name stays a variable reference.
|
|
3851
|
+
entry = lookup_ordinary(tok.value)
|
|
3852
|
+
if entry&.kind == :enum
|
|
3853
|
+
AST::IntLit.new(entry.value, tok, Type::Int)
|
|
3854
|
+
else
|
|
3855
|
+
AST::VariableRef.new(tok.value, tok)
|
|
3856
|
+
end
|
|
3857
|
+
elsif tok.punct?("(")
|
|
3858
|
+
# A "(" immediately followed by "{" opens a GNU statement expression
|
|
3859
|
+
# "( { block-item* } )" (a GCC extension): the braces enclose a
|
|
3860
|
+
# compound-statement, and its last expression-statement (if any) gives
|
|
3861
|
+
# the whole construct its value and type. Every other "(" is an
|
|
3862
|
+
# ordinary parenthesized expression. #parse_compound_statement carries
|
|
3863
|
+
# its own nesting guard and pushes the block's tag/ordinary scopes.
|
|
3864
|
+
if peek_ahead(1)&.punct?("{")
|
|
3865
|
+
advance # "("
|
|
3866
|
+
body = parse_compound_statement
|
|
3867
|
+
expect_punct(")")
|
|
3868
|
+
AST::StatementExpr.new(body, tok)
|
|
3869
|
+
else
|
|
3870
|
+
advance
|
|
3871
|
+
node = parse_expression
|
|
3872
|
+
expect_punct(")")
|
|
3873
|
+
node
|
|
3874
|
+
end
|
|
3875
|
+
else
|
|
3876
|
+
error_at(tok, "expected expression")
|
|
3877
|
+
end
|
|
3878
|
+
end
|
|
3879
|
+
|
|
3880
|
+
# The type of an integer constant (6.4.4.1): the first type in a
|
|
3881
|
+
# base/suffix-specific candidate list whose range holds the value. A `u`
|
|
3882
|
+
# suffix admits the unsigned types; a decimal constant is never unsigned
|
|
3883
|
+
# without one, while hex and octal constants may fall through to an
|
|
3884
|
+
# unsigned type. `l`/`ll` (folded to one "long" width under LP64) demote
|
|
3885
|
+
# the int candidates. A value beyond even unsigned long is rejected.
|
|
3886
|
+
def integer_literal_type(value, base, suffix, tok)
|
|
3887
|
+
has_u = suffix.include?("u")
|
|
3888
|
+
has_l = suffix.include?("l")
|
|
3889
|
+
decimal = base == 10
|
|
3890
|
+
candidates =
|
|
3891
|
+
if has_u && has_l then [Type::ULong]
|
|
3892
|
+
elsif has_u then [Type::UInt, Type::ULong]
|
|
3893
|
+
elsif has_l then decimal ? [Type::Long] : [Type::Long, Type::ULong]
|
|
3894
|
+
elsif decimal then [Type::Int, Type::Long]
|
|
3895
|
+
else [Type::Int, Type::UInt, Type::Long, Type::ULong]
|
|
3896
|
+
end
|
|
3897
|
+
|
|
3898
|
+
candidates.find { |type| integer_fits?(value, type) } ||
|
|
3899
|
+
# gcc widens an out-of-range constant to unsigned long rather than
|
|
3900
|
+
# reject it outright; only a value past unsigned long is an error.
|
|
3901
|
+
(integer_fits?(value, Type::ULong) ? Type::ULong : error_at(tok, "integer constant is too large"))
|
|
3902
|
+
end
|
|
3903
|
+
|
|
3904
|
+
# Whether the non-negative `value` fits in integer type `type`.
|
|
3905
|
+
def integer_fits?(value, type)
|
|
3906
|
+
limit = type.signed? ? (1 << (type.size * 8 - 1)) - 1 : (1 << (type.size * 8)) - 1
|
|
3907
|
+
value <= limit
|
|
3908
|
+
end
|
|
3909
|
+
|
|
3910
|
+
# --- ordinary-identifier namespace ---------------------------------
|
|
3911
|
+
|
|
3912
|
+
# Records a variable, parameter or function name in the current ordinary
|
|
3913
|
+
# scope. Its main job is to shadow a typedef name or enum constant of the
|
|
3914
|
+
# same name from an outer scope, so a redeclaration of an ordinary name (a
|
|
3915
|
+
# genuine error the generator reports) is deliberately not diagnosed here.
|
|
3916
|
+
# The declared `type` is kept as the entry's payload so a constant
|
|
3917
|
+
# expression folded during parsing can resolve "sizeof <variable>" (see
|
|
3918
|
+
# #fold_time_sizeof), which the type-table-free ConstantEvaluator otherwise
|
|
3919
|
+
# cannot; it is nil only for the synthetic entries that predate a type.
|
|
3920
|
+
def declare_ordinary_name(name, type = nil)
|
|
3921
|
+
@ordinary_scopes.last[name] = OrdinaryName.new(:ordinary, type)
|
|
3922
|
+
end
|
|
3923
|
+
|
|
3924
|
+
# Binds a typedef name to its resolved type (and whether it names a
|
|
3925
|
+
# const-qualified object type) in the current ordinary scope. C permits a
|
|
3926
|
+
# typedef name to be redeclared in the same scope when the new declaration
|
|
3927
|
+
# names the same type; a different type remains a redefinition diagnostic.
|
|
3928
|
+
def declare_typedef_name(name_tok, type, const)
|
|
3929
|
+
existing = @ordinary_scopes.last[name_tok.value]
|
|
3930
|
+
if existing
|
|
3931
|
+
return if existing.kind == :typedef && existing.value == [type, const]
|
|
3932
|
+
|
|
3933
|
+
error_at(name_tok, "redefinition of typedef '#{name_tok.value}'")
|
|
3934
|
+
end
|
|
3935
|
+
@ordinary_scopes.last[name_tok.value] = OrdinaryName.new(:typedef, [type, const])
|
|
3936
|
+
end
|
|
3937
|
+
|
|
3938
|
+
# The innermost ordinary-scope entry for `name`, or nil when none binds it.
|
|
3939
|
+
def lookup_ordinary(name)
|
|
3940
|
+
@ordinary_scopes.reverse_each do |scope|
|
|
3941
|
+
entry = scope[name]
|
|
3942
|
+
return entry if entry
|
|
3943
|
+
end
|
|
3944
|
+
nil
|
|
3945
|
+
end
|
|
3946
|
+
|
|
3947
|
+
# Whether `name`'s innermost ordinary binding is a typedef name — false
|
|
3948
|
+
# when it is unbound or shadowed by a nearer variable or enum constant.
|
|
3949
|
+
def typedef_name?(name)
|
|
3950
|
+
entry = lookup_ordinary(name)
|
|
3951
|
+
!entry.nil? && entry.kind == :typedef
|
|
3952
|
+
end
|
|
3953
|
+
|
|
3954
|
+
# --- token consumption helpers -------------------------------------
|
|
3955
|
+
|
|
3956
|
+
def expect_keyword(str)
|
|
3957
|
+
tok = peek
|
|
3958
|
+
error_at(tok, "expected '#{str}'") unless tok.keyword?(str)
|
|
3959
|
+
advance
|
|
3960
|
+
end
|
|
3961
|
+
|
|
3962
|
+
def expect_ident
|
|
3963
|
+
tok = peek
|
|
3964
|
+
error_at(tok, "expected identifier") unless tok.type == :ident
|
|
3965
|
+
advance
|
|
3966
|
+
end
|
|
3967
|
+
|
|
3968
|
+
def expect_punct(str)
|
|
3969
|
+
tok = peek
|
|
3970
|
+
error_at(tok, "expected '#{str}'") unless tok.punct?(str)
|
|
3971
|
+
advance
|
|
3972
|
+
end
|
|
3973
|
+
|
|
3974
|
+
def error_at(token, description)
|
|
3975
|
+
raise CompileError.new(
|
|
3976
|
+
description,
|
|
3977
|
+
filename: token.filename,
|
|
3978
|
+
line: token.line,
|
|
3979
|
+
column: token.column,
|
|
3980
|
+
source_line: token.source_line
|
|
3981
|
+
)
|
|
3982
|
+
end
|
|
3983
|
+
|
|
3984
|
+
# Folds `node` — a conditional-expression already parsed as a
|
|
3985
|
+
# constant-expression (6.6) — to a Ruby Integer via ConstantEvaluator.
|
|
3986
|
+
# A sub-expression that is not itself a constant expression is reported
|
|
3987
|
+
# with `message` at its own token; a division/remainder by zero that is
|
|
3988
|
+
# actually reached is reported at the operator's token, independent of
|
|
3989
|
+
# `message`, since it is a different failure than "not a constant".
|
|
3990
|
+
def evaluate_constant_expression(node, message, sizeof_expr: nil)
|
|
3991
|
+
ConstantEvaluator.evaluate(node, sizeof_expr: sizeof_expr)
|
|
3992
|
+
rescue ConstantEvaluator::NotConstant => e
|
|
3993
|
+
error_at(e.token, message)
|
|
3994
|
+
rescue ConstantEvaluator::DivisionByZero => e
|
|
3995
|
+
error_at(e.token, "division by zero in constant expression")
|
|
3996
|
+
end
|
|
3997
|
+
|
|
3998
|
+
# Resolves a "sizeof <expression>" operand to its byte size at parse time.
|
|
3999
|
+
# This is passed as ConstantEvaluator's `sizeof_expr:` in every constant
|
|
4000
|
+
# (or integer-constant) expression context the parser folds on the spot --
|
|
4001
|
+
# an array bound, an enumerator, a bit-field width, a case label, an array
|
|
4002
|
+
# designator, an "aligned" attribute argument, and the like -- since none
|
|
4003
|
+
# of them carries a type table the way "sizeof x" would otherwise need.
|
|
4004
|
+
# The operand's type is inferred by #sizeof_operand_type over the forms a
|
|
4005
|
+
# real constant expression's "sizeof <expr>" reaches (a named object, a
|
|
4006
|
+
# string literal, a subscript, a dereference, a cast -- notably ruby.h's
|
|
4007
|
+
# rb_strlen_lit, "(sizeof(s "") / sizeof(s ""[0])) - 1", which sizes both a
|
|
4008
|
+
# string literal and its element). sizeof measures its immediate operand
|
|
4009
|
+
# undecayed (6.5.3.4), so "sizeof arr" is the whole array. An operand whose
|
|
4010
|
+
# type cannot be inferred, or one of incomplete/void/function type with no
|
|
4011
|
+
# size, stays a NotConstant so the surrounding context reports "not an
|
|
4012
|
+
# integer constant" rather than a wrong value.
|
|
4013
|
+
def fold_time_sizeof(node)
|
|
4014
|
+
type = sizeof_operand_type(node.operand)
|
|
4015
|
+
if type.nil? || type.void? || type.function? || (type.array? && type.incomplete?)
|
|
4016
|
+
raise ConstantEvaluator::NotConstant, node.token
|
|
4017
|
+
end
|
|
4018
|
+
|
|
4019
|
+
type.size
|
|
4020
|
+
end
|
|
4021
|
+
|
|
4022
|
+
# The type a "sizeof" operand expression has, inferred without the
|
|
4023
|
+
# generator's symbol table, or nil when a form outside this small set is
|
|
4024
|
+
# met. A subscript and a dereference each decay their base (an array to a
|
|
4025
|
+
# pointer to its element) and yield the pointed-to type; a cast is its named
|
|
4026
|
+
# type; a named object's type is the one the ordinary scope recorded; a
|
|
4027
|
+
# member access ("." or "->") resolves against its base's struct/union type
|
|
4028
|
+
# -- sqlite3's "char dbFileVers[sizeof(pPager->dbFileVers)]" is exactly this
|
|
4029
|
+
# shape, an array bound sized from a pointer parameter's member. Only what
|
|
4030
|
+
# an array-bound constant expression realistically uses is covered.
|
|
4031
|
+
def sizeof_operand_type(node)
|
|
4032
|
+
case node
|
|
4033
|
+
when AST::StringLit
|
|
4034
|
+
Type::Array.new(Type::Char, node.value.bytesize + 1)
|
|
4035
|
+
when AST::VariableRef
|
|
4036
|
+
entry = lookup_ordinary(node.name)
|
|
4037
|
+
entry && entry.kind == :ordinary ? entry.value : nil
|
|
4038
|
+
when AST::Subscript
|
|
4039
|
+
element_of(sizeof_operand_type(node.target))
|
|
4040
|
+
when AST::Unary
|
|
4041
|
+
node.op == :deref ? element_of(sizeof_operand_type(node.operand)) : nil
|
|
4042
|
+
when AST::Cast
|
|
4043
|
+
node.type
|
|
4044
|
+
when AST::MemberAccess
|
|
4045
|
+
base = sizeof_operand_type(node.base)
|
|
4046
|
+
base = element_of(base) if node.arrow
|
|
4047
|
+
member_sizeof_type(base, node.member)
|
|
4048
|
+
end
|
|
4049
|
+
end
|
|
4050
|
+
|
|
4051
|
+
# The element type reached by subscripting or dereferencing a base of type
|
|
4052
|
+
# `type`: an array decays to a pointer first, so both an array and a pointer
|
|
4053
|
+
# yield their element/pointee. Anything else (or an unknown base) has none.
|
|
4054
|
+
def element_of(type)
|
|
4055
|
+
return nil if type.nil?
|
|
4056
|
+
return type.element if type.array?
|
|
4057
|
+
|
|
4058
|
+
type.target if type.pointer?
|
|
4059
|
+
end
|
|
4060
|
+
|
|
4061
|
+
# The type of member `name` in a struct/union `type`, for #sizeof_operand_type
|
|
4062
|
+
# resolving "sizeof base.member"/"sizeof base->member" -- nil when `type`
|
|
4063
|
+
# is not a completed struct/union, the member does not exist, or it is a
|
|
4064
|
+
# bit-field, since a bit-field has no size to take (6.5.3.4p1) and so must
|
|
4065
|
+
# stay a NotConstant rather than fold to a wrong value. #struct? alone
|
|
4066
|
+
# tells a struct/union base apart from every other type (it answers true
|
|
4067
|
+
# for both, see Type::StructType), so a plain `sizeof x.m` with `x` of a
|
|
4068
|
+
# non-aggregate type -- syntactically parseable, only later rejected by
|
|
4069
|
+
# the generator -- stops here rather than reaching #union?, which only
|
|
4070
|
+
# Type::StructType implements.
|
|
4071
|
+
def member_sizeof_type(type, name)
|
|
4072
|
+
return nil if type.nil? || !type.struct?
|
|
4073
|
+
|
|
4074
|
+
member = type.member(name)
|
|
4075
|
+
member && member.bit_width.nil? ? member.type : nil
|
|
4076
|
+
end
|
|
4077
|
+
|
|
4078
|
+
# Whether the initializer subtree uses `sizeof <expression>` (as opposed to
|
|
4079
|
+
# `sizeof(type-name)`) anywhere. Such an operand's type can only be
|
|
4080
|
+
# inferred with the symbol table the generator holds, so its presence tells
|
|
4081
|
+
# #parse_global_declarator to defer folding to the generator rather than
|
|
4082
|
+
# evaluate the initializer here. The walk descends only through AST nodes
|
|
4083
|
+
# (each a `Data` under this AST module), so it never recurses into the
|
|
4084
|
+
# Type or Token objects a node's fields also carry.
|
|
4085
|
+
def references_sizeof_expr?(node)
|
|
4086
|
+
return true if node.is_a?(AST::SizeofExpr)
|
|
4087
|
+
return false unless ast_node?(node)
|
|
4088
|
+
|
|
4089
|
+
node.deconstruct_keys(nil).each_value do |field|
|
|
4090
|
+
values = field.is_a?(Array) ? field : [field]
|
|
4091
|
+
return true if values.any? { |value| references_sizeof_expr?(value) }
|
|
4092
|
+
end
|
|
4093
|
+
false
|
|
4094
|
+
end
|
|
4095
|
+
|
|
4096
|
+
# Whether the initializer subtree takes an address ("&x") anywhere. Such an
|
|
4097
|
+
# expression reduces only through the generator's address-constant
|
|
4098
|
+
# machinery (the "(size_t)&((T*)0)->m" offsetof idiom folds to a member's
|
|
4099
|
+
# byte offset), not the parser's type-table-free evaluator, so its presence
|
|
4100
|
+
# defers folding of an integer initializer to the generator — mirroring
|
|
4101
|
+
# #references_sizeof_expr?. The walk descends only through AST nodes.
|
|
4102
|
+
def references_address_of?(node)
|
|
4103
|
+
return true if node.is_a?(AST::Unary) && node.op == :addr
|
|
4104
|
+
return false unless ast_node?(node)
|
|
4105
|
+
|
|
4106
|
+
node.deconstruct_keys(nil).each_value do |field|
|
|
4107
|
+
values = field.is_a?(Array) ? field : [field]
|
|
4108
|
+
return true if values.any? { |value| references_address_of?(value) }
|
|
4109
|
+
end
|
|
4110
|
+
false
|
|
4111
|
+
end
|
|
4112
|
+
|
|
4113
|
+
# Whether `value` is one of this module's AST nodes — a `Data` instance
|
|
4114
|
+
# whose class lives under `Rubycc::Front::AST` — so the initializer walk
|
|
4115
|
+
# descends into it but not into the tokens, types or literals a field may
|
|
4116
|
+
# hold.
|
|
4117
|
+
def ast_node?(value)
|
|
4118
|
+
value.is_a?(Data) && AST.constants.any? { |c| AST.const_get(c).equal?(value.class) }
|
|
4119
|
+
end
|
|
4120
|
+
end
|
|
4121
|
+
end
|
|
4122
|
+
end
|