comparison gcc/go/gofrontend/parse.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
18 18
19 // Return true if v1 should be considered to be less than v2. 19 // Return true if v1 should be considered to be less than v2.
20 20
21 bool 21 bool
22 Parse::Enclosing_var_comparison::operator()(const Enclosing_var& v1, 22 Parse::Enclosing_var_comparison::operator()(const Enclosing_var& v1,
23 const Enclosing_var& v2) 23 const Enclosing_var& v2) const
24 { 24 {
25 if (v1.var() == v2.var()) 25 if (v1.var() == v2.var())
26 return false; 26 return false;
27 27
28 const std::string& n1(v1.var()->name()); 28 const std::string& n1(v1.var()->name());
48 unget_token_valid_(false), 48 unget_token_valid_(false),
49 is_erroneous_function_(false), 49 is_erroneous_function_(false),
50 gogo_(gogo), 50 gogo_(gogo),
51 break_stack_(NULL), 51 break_stack_(NULL),
52 continue_stack_(NULL), 52 continue_stack_(NULL),
53 iota_(0),
54 enclosing_vars_() 53 enclosing_vars_()
55 { 54 {
56 } 55 }
57 56
58 // Return the current token. 57 // Return the current token.
1405 void 1404 void
1406 Parse::const_decl() 1405 Parse::const_decl()
1407 { 1406 {
1408 go_assert(this->peek_token()->is_keyword(KEYWORD_CONST)); 1407 go_assert(this->peek_token()->is_keyword(KEYWORD_CONST));
1409 this->advance_token(); 1408 this->advance_token();
1410 this->reset_iota(); 1409
1411 1410 int iota = 0;
1412 Type* last_type = NULL; 1411 Type* last_type = NULL;
1413 Expression_list* last_expr_list = NULL; 1412 Expression_list* last_expr_list = NULL;
1414 1413
1415 if (!this->peek_token()->is_op(OPERATOR_LPAREN)) 1414 if (!this->peek_token()->is_op(OPERATOR_LPAREN))
1416 this->const_spec(&last_type, &last_expr_list); 1415 this->const_spec(iota, &last_type, &last_expr_list);
1417 else 1416 else
1418 { 1417 {
1419 this->advance_token(); 1418 this->advance_token();
1420 while (!this->peek_token()->is_op(OPERATOR_RPAREN)) 1419 while (!this->peek_token()->is_op(OPERATOR_RPAREN))
1421 { 1420 {
1422 this->const_spec(&last_type, &last_expr_list); 1421 this->const_spec(iota, &last_type, &last_expr_list);
1422 ++iota;
1423 if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) 1423 if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
1424 this->advance_token(); 1424 this->advance_token();
1425 else if (!this->peek_token()->is_op(OPERATOR_RPAREN)) 1425 else if (!this->peek_token()->is_op(OPERATOR_RPAREN))
1426 { 1426 {
1427 go_error_at(this->location(), 1427 go_error_at(this->location(),
1438 } 1438 }
1439 1439
1440 // ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] . 1440 // ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] .
1441 1441
1442 void 1442 void
1443 Parse::const_spec(Type** last_type, Expression_list** last_expr_list) 1443 Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
1444 { 1444 {
1445 Typed_identifier_list til; 1445 Typed_identifier_list til;
1446 this->identifier_list(&til); 1446 this->identifier_list(&til);
1447 1447
1448 Type* type = NULL; 1448 Type* type = NULL;
1490 } 1490 }
1491 if (type != NULL) 1491 if (type != NULL)
1492 pi->set_type(type); 1492 pi->set_type(type);
1493 1493
1494 if (!Gogo::is_sink_name(pi->name())) 1494 if (!Gogo::is_sink_name(pi->name()))
1495 this->gogo_->add_constant(*pi, *pe, this->iota_value()); 1495 this->gogo_->add_constant(*pi, *pe, iota);
1496 else 1496 else
1497 { 1497 {
1498 static int count; 1498 static int count;
1499 char buf[30]; 1499 char buf[30];
1500 snprintf(buf, sizeof buf, ".$sinkconst%d", count); 1500 snprintf(buf, sizeof buf, ".$sinkconst%d", count);
1501 ++count; 1501 ++count;
1502 Typed_identifier ti(std::string(buf), type, pi->location()); 1502 Typed_identifier ti(std::string(buf), type, pi->location());
1503 Named_object* no = this->gogo_->add_constant(ti, *pe, this->iota_value()); 1503 Named_object* no = this->gogo_->add_constant(ti, *pe, iota);
1504 no->const_value()->set_is_sink(); 1504 no->const_value()->set_is_sink();
1505 } 1505 }
1506 } 1506 }
1507 if (pe != expr_list->end()) 1507 if (pe != expr_list->end())
1508 go_error_at(this->location(), "too many initializers"); 1508 go_error_at(this->location(), "too many initializers");
1509
1510 this->increment_iota();
1511 1509
1512 return; 1510 return;
1513 } 1511 }
1514 1512
1515 // TypeDecl = "type" Decl<TypeSpec> . 1513 // TypeDecl = "type" Decl<TypeSpec> .
2360 { GOPRAGMA_NORACE, "norace", false, true, true }, 2358 { GOPRAGMA_NORACE, "norace", false, true, true },
2361 { GOPRAGMA_NOSPLIT, "nosplit", false, true, true }, 2359 { GOPRAGMA_NOSPLIT, "nosplit", false, true, true },
2362 { GOPRAGMA_NOINLINE, "noinline", false, true, true }, 2360 { GOPRAGMA_NOINLINE, "noinline", false, true, true },
2363 { GOPRAGMA_SYSTEMSTACK, "systemstack", false, true, true }, 2361 { GOPRAGMA_SYSTEMSTACK, "systemstack", false, true, true },
2364 { GOPRAGMA_NOWRITEBARRIER, "nowritebarrier", false, true, true }, 2362 { GOPRAGMA_NOWRITEBARRIER, "nowritebarrier", false, true, true },
2365 { GOPRAGMA_NOWRITEBARRIERREC, "nowritebarrierrec", false, true, true }, 2363 { GOPRAGMA_NOWRITEBARRIERREC, "nowritebarrierrec", false, true,
2364 true },
2365 { GOPRAGMA_YESWRITEBARRIERREC, "yeswritebarrierrec", false, true,
2366 true },
2366 { GOPRAGMA_CGOUNSAFEARGS, "cgo_unsafe_args", false, true, true }, 2367 { GOPRAGMA_CGOUNSAFEARGS, "cgo_unsafe_args", false, true, true },
2367 { GOPRAGMA_UINTPTRESCAPES, "uintptrescapes", true, true, true }, 2368 { GOPRAGMA_UINTPTRESCAPES, "uintptrescapes", true, true, true },
2368 }; 2369 };
2369 2370
2370 bool is_decl = !this->peek_token()->is_op(OPERATOR_LCURLY); 2371 bool is_decl = !this->peek_token()->is_op(OPERATOR_LCURLY);
2743 this_function->func_value()->add_closure_field(var, location); 2744 this_function->func_value()->add_closure_field(var, location);
2744 } 2745 }
2745 2746
2746 Expression* closure_ref = Expression::make_var_reference(closure, 2747 Expression* closure_ref = Expression::make_var_reference(closure,
2747 location); 2748 location);
2748 closure_ref = Expression::make_unary(OPERATOR_MULT, closure_ref, location); 2749 closure_ref =
2750 Expression::make_dereference(closure_ref,
2751 Expression::NIL_CHECK_NOT_NEEDED,
2752 location);
2749 2753
2750 // The closure structure holds pointers to the variables, so we need 2754 // The closure structure holds pointers to the variables, so we need
2751 // to introduce an indirection. 2755 // to introduce an indirection.
2752 Expression* e = Expression::make_field_reference(closure_ref, 2756 Expression* e = Expression::make_field_reference(closure_ref,
2753 ins.first->index(), 2757 ins.first->index(),
2754 location); 2758 location);
2755 e = Expression::make_unary(OPERATOR_MULT, e, location); 2759 e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
2760 location);
2756 return Expression::make_enclosing_var_reference(e, var, location); 2761 return Expression::make_enclosing_var_reference(e, var, location);
2757 } 2762 }
2758 2763
2759 // CompositeLit = LiteralType LiteralValue . 2764 // CompositeLit = LiteralType LiteralValue .
2760 // LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | 2765 // LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
3053 3058
3054 Named_object* closure_var = function->func_value()->closure_var(); 3059 Named_object* closure_var = function->func_value()->closure_var();
3055 Struct_type* st = closure_var->var_value()->type()->deref()->struct_type(); 3060 Struct_type* st = closure_var->var_value()->type()->deref()->struct_type();
3056 Expression* cv = Expression::make_struct_composite_literal(st, initializer, 3061 Expression* cv = Expression::make_struct_composite_literal(st, initializer,
3057 location); 3062 location);
3058
3059 // When compiling the runtime, closures do not escape. When escape
3060 // analysis becomes the default, and applies to closures, this
3061 // should be changed to make it an error if a closure escapes.
3062 if (this->gogo_->compiling_runtime()
3063 && this->gogo_->package_name() == "runtime")
3064 {
3065 Temporary_statement* ctemp = Statement::make_temporary(st, cv, location);
3066 this->gogo_->add_statement(ctemp);
3067 Expression* ref = Expression::make_temporary_reference(ctemp, location);
3068 Expression* addr = Expression::make_unary(OPERATOR_AND, ref, location);
3069 addr->unary_expression()->set_does_not_escape();
3070 return addr;
3071 }
3072
3073 return Expression::make_heap_expression(cv, location); 3063 return Expression::make_heap_expression(cv, location);
3074 } 3064 }
3075 3065
3076 // PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } . 3066 // PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } .
3077 3067
4312 // Make it easier to simplify go/defer statements by putting every 4302 // Make it easier to simplify go/defer statements by putting every
4313 // statement in its own block. 4303 // statement in its own block.
4314 this->gogo_->start_block(stat_location); 4304 this->gogo_->start_block(stat_location);
4315 Statement* stat; 4305 Statement* stat;
4316 if (is_go) 4306 if (is_go)
4317 stat = Statement::make_go_statement(call_expr, stat_location); 4307 {
4308 stat = Statement::make_go_statement(call_expr, stat_location);
4309 call_expr->set_is_concurrent();
4310 }
4318 else 4311 else
4319 stat = Statement::make_defer_statement(call_expr, stat_location); 4312 {
4313 stat = Statement::make_defer_statement(call_expr, stat_location);
4314 call_expr->set_is_deferred();
4315 }
4320 this->gogo_->add_statement(stat); 4316 this->gogo_->add_statement(stat);
4321 this->gogo_->add_block(this->gogo_->finish_block(stat_location), 4317 this->gogo_->add_block(this->gogo_->finish_block(stat_location),
4322 stat_location); 4318 stat_location);
4323 } 4319 }
4324 4320
4676 bool is_fallthrough = false; 4672 bool is_fallthrough = false;
4677 if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH)) 4673 if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH))
4678 { 4674 {
4679 Location fallthrough_loc = this->location(); 4675 Location fallthrough_loc = this->location();
4680 is_fallthrough = true; 4676 is_fallthrough = true;
4681 if (this->advance_token()->is_op(OPERATOR_SEMICOLON)) 4677 while (this->advance_token()->is_op(OPERATOR_SEMICOLON))
4682 this->advance_token(); 4678 ;
4683 if (this->peek_token()->is_op(OPERATOR_RCURLY)) 4679 if (this->peek_token()->is_op(OPERATOR_RCURLY))
4684 go_error_at(fallthrough_loc, 4680 go_error_at(fallthrough_loc,
4685 _("cannot fallthrough final case in switch")); 4681 _("cannot fallthrough final case in switch"));
4682 else if (!this->peek_token()->is_keyword(KEYWORD_CASE)
4683 && !this->peek_token()->is_keyword(KEYWORD_DEFAULT))
4684 {
4685 go_error_at(fallthrough_loc, "fallthrough statement out of place");
4686 while (!this->peek_token()->is_keyword(KEYWORD_CASE)
4687 && !this->peek_token()->is_keyword(KEYWORD_DEFAULT)
4688 && !this->peek_token()->is_op(OPERATOR_RCURLY)
4689 && !this->peek_token()->is_eof())
4690 {
4691 if (this->statement_may_start_here())
4692 this->statement_list();
4693 else
4694 this->advance_token();
4695 }
4696 }
4686 } 4697 }
4687 4698
4688 if (is_default) 4699 if (is_default)
4689 { 4700 {
4690 if (*saw_default) 4701 if (*saw_default)
5169 // send or receive expression. If SAW_COMMA is true, then *VAL is 5180 // send or receive expression. If SAW_COMMA is true, then *VAL is
5170 // set and we just read a comma. 5181 // set and we just read a comma.
5171 5182
5172 Expression* e; 5183 Expression* e;
5173 if (saw_comma || !this->peek_token()->is_op(OPERATOR_CHANOP)) 5184 if (saw_comma || !this->peek_token()->is_op(OPERATOR_CHANOP))
5174 e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL); 5185 {
5186 e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL);
5187 if (e->receive_expression() != NULL)
5188 {
5189 *is_send = false;
5190 *channel = e->receive_expression()->channel();
5191 // This is 'case (<-c):'. We now expect ':'. If we see
5192 // '<-', then we have case (<-c)<-v:
5193 if (!this->peek_token()->is_op(OPERATOR_CHANOP))
5194 return true;
5195 }
5196 }
5175 else 5197 else
5176 { 5198 {
5177 // case <-c: 5199 // case <-c:
5178 *is_send = false; 5200 *is_send = false;
5179 this->advance_token(); 5201 this->advance_token();
5198 saw_comma = true; 5220 saw_comma = true;
5199 } 5221 }
5200 5222
5201 if (this->peek_token()->is_op(OPERATOR_EQ)) 5223 if (this->peek_token()->is_op(OPERATOR_EQ))
5202 { 5224 {
5203 if (!this->advance_token()->is_op(OPERATOR_CHANOP))
5204 {
5205 go_error_at(this->location(), "missing %<<-%>");
5206 return false;
5207 }
5208 *is_send = false; 5225 *is_send = false;
5209 this->advance_token(); 5226 this->advance_token();
5210 *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL); 5227 Location recvloc = this->location();
5228 Expression* recvexpr = this->expression(PRECEDENCE_NORMAL, false,
5229 true, NULL, NULL);
5230 if (recvexpr->receive_expression() == NULL)
5231 {
5232 go_error_at(recvloc, "missing %<<-%>");
5233 return false;
5234 }
5235 *channel = recvexpr->receive_expression()->channel();
5211 if (saw_comma) 5236 if (saw_comma)
5212 { 5237 {
5213 // case v, e = <-c: 5238 // case v, e = <-c:
5214 // *VAL is already set. 5239 // *VAL is already set.
5215 if (!e->is_sink_expression()) 5240 if (!e->is_sink_expression())
5454 no = this->init_var(*pti, NULL, expr, true, true, &is_new, NULL, NULL); 5479 no = this->init_var(*pti, NULL, expr, true, true, &is_new, NULL, NULL);
5455 if (is_new && no->is_variable()) 5480 if (is_new && no->is_variable())
5456 no->var_value()->set_type_from_range_value(); 5481 no->var_value()->set_type_from_range_value();
5457 if (is_new) 5482 if (is_new)
5458 any_new = true; 5483 any_new = true;
5459 if (!Gogo::is_sink_name(pti->name())) 5484 p_range_clause->value = Expression::make_var_reference(no, location);
5460 p_range_clause->value = Expression::make_var_reference(no, location);
5461 } 5485 }
5462 5486
5463 if (!any_new) 5487 if (!any_new)
5464 go_error_at(location, "variables redeclared but no variable is new"); 5488 go_error_at(location, "variables redeclared but no variable is new");
5465 } 5489 }
5819 this->skip_past_error(OPERATOR_INVALID); 5843 this->skip_past_error(OPERATOR_INVALID);
5820 } 5844 }
5821 } 5845 }
5822 } 5846 }
5823 5847
5824 // Reset the current iota value.
5825
5826 void
5827 Parse::reset_iota()
5828 {
5829 this->iota_ = 0;
5830 }
5831
5832 // Return the current iota value.
5833
5834 int
5835 Parse::iota_value()
5836 {
5837 return this->iota_;
5838 }
5839
5840 // Increment the current iota value.
5841
5842 void
5843 Parse::increment_iota()
5844 {
5845 ++this->iota_;
5846 }
5847
5848 // Skip forward to a semicolon or OP. OP will normally be 5848 // Skip forward to a semicolon or OP. OP will normally be
5849 // OPERATOR_RPAREN or OPERATOR_RCURLY. If we find a semicolon, move 5849 // OPERATOR_RPAREN or OPERATOR_RCURLY. If we find a semicolon, move
5850 // past it and return. If we find OP, it will be the next token to 5850 // past it and return. If we find OP, it will be the next token to
5851 // read. Return true if we are OK, false if we found EOF. 5851 // read. Return true if we are OK, false if we found EOF.
5852 5852