Bug Summary

File:tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
Warning:line 629, column 19
Potential leak of memory pointed to by 't'

Annotated Source Code

Press '?' to see keyboard shortcuts

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 _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn338205/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/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/lib/gcc/x86_64-linux-gnu/8/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-class-memaccess -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~svn338205/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-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp -faddrsig
1//===-- GoParser.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
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
18using namespace lldb_private;
19using namespace lldb;
20
21namespace {
22llvm::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} // namespace
43
44class GoParser::Rule {
45public:
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 // Set m_error in case this is the top level.
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 // And set m_last in case it isn't.
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
64private:
65 llvm::StringRef m_name;
66 GoParser *m_parser;
67 size_t m_pos;
68};
69
70GoParser::GoParser(const char *src)
71 : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID),
72 m_failed(false) {}
73
74GoASTStmt *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 /* TODO:
89case GoLexer::KEYWORD_GO:
90 return GoStmt();
91case GoLexer::KEYWORD_RETURN:
92 return ReturnStmt();
93case GoLexer::KEYWORD_BREAK:
94case GoLexer::KEYWORD_CONTINUE:
95case GoLexer::KEYWORD_GOTO:
96case GoLexer::KEYWORD_FALLTHROUGH:
97 return BranchStmt();
98case GoLexer::KEYWORD_IF:
99 return IfStmt();
100case GoLexer::KEYWORD_SWITCH:
101 return SwitchStmt();
102case GoLexer::KEYWORD_SELECT:
103 return SelectStmt();
104case GoLexer::KEYWORD_FOR:
105 return ForStmt();
106case GoLexer::KEYWORD_DEFER:
107 return DeferStmt();
108case GoLexer::KEYWORD_CONST:
109case GoLexer::KEYWORD_TYPE:
110case GoLexer::KEYWORD_VAR:
111 return DeclStmt();
112case GoLexer::TOK_IDENTIFIER:
113 if ((ret = LabeledStmt()) ||
114 (ret = ShortVarDecl()))
115 {
116 return ret;
117 }
118*/
119 default:
120 break;
121 }
122 GoASTExpr *expr = Expression();
123 if (expr == nullptr)
124 return r.error();
125 if (/*(ret = SendStmt(expr)) ||*/
126 (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) ||
127 (ret = ExpressionStmt(expr))) {
128 return ret;
129 }
130 delete expr;
131 return r.error();
132}
133
134GoASTStmt *GoParser::ExpressionStmt(GoASTExpr *e) {
135 if (Semicolon())
136 return new GoASTExprStmt(e);
137 return nullptr;
138}
139
140GoASTStmt *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
151GoASTStmt *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 // We don't want to own e until we know this is an assignment.
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
185GoASTStmt *GoParser::EmptyStmt() {
186 if (match(GoLexer::TOK_EOF))
187 return nullptr;
188 if (Semicolon())
189 return new GoASTEmptyStmt;
190 return nullptr;
191}
192
193GoASTStmt *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
206GoASTStmt *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
216GoASTStmt *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
232GoASTIdent *GoParser::Identifier() {
233 if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
234 return new GoASTIdent(*tok);
235 return nullptr;
236}
237
238GoASTExpr *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
248GoASTIdent *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
258GoASTExpr *GoParser::Expression() {
259 Rule r("Expression", this);
260 if (GoASTExpr *ret = OrExpr())
261 return ret;
262 return r.error();
263}
264
265GoASTExpr *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
288GoASTExpr *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
303GoASTExpr *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
318GoASTExpr *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
337GoASTExpr *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
355GoASTExpr *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
375GoASTExpr *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
388GoASTExpr *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 // MethodExpr should be handled by Selector
402 if (GoASTExpr *e = CompositeLit())
403 return e;
404 if (GoASTExpr *n = Name())
405 return n;
406 return FunctionLit();
407}
408
409GoASTExpr *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
423GoASTBlockStmt *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
434GoASTExpr *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
450GoASTCompositeLit *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
464GoASTExpr *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
477GoASTExpr *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
486GoASTExpr *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
514GoASTExpr *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
527GoASTExpr *GoParser::Arguments(GoASTExpr *e) {
528 if (match(GoLexer::OP_LPAREN)) {
529 std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
530 GoASTExpr *arg;
531 // ( ExpressionList | Type [ "," ExpressionList ] )
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 // Eat trailing comma
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
550GoASTExpr *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
571GoASTExpr *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
590GoASTExpr *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
610GoASTExpr *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
621GoASTField *GoParser::FieldDecl() {
622 std::unique_ptr<GoASTField> f(new GoASTField);
623 GoASTExpr *t = FieldNamesAndType(f.get());
624 if (!t)
1
Taking true branch
625 t = AnonymousFieldType();
2
Calling 'GoParser::AnonymousFieldType'
7
Returned allocated memory
626 if (!t)
8
Taking false branch
627 return nullptr;
628
629 if (auto *tok = match(GoLexer::LIT_STRING))
9
Potential leak of memory pointed to by 't'
630 f->SetTag(new GoASTBasicLit(*tok));
631 if (!Semicolon())
632 return syntaxerror();
633 return f.release();
634}
635
636GoASTExpr *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
648GoASTExpr *GoParser::AnonymousFieldType() {
649 bool pointer = match(GoLexer::OP_STAR);
650 GoASTExpr *t = Type();
651 if (!t)
3
Assuming 't' is non-null
4
Taking false branch
652 return nullptr;
653 if (pointer)
5
Taking true branch
654 return new GoASTStarExpr(t);
6
Memory is allocated
655 return t;
656}
657
658GoASTExpr *GoParser::FunctionType() {
659 if (!match(GoLexer::KEYWORD_FUNC))
660 return nullptr;
661 return Signature();
662}
663
664GoASTFuncType *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
680GoASTFieldList *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
694GoASTField *GoParser::ParamDecl() {
695 std::unique_ptr<GoASTField> field(new GoASTField);
696 GoASTIdent *id = Identifier();
697 if (id) {
698 // Try `IdentifierList [ "..." ] Type`.
699 // If that fails, backtrack and try `[ "..." ] Type`.
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
719GoASTExpr *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
729GoASTExpr *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) {
734 Rule r("MethodSpec", this);
735 // ( identifier Signature | TypeName ) ;
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();
744 }
745 if (!Semicolon())
746 return syntaxerror();
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
758GoASTExpr *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
772GoASTExpr *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
786GoASTExpr *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
798GoASTExpr *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
820bool 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
833GoASTExpr *GoParser::Name() {
834 if (auto *id = Identifier()) {
835 if (GoASTExpr *qual = QualifiedIdent(id))
836 return qual;
837 return id;
838 }
839 return nullptr;
840}
841
842GoASTExpr *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 // LLDB extension: support full/package/path.name
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
865llvm::StringRef GoParser::CopyString(llvm::StringRef s) {
866 return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
867}
868
869void 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}