clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name GoParser.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D LLDB_USE_BUILTIN_DEMANGLER -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326246/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn326246/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-02-28-041547-14988-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include <vector> |
11 | |
12 | #include "GoParser.h" |
13 | |
14 | #include "Plugins/ExpressionParser/Go/GoAST.h" |
15 | #include "lldb/Utility/Status.h" |
16 | #include "llvm/ADT/SmallString.h" |
17 | |
18 | using namespace lldb_private; |
19 | using namespace lldb; |
20 | |
21 | namespace { |
22 | llvm::StringRef DescribeToken(GoLexer::TokenType t) { |
23 | switch (t) { |
24 | case GoLexer::TOK_EOF: |
25 | return "<eof>"; |
26 | case GoLexer::TOK_IDENTIFIER: |
27 | return "identifier"; |
28 | case GoLexer::LIT_FLOAT: |
29 | return "float"; |
30 | case GoLexer::LIT_IMAGINARY: |
31 | return "imaginary"; |
32 | case GoLexer::LIT_INTEGER: |
33 | return "integer"; |
34 | case GoLexer::LIT_RUNE: |
35 | return "rune"; |
36 | case GoLexer::LIT_STRING: |
37 | return "string"; |
38 | default: |
39 | return GoLexer::LookupToken(t); |
40 | } |
41 | } |
42 | } |
43 | |
44 | class GoParser::Rule { |
45 | public: |
46 | Rule(llvm::StringRef name, GoParser *p) |
47 | : m_name(name), m_parser(p), m_pos(p->m_pos) {} |
48 | |
49 | std::nullptr_t error() { |
50 | if (!m_parser->m_failed) { |
51 | |
52 | if (m_parser->m_last_tok == GoLexer::TOK_INVALID) |
53 | m_parser->m_error = m_parser->m_last; |
54 | else |
55 | m_parser->m_error = DescribeToken(m_parser->m_last_tok); |
56 | |
57 | m_parser->m_last = m_name; |
58 | m_parser->m_last_tok = GoLexer::TOK_INVALID; |
59 | m_parser->m_pos = m_pos; |
60 | } |
61 | return nullptr; |
62 | } |
63 | |
64 | private: |
65 | llvm::StringRef m_name; |
66 | GoParser *m_parser; |
67 | size_t m_pos; |
68 | }; |
69 | |
70 | GoParser::GoParser(const char *src) |
71 | : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID), |
72 | m_failed(false) {} |
73 | |
74 | GoASTStmt *GoParser::Statement() { |
75 | Rule r("Statement", this); |
76 | GoLexer::TokenType t = peek(); |
77 | GoASTStmt *ret = nullptr; |
78 | switch (t) { |
79 | case GoLexer::TOK_EOF: |
80 | case GoLexer::OP_SEMICOLON: |
81 | case GoLexer::OP_RPAREN: |
82 | case GoLexer::OP_RBRACE: |
83 | case GoLexer::TOK_INVALID: |
84 | return EmptyStmt(); |
85 | case GoLexer::OP_LBRACE: |
86 | return Block(); |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | default: |
120 | break; |
121 | } |
122 | GoASTExpr *expr = Expression(); |
123 | if (expr == nullptr) |
124 | return r.error(); |
125 | if ( |
126 | (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || |
127 | (ret = ExpressionStmt(expr))) { |
128 | return ret; |
129 | } |
130 | delete expr; |
131 | return r.error(); |
132 | } |
133 | |
134 | GoASTStmt *GoParser::ExpressionStmt(GoASTExpr *e) { |
135 | if (Semicolon()) |
136 | return new GoASTExprStmt(e); |
137 | return nullptr; |
138 | } |
139 | |
140 | GoASTStmt *GoParser::IncDecStmt(GoASTExpr *e) { |
141 | Rule r("IncDecStmt", this); |
142 | if (match(GoLexer::OP_PLUS_PLUS)) |
143 | return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) |
144 | : r.error(); |
145 | if (match(GoLexer::OP_MINUS_MINUS)) |
146 | return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) |
147 | : r.error(); |
148 | return nullptr; |
149 | } |
150 | |
151 | GoASTStmt *GoParser::Assignment(lldb_private::GoASTExpr *e) { |
152 | Rule r("Assignment", this); |
153 | std::vector<std::unique_ptr<GoASTExpr>> lhs; |
154 | for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) |
155 | lhs.push_back(std::unique_ptr<GoASTExpr>(l)); |
156 | switch (peek()) { |
157 | case GoLexer::OP_EQ: |
158 | case GoLexer::OP_PLUS_EQ: |
159 | case GoLexer::OP_MINUS_EQ: |
160 | case GoLexer::OP_PIPE_EQ: |
161 | case GoLexer::OP_CARET_EQ: |
162 | case GoLexer::OP_STAR_EQ: |
163 | case GoLexer::OP_SLASH_EQ: |
164 | case GoLexer::OP_PERCENT_EQ: |
165 | case GoLexer::OP_LSHIFT_EQ: |
166 | case GoLexer::OP_RSHIFT_EQ: |
167 | case GoLexer::OP_AMP_EQ: |
168 | case GoLexer::OP_AMP_CARET_EQ: |
169 | break; |
170 | default: |
171 | return r.error(); |
172 | } |
173 | |
174 | std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false)); |
175 | stmt->AddLhs(e); |
176 | for (auto &l : lhs) |
177 | stmt->AddLhs(l.release()); |
178 | for (GoASTExpr *r = Expression(); r; r = MoreExpressionList()) |
179 | stmt->AddRhs(r); |
180 | if (!Semicolon() || stmt->NumRhs() == 0) |
181 | return new GoASTBadStmt; |
182 | return stmt.release(); |
183 | } |
184 | |
185 | GoASTStmt *GoParser::EmptyStmt() { |
186 | if (match(GoLexer::TOK_EOF)) |
187 | return nullptr; |
188 | if (Semicolon()) |
189 | return new GoASTEmptyStmt; |
190 | return nullptr; |
191 | } |
192 | |
193 | GoASTStmt *GoParser::GoStmt() { |
194 | if (match(GoLexer::KEYWORD_GO)) { |
195 | if (GoASTCallExpr *e = |
196 | llvm::dyn_cast_or_null<GoASTCallExpr>(Expression())) { |
197 | return FinishStmt(new GoASTGoStmt(e)); |
198 | } |
199 | m_last = "call expression"; |
200 | m_failed = true; |
201 | return new GoASTBadStmt(); |
202 | } |
203 | return nullptr; |
204 | } |
205 | |
206 | GoASTStmt *GoParser::ReturnStmt() { |
207 | if (match(GoLexer::KEYWORD_RETURN)) { |
208 | std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt()); |
209 | for (GoASTExpr *e = Expression(); e; e = MoreExpressionList()) |
210 | r->AddResults(e); |
211 | return FinishStmt(r.release()); |
212 | } |
213 | return nullptr; |
214 | } |
215 | |
216 | GoASTStmt *GoParser::BranchStmt() { |
217 | GoLexer::Token *tok; |
218 | if ((tok = match(GoLexer::KEYWORD_BREAK)) || |
219 | (tok = match(GoLexer::KEYWORD_CONTINUE)) || |
220 | (tok = match(GoLexer::KEYWORD_GOTO))) { |
221 | auto *e = Identifier(); |
222 | if (tok->m_type == GoLexer::KEYWORD_GOTO && !e) |
223 | return syntaxerror(); |
224 | return FinishStmt(new GoASTBranchStmt(e, tok->m_type)); |
225 | } |
226 | if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH))) |
227 | return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type)); |
228 | |
229 | return nullptr; |
230 | } |
231 | |
232 | GoASTIdent *GoParser::Identifier() { |
233 | if (auto *tok = match(GoLexer::TOK_IDENTIFIER)) |
| |
234 | return new GoASTIdent(*tok); |
| |
235 | return nullptr; |
236 | } |
237 | |
238 | GoASTExpr *GoParser::MoreExpressionList() { |
239 | if (match(GoLexer::OP_COMMA)) { |
240 | auto *e = Expression(); |
241 | if (!e) |
242 | return syntaxerror(); |
243 | return e; |
244 | } |
245 | return nullptr; |
246 | } |
247 | |
248 | GoASTIdent *GoParser::MoreIdentifierList() { |
249 | if (match(GoLexer::OP_COMMA)) { |
250 | auto *i = Identifier(); |
251 | if (!i) |
252 | return syntaxerror(); |
253 | return i; |
254 | } |
255 | return nullptr; |
256 | } |
257 | |
258 | GoASTExpr *GoParser::Expression() { |
259 | Rule r("Expression", this); |
260 | if (GoASTExpr *ret = OrExpr()) |
261 | return ret; |
262 | return r.error(); |
263 | } |
264 | |
265 | GoASTExpr *GoParser::UnaryExpr() { |
266 | switch (peek()) { |
267 | case GoLexer::OP_PLUS: |
268 | case GoLexer::OP_MINUS: |
269 | case GoLexer::OP_BANG: |
270 | case GoLexer::OP_CARET: |
271 | case GoLexer::OP_STAR: |
272 | case GoLexer::OP_AMP: |
273 | case GoLexer::OP_LT_MINUS: { |
274 | const GoLexer::Token t = next(); |
275 | if (GoASTExpr *e = UnaryExpr()) { |
276 | if (t.m_type == GoLexer::OP_STAR) |
277 | return new GoASTStarExpr(e); |
278 | else |
279 | return new GoASTUnaryExpr(t.m_type, e); |
280 | } |
281 | return syntaxerror(); |
282 | } |
283 | default: |
284 | return PrimaryExpr(); |
285 | } |
286 | } |
287 | |
288 | GoASTExpr *GoParser::OrExpr() { |
289 | std::unique_ptr<GoASTExpr> l(AndExpr()); |
290 | if (l) { |
291 | while (match(GoLexer::OP_PIPE_PIPE)) { |
292 | GoASTExpr *r = AndExpr(); |
293 | if (r) |
294 | l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE)); |
295 | else |
296 | return syntaxerror(); |
297 | } |
298 | return l.release(); |
299 | } |
300 | return nullptr; |
301 | } |
302 | |
303 | GoASTExpr *GoParser::AndExpr() { |
304 | std::unique_ptr<GoASTExpr> l(RelExpr()); |
305 | if (l) { |
306 | while (match(GoLexer::OP_AMP_AMP)) { |
307 | GoASTExpr *r = RelExpr(); |
308 | if (r) |
309 | l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP)); |
310 | else |
311 | return syntaxerror(); |
312 | } |
313 | return l.release(); |
314 | } |
315 | return nullptr; |
316 | } |
317 | |
318 | GoASTExpr *GoParser::RelExpr() { |
319 | std::unique_ptr<GoASTExpr> l(AddExpr()); |
320 | if (l) { |
321 | for (GoLexer::Token *t; |
322 | (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) || |
323 | (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) || |
324 | (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));) { |
325 | GoLexer::TokenType op = t->m_type; |
326 | GoASTExpr *r = AddExpr(); |
327 | if (r) |
328 | l.reset(new GoASTBinaryExpr(l.release(), r, op)); |
329 | else |
330 | return syntaxerror(); |
331 | } |
332 | return l.release(); |
333 | } |
334 | return nullptr; |
335 | } |
336 | |
337 | GoASTExpr *GoParser::AddExpr() { |
338 | std::unique_ptr<GoASTExpr> l(MulExpr()); |
339 | if (l) { |
340 | for (GoLexer::Token *t; |
341 | (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) || |
342 | (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));) { |
343 | GoLexer::TokenType op = t->m_type; |
344 | GoASTExpr *r = MulExpr(); |
345 | if (r) |
346 | l.reset(new GoASTBinaryExpr(l.release(), r, op)); |
347 | else |
348 | return syntaxerror(); |
349 | } |
350 | return l.release(); |
351 | } |
352 | return nullptr; |
353 | } |
354 | |
355 | GoASTExpr *GoParser::MulExpr() { |
356 | std::unique_ptr<GoASTExpr> l(UnaryExpr()); |
357 | if (l) { |
358 | for (GoLexer::Token *t; |
359 | (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) || |
360 | (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) || |
361 | (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) || |
362 | (t = match(GoLexer::OP_AMP_CARET));) { |
363 | GoLexer::TokenType op = t->m_type; |
364 | GoASTExpr *r = UnaryExpr(); |
365 | if (r) |
366 | l.reset(new GoASTBinaryExpr(l.release(), r, op)); |
367 | else |
368 | return syntaxerror(); |
369 | } |
370 | return l.release(); |
371 | } |
372 | return nullptr; |
373 | } |
374 | |
375 | GoASTExpr *GoParser::PrimaryExpr() { |
376 | GoASTExpr *l; |
377 | GoASTExpr *r; |
378 | (l = Conversion()) || (l = Operand()); |
379 | if (!l) |
380 | return nullptr; |
381 | while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || |
382 | (r = Arguments(l))) { |
383 | l = r; |
384 | } |
385 | return l; |
386 | } |
387 | |
388 | GoASTExpr *GoParser::Operand() { |
389 | GoLexer::Token *lit; |
390 | if ((lit = match(GoLexer::LIT_INTEGER)) || |
391 | (lit = match(GoLexer::LIT_FLOAT)) || |
392 | (lit = match(GoLexer::LIT_IMAGINARY)) || |
393 | (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING))) |
394 | return new GoASTBasicLit(*lit); |
395 | if (match(GoLexer::OP_LPAREN)) { |
396 | GoASTExpr *e; |
397 | if (!((e = Expression()) && match(GoLexer::OP_RPAREN))) |
398 | return syntaxerror(); |
399 | return e; |
400 | } |
401 | |
402 | if (GoASTExpr *e = CompositeLit()) |
403 | return e; |
404 | if (GoASTExpr *n = Name()) |
405 | return n; |
406 | return FunctionLit(); |
407 | } |
408 | |
409 | GoASTExpr *GoParser::FunctionLit() { |
410 | if (!match(GoLexer::KEYWORD_FUNC)) |
411 | return nullptr; |
412 | auto *sig = Signature(); |
413 | if (!sig) |
414 | return syntaxerror(); |
415 | auto *body = Block(); |
416 | if (!body) { |
417 | delete sig; |
418 | return syntaxerror(); |
419 | } |
420 | return new GoASTFuncLit(sig, body); |
421 | } |
422 | |
423 | GoASTBlockStmt *GoParser::Block() { |
424 | if (!match(GoLexer::OP_LBRACE)) |
425 | return nullptr; |
426 | std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt); |
427 | for (auto *s = Statement(); s; s = Statement()) |
428 | block->AddList(s); |
429 | if (!match(GoLexer::OP_RBRACE)) |
430 | return syntaxerror(); |
431 | return block.release(); |
432 | } |
433 | |
434 | GoASTExpr *GoParser::CompositeLit() { |
435 | Rule r("CompositeLit", this); |
436 | GoASTExpr *type; |
437 | (type = StructType()) || (type = ArrayOrSliceType(true)) || |
438 | (type = MapType()) || (type = Name()); |
439 | if (!type) |
440 | return r.error(); |
441 | GoASTCompositeLit *lit = LiteralValue(); |
442 | if (!lit) { |
443 | delete type; |
444 | return r.error(); |
445 | } |
446 | lit->SetType(type); |
447 | return lit; |
448 | } |
449 | |
450 | GoASTCompositeLit *GoParser::LiteralValue() { |
451 | if (!match(GoLexer::OP_LBRACE)) |
452 | return nullptr; |
453 | std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit); |
454 | for (GoASTExpr *e = Element(); e; e = Element()) { |
455 | lit->AddElts(e); |
456 | if (!match(GoLexer::OP_COMMA)) |
457 | break; |
458 | } |
459 | if (!mustMatch(GoLexer::OP_RBRACE)) |
460 | return nullptr; |
461 | return lit.release(); |
462 | } |
463 | |
464 | GoASTExpr *GoParser::Element() { |
465 | GoASTExpr *key; |
466 | if (!((key = Expression()) || (key = LiteralValue()))) |
467 | return nullptr; |
468 | if (!match(GoLexer::OP_COLON)) |
469 | return key; |
470 | GoASTExpr *value; |
471 | if ((value = Expression()) || (value = LiteralValue())) |
472 | return new GoASTKeyValueExpr(key, value); |
473 | delete key; |
474 | return syntaxerror(); |
475 | } |
476 | |
477 | GoASTExpr *GoParser::Selector(GoASTExpr *e) { |
478 | Rule r("Selector", this); |
479 | if (match(GoLexer::OP_DOT)) { |
480 | if (auto *name = Identifier()) |
481 | return new GoASTSelectorExpr(e, name); |
482 | } |
483 | return r.error(); |
484 | } |
485 | |
486 | GoASTExpr *GoParser::IndexOrSlice(GoASTExpr *e) { |
487 | Rule r("IndexOrSlice", this); |
488 | if (match(GoLexer::OP_LBRACK)) { |
489 | std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3; |
490 | bool slice = false; |
491 | if (match(GoLexer::OP_COLON)) { |
492 | slice = true; |
493 | i2.reset(Expression()); |
494 | if (i2 && match(GoLexer::OP_COLON)) { |
495 | i3.reset(Expression()); |
496 | if (!i3) |
497 | return syntaxerror(); |
498 | } |
499 | } |
500 | if (!(slice || i1)) |
501 | return syntaxerror(); |
502 | if (!mustMatch(GoLexer::OP_RBRACK)) |
503 | return nullptr; |
504 | if (slice) { |
505 | bool slice3 = i3.get(); |
506 | return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), |
507 | slice3); |
508 | } |
509 | return new GoASTIndexExpr(e, i1.release()); |
510 | } |
511 | return r.error(); |
512 | } |
513 | |
514 | GoASTExpr *GoParser::TypeAssertion(GoASTExpr *e) { |
515 | Rule r("TypeAssertion", this); |
516 | if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN)) { |
517 | if (auto *t = Type()) { |
518 | if (!mustMatch(GoLexer::OP_RPAREN)) |
519 | return nullptr; |
520 | return new GoASTTypeAssertExpr(e, t); |
521 | } |
522 | return syntaxerror(); |
523 | } |
524 | return r.error(); |
525 | } |
526 | |
527 | GoASTExpr *GoParser::Arguments(GoASTExpr *e) { |
528 | if (match(GoLexer::OP_LPAREN)) { |
529 | std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false)); |
530 | GoASTExpr *arg; |
531 | |
532 | for ((arg = Expression()) || (arg = Type()); arg; |
533 | arg = MoreExpressionList()) { |
534 | call->AddArgs(arg); |
535 | } |
536 | if (match(GoLexer::OP_DOTS)) |
537 | call->SetEllipsis(true); |
538 | |
539 | |
540 | match(GoLexer::OP_COMMA); |
541 | |
542 | if (!mustMatch(GoLexer::OP_RPAREN)) |
543 | return nullptr; |
544 | call->SetFun(e); |
545 | return call.release(); |
546 | } |
547 | return nullptr; |
548 | } |
549 | |
550 | GoASTExpr *GoParser::Conversion() { |
551 | Rule r("Conversion", this); |
552 | if (GoASTExpr *t = Type2()) { |
553 | std::unique_ptr<GoASTExpr> owner(t); |
554 | if (match(GoLexer::OP_LPAREN)) { |
555 | GoASTExpr *v = Expression(); |
556 | if (!v) |
557 | return syntaxerror(); |
558 | match(GoLexer::OP_COMMA); |
559 | if (!mustMatch(GoLexer::OP_RPAREN)) |
560 | return r.error(); |
561 | GoASTCallExpr *call = new GoASTCallExpr(false); |
562 | call->SetFun(t); |
563 | owner.release(); |
564 | call->AddArgs(v); |
565 | return call; |
566 | } |
567 | } |
568 | return r.error(); |
569 | } |
570 | |
571 | GoASTExpr *GoParser::Type2() { |
572 | switch (peek()) { |
573 | case GoLexer::OP_LBRACK: |
574 | return ArrayOrSliceType(false); |
575 | case GoLexer::KEYWORD_STRUCT: |
576 | return StructType(); |
577 | case GoLexer::KEYWORD_FUNC: |
578 | return FunctionType(); |
579 | case GoLexer::KEYWORD_INTERFACE: |
580 | return InterfaceType(); |
581 | case GoLexer::KEYWORD_MAP: |
582 | return MapType(); |
583 | case GoLexer::KEYWORD_CHAN: |
584 | return ChanType2(); |
585 | default: |
586 | return nullptr; |
587 | } |
588 | } |
589 | |
590 | GoASTExpr *GoParser::ArrayOrSliceType(bool allowEllipsis) { |
591 | Rule r("ArrayType", this); |
592 | if (match(GoLexer::OP_LBRACK)) { |
593 | std::unique_ptr<GoASTExpr> len; |
594 | if (allowEllipsis && match(GoLexer::OP_DOTS)) { |
595 | len.reset(new GoASTEllipsis(nullptr)); |
596 | } else { |
597 | len.reset(Expression()); |
598 | } |
599 | |
600 | if (!match(GoLexer::OP_RBRACK)) |
601 | return r.error(); |
602 | GoASTExpr *elem = Type(); |
603 | if (!elem) |
604 | return syntaxerror(); |
605 | return new GoASTArrayType(len.release(), elem); |
606 | } |
607 | return r.error(); |
608 | } |
609 | |
610 | GoASTExpr *GoParser::StructType() { |
611 | if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE))) |
612 | return nullptr; |
613 | std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList); |
614 | while (auto *field = FieldDecl()) |
615 | fields->AddList(field); |
616 | if (!mustMatch(GoLexer::OP_RBRACE)) |
617 | return nullptr; |
618 | return new GoASTStructType(fields.release()); |
619 | } |
620 | |
621 | GoASTField *GoParser::FieldDecl() { |
622 | std::unique_ptr<GoASTField> f(new GoASTField); |
623 | GoASTExpr *t = FieldNamesAndType(f.get()); |
624 | if (!t) |
625 | t = AnonymousFieldType(); |
626 | if (!t) |
627 | return nullptr; |
628 | |
629 | if (auto *tok = match(GoLexer::LIT_STRING)) |
630 | f->SetTag(new GoASTBasicLit(*tok)); |
631 | if (!Semicolon()) |
632 | return syntaxerror(); |
633 | return f.release(); |
634 | } |
635 | |
636 | GoASTExpr *GoParser::FieldNamesAndType(GoASTField *field) { |
637 | Rule r("FieldNames", this); |
638 | for (auto *id = Identifier(); id; id = MoreIdentifierList()) |
639 | field->AddNames(id); |
640 | if (m_failed) |
641 | return nullptr; |
642 | GoASTExpr *t = Type(); |
643 | if (t) |
644 | return t; |
645 | return r.error(); |
646 | } |
647 | |
648 | GoASTExpr *GoParser::AnonymousFieldType() { |
649 | bool pointer = match(GoLexer::OP_STAR); |
650 | GoASTExpr *t = Type(); |
651 | if (!t) |
652 | return nullptr; |
653 | if (pointer) |
654 | return new GoASTStarExpr(t); |
655 | return t; |
656 | } |
657 | |
658 | GoASTExpr *GoParser::FunctionType() { |
659 | if (!match(GoLexer::KEYWORD_FUNC)) |
660 | return nullptr; |
661 | return Signature(); |
662 | } |
663 | |
664 | GoASTFuncType *GoParser::Signature() { |
665 | auto *params = Params(); |
666 | if (!params) |
667 | return syntaxerror(); |
668 | auto *result = Params(); |
669 | if (!result) { |
670 | if (auto *t = Type()) { |
671 | result = new GoASTFieldList; |
672 | auto *f = new GoASTField; |
673 | f->SetType(t); |
674 | result->AddList(f); |
675 | } |
676 | } |
677 | return new GoASTFuncType(params, result); |
678 | } |
679 | |
680 | GoASTFieldList *GoParser::Params() { |
681 | if (!match(GoLexer::OP_LPAREN)) |
682 | return nullptr; |
683 | std::unique_ptr<GoASTFieldList> l(new GoASTFieldList); |
684 | while (GoASTField *p = ParamDecl()) { |
685 | l->AddList(p); |
686 | if (!match(GoLexer::OP_COMMA)) |
687 | break; |
688 | } |
689 | if (!mustMatch(GoLexer::OP_RPAREN)) |
690 | return nullptr; |
691 | return l.release(); |
692 | } |
693 | |
694 | GoASTField *GoParser::ParamDecl() { |
695 | std::unique_ptr<GoASTField> field(new GoASTField); |
696 | GoASTIdent *id = Identifier(); |
697 | if (id) { |
698 | |
699 | |
700 | Rule r("NamedParam", this); |
701 | for (; id; id = MoreIdentifierList()) |
702 | field->AddNames(id); |
703 | GoASTExpr *t = ParamType(); |
704 | if (t) { |
705 | field->SetType(t); |
706 | return field.release(); |
707 | } |
708 | field.reset(new GoASTField); |
709 | r.error(); |
710 | } |
711 | GoASTExpr *t = ParamType(); |
712 | if (t) { |
713 | field->SetType(t); |
714 | return field.release(); |
715 | } |
716 | return nullptr; |
717 | } |
718 | |
719 | GoASTExpr *GoParser::ParamType() { |
720 | bool dots = match(GoLexer::OP_DOTS); |
721 | GoASTExpr *t = Type(); |
722 | if (!dots) |
723 | return t; |
724 | if (!t) |
725 | return syntaxerror(); |
726 | return new GoASTEllipsis(t); |
727 | } |
728 | |
729 | GoASTExpr *GoParser::InterfaceType() { |
730 | if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE)) |
| |
731 | return nullptr; |
732 | std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList); |
733 | while (true) { |
| 2 | | Loop condition is true. Entering loop body | |
|
| 7 | | Loop condition is true. Entering loop body | |
|
| 12 | | Loop condition is true. Entering loop body | |
|
| 17 | | Loop condition is true. Entering loop body | |
|
734 | Rule r("MethodSpec", this); |
735 | |
736 | std::unique_ptr<GoASTIdent> id(Identifier()); |
737 | if (!id) |
| |
| |
| |
| |
738 | break; |
739 | GoASTExpr *type = Signature(); |
740 | if (!type) { |
| |
| |
| |
| |
741 | r.error(); |
742 | id.reset(); |
743 | type = Name(); |
| 20 | | Calling 'GoParser::Name' | |
|
| 27 | | Returned allocated memory | |
|
744 | } |
745 | if (!Semicolon()) |
| |
| |
| |
| |
746 | return syntaxerror(); |
| 29 | | Potential leak of memory pointed to by 'type' |
|
747 | auto *f = new GoASTField; |
748 | if (id) |
| |
| |
| |
749 | f->AddNames(id.release()); |
750 | f->SetType(type); |
751 | methods->AddList(f); |
752 | } |
753 | if (!mustMatch(GoLexer::OP_RBRACE)) |
754 | return nullptr; |
755 | return new GoASTInterfaceType(methods.release()); |
756 | } |
757 | |
758 | GoASTExpr *GoParser::MapType() { |
759 | if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK))) |
760 | return nullptr; |
761 | std::unique_ptr<GoASTExpr> key(Type()); |
762 | if (!key) |
763 | return syntaxerror(); |
764 | if (!mustMatch(GoLexer::OP_RBRACK)) |
765 | return nullptr; |
766 | auto *elem = Type(); |
767 | if (!elem) |
768 | return syntaxerror(); |
769 | return new GoASTMapType(key.release(), elem); |
770 | } |
771 | |
772 | GoASTExpr *GoParser::ChanType() { |
773 | Rule r("chan", this); |
774 | if (match(GoLexer::OP_LT_MINUS)) { |
775 | if (match(GoLexer::KEYWORD_CHAN)) { |
776 | auto *elem = Type(); |
777 | if (!elem) |
778 | return syntaxerror(); |
779 | return new GoASTChanType(GoASTNode::eChanRecv, elem); |
780 | } |
781 | return r.error(); |
782 | } |
783 | return ChanType2(); |
784 | } |
785 | |
786 | GoASTExpr *GoParser::ChanType2() { |
787 | if (!match(GoLexer::KEYWORD_CHAN)) |
788 | return nullptr; |
789 | auto dir = GoASTNode::eChanBidir; |
790 | if (match(GoLexer::OP_LT_MINUS)) |
791 | dir = GoASTNode::eChanSend; |
792 | auto *elem = Type(); |
793 | if (!elem) |
794 | return syntaxerror(); |
795 | return new GoASTChanType(dir, elem); |
796 | } |
797 | |
798 | GoASTExpr *GoParser::Type() { |
799 | if (GoASTExpr *t = Type2()) |
800 | return t; |
801 | if (GoASTExpr *t = Name()) |
802 | return t; |
803 | if (GoASTExpr *t = ChanType()) |
804 | return t; |
805 | if (match(GoLexer::OP_STAR)) { |
806 | GoASTExpr *t = Type(); |
807 | if (!t) |
808 | return syntaxerror(); |
809 | return new GoASTStarExpr(t); |
810 | } |
811 | if (match(GoLexer::OP_LPAREN)) { |
812 | std::unique_ptr<GoASTExpr> t(Type()); |
813 | if (!t || !match(GoLexer::OP_RPAREN)) |
814 | return syntaxerror(); |
815 | return t.release(); |
816 | } |
817 | return nullptr; |
818 | } |
819 | |
820 | bool GoParser::Semicolon() { |
821 | if (match(GoLexer::OP_SEMICOLON)) |
822 | return true; |
823 | switch (peek()) { |
824 | case GoLexer::OP_RPAREN: |
825 | case GoLexer::OP_RBRACE: |
826 | case GoLexer::TOK_EOF: |
827 | return true; |
828 | default: |
829 | return false; |
830 | } |
831 | } |
832 | |
833 | GoASTExpr *GoParser::Name() { |
834 | if (auto *id = Identifier()) { |
| 21 | | Calling 'GoParser::Identifier' | |
|
| 24 | | Returned allocated memory | |
|
| |
835 | if (GoASTExpr *qual = QualifiedIdent(id)) |
| |
836 | return qual; |
837 | return id; |
838 | } |
839 | return nullptr; |
840 | } |
841 | |
842 | GoASTExpr *GoParser::QualifiedIdent(lldb_private::GoASTIdent *p) { |
843 | Rule r("QualifiedIdent", this); |
844 | llvm::SmallString<32> path(p->GetName().m_value); |
845 | GoLexer::Token *next; |
846 | bool have_slashes = false; |
847 | |
848 | while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER))) { |
849 | have_slashes = true; |
850 | path.append("/"); |
851 | path.append(next->m_value); |
852 | } |
853 | if (match(GoLexer::OP_DOT)) { |
854 | auto *name = Identifier(); |
855 | if (name) { |
856 | if (have_slashes) { |
857 | p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path))); |
858 | } |
859 | return new GoASTSelectorExpr(p, name); |
860 | } |
861 | } |
862 | return r.error(); |
863 | } |
864 | |
865 | llvm::StringRef GoParser::CopyString(llvm::StringRef s) { |
866 | return m_strings.insert(std::make_pair(s, 'x')).first->getKey(); |
867 | } |
868 | |
869 | void GoParser::GetError(Status &error) { |
870 | llvm::StringRef want; |
871 | if (m_failed) |
872 | want = |
873 | m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last; |
874 | else |
875 | want = m_error; |
876 | size_t len = m_lexer.BytesRemaining(); |
877 | if (len > 10) |
878 | len = 10; |
879 | llvm::StringRef got; |
880 | if (len == 0) |
881 | got = "<eof>"; |
882 | else |
883 | got = m_lexer.GetString(len); |
884 | error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", |
885 | want.str().c_str(), got.str().c_str()); |
886 | } |