Mercurial > hg > CbC > CbC_gcc
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 |