Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
26b8f7eb
Commit
26b8f7eb
authored
Oct 24, 2013
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
compiler: Implement 3-index slicing.
From-SVN: r204034
parent
ccc23115
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
169 additions
and
42 deletions
+169
-42
gcc/go/gofrontend/expressions.cc
+124
-24
gcc/go/gofrontend/expressions.h
+21
-11
gcc/go/gofrontend/parse.cc
+19
-2
gcc/go/gofrontend/statements.cc
+3
-3
gcc/go/gofrontend/types.cc
+2
-2
No files found.
gcc/go/gofrontend/expressions.cc
View file @
26b8f7eb
...
@@ -10235,7 +10235,9 @@ Index_expression::do_traverse(Traverse* traverse)
...
@@ -10235,7 +10235,9 @@ Index_expression::do_traverse(Traverse* traverse)
if
(
Expression
::
traverse
(
&
this
->
left_
,
traverse
)
==
TRAVERSE_EXIT
if
(
Expression
::
traverse
(
&
this
->
left_
,
traverse
)
==
TRAVERSE_EXIT
||
Expression
::
traverse
(
&
this
->
start_
,
traverse
)
==
TRAVERSE_EXIT
||
Expression
::
traverse
(
&
this
->
start_
,
traverse
)
==
TRAVERSE_EXIT
||
(
this
->
end_
!=
NULL
||
(
this
->
end_
!=
NULL
&&
Expression
::
traverse
(
&
this
->
end_
,
traverse
)
==
TRAVERSE_EXIT
))
&&
Expression
::
traverse
(
&
this
->
end_
,
traverse
)
==
TRAVERSE_EXIT
)
||
(
this
->
cap_
!=
NULL
&&
Expression
::
traverse
(
&
this
->
cap_
,
traverse
)
==
TRAVERSE_EXIT
))
return
TRAVERSE_EXIT
;
return
TRAVERSE_EXIT
;
return
TRAVERSE_CONTINUE
;
return
TRAVERSE_CONTINUE
;
}
}
...
@@ -10250,6 +10252,7 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
...
@@ -10250,6 +10252,7 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
Expression
*
left
=
this
->
left_
;
Expression
*
left
=
this
->
left_
;
Expression
*
start
=
this
->
start_
;
Expression
*
start
=
this
->
start_
;
Expression
*
end
=
this
->
end_
;
Expression
*
end
=
this
->
end_
;
Expression
*
cap
=
this
->
cap_
;
Type
*
type
=
left
->
type
();
Type
*
type
=
left
->
type
();
if
(
type
->
is_error
())
if
(
type
->
is_error
())
...
@@ -10260,20 +10263,27 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
...
@@ -10260,20 +10263,27 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
return
Expression
::
make_error
(
location
);
return
Expression
::
make_error
(
location
);
}
}
else
if
(
type
->
array_type
()
!=
NULL
)
else
if
(
type
->
array_type
()
!=
NULL
)
return
Expression
::
make_array_index
(
left
,
start
,
end
,
location
);
return
Expression
::
make_array_index
(
left
,
start
,
end
,
cap
,
location
);
else
if
(
type
->
points_to
()
!=
NULL
else
if
(
type
->
points_to
()
!=
NULL
&&
type
->
points_to
()
->
array_type
()
!=
NULL
&&
type
->
points_to
()
->
array_type
()
!=
NULL
&&
!
type
->
points_to
()
->
is_slice_type
())
&&
!
type
->
points_to
()
->
is_slice_type
())
{
{
Expression
*
deref
=
Expression
::
make_unary
(
OPERATOR_MULT
,
left
,
Expression
*
deref
=
Expression
::
make_unary
(
OPERATOR_MULT
,
left
,
location
);
location
);
return
Expression
::
make_array_index
(
deref
,
start
,
end
,
location
);
return
Expression
::
make_array_index
(
deref
,
start
,
end
,
cap
,
location
);
}
}
else
if
(
type
->
is_string_type
())
else
if
(
type
->
is_string_type
())
{
if
(
cap
!=
NULL
)
{
error_at
(
location
,
"invalid 3-index slice of string"
);
return
Expression
::
make_error
(
location
);
}
return
Expression
::
make_string_index
(
left
,
start
,
end
,
location
);
return
Expression
::
make_string_index
(
left
,
start
,
end
,
location
);
}
else
if
(
type
->
map_type
()
!=
NULL
)
else
if
(
type
->
map_type
()
!=
NULL
)
{
{
if
(
end
!=
NULL
)
if
(
end
!=
NULL
||
cap
!=
NULL
)
{
{
error_at
(
location
,
"invalid slice of map"
);
error_at
(
location
,
"invalid slice of map"
);
return
Expression
::
make_error
(
location
);
return
Expression
::
make_error
(
location
);
...
@@ -10292,14 +10302,15 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
...
@@ -10292,14 +10302,15 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
}
}
}
}
// Write an indexed expression
(expr[expr:expr] or expr[expr]) to a
// Write an indexed expression
//
dump context
//
(expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context.
void
void
Index_expression
::
dump_index_expression
(
Ast_dump_context
*
ast_dump_context
,
Index_expression
::
dump_index_expression
(
Ast_dump_context
*
ast_dump_context
,
const
Expression
*
expr
,
const
Expression
*
expr
,
const
Expression
*
start
,
const
Expression
*
start
,
const
Expression
*
end
)
const
Expression
*
end
,
const
Expression
*
cap
)
{
{
expr
->
dump_expression
(
ast_dump_context
);
expr
->
dump_expression
(
ast_dump_context
);
ast_dump_context
->
ostream
()
<<
"["
;
ast_dump_context
->
ostream
()
<<
"["
;
...
@@ -10309,6 +10320,11 @@ Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
...
@@ -10309,6 +10320,11 @@ Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
ast_dump_context
->
ostream
()
<<
":"
;
ast_dump_context
->
ostream
()
<<
":"
;
end
->
dump_expression
(
ast_dump_context
);
end
->
dump_expression
(
ast_dump_context
);
}
}
if
(
cap
!=
NULL
)
{
ast_dump_context
->
ostream
()
<<
":"
;
cap
->
dump_expression
(
ast_dump_context
);
}
ast_dump_context
->
ostream
()
<<
"]"
;
ast_dump_context
->
ostream
()
<<
"]"
;
}
}
...
@@ -10319,16 +10335,16 @@ Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
...
@@ -10319,16 +10335,16 @@ Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
const
{
{
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
left_
,
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
left_
,
this
->
start_
,
this
->
end_
);
this
->
start_
,
this
->
end_
,
this
->
cap_
);
}
}
// Make an index expression.
// Make an index expression.
Expression
*
Expression
*
Expression
::
make_index
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
Expression
::
make_index
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
Location
location
)
Expression
*
cap
,
Location
location
)
{
{
return
new
Index_expression
(
left
,
start
,
end
,
location
);
return
new
Index_expression
(
left
,
start
,
end
,
cap
,
location
);
}
}
// An array index. This is used for both indexing and slicing.
// An array index. This is used for both indexing and slicing.
...
@@ -10337,9 +10353,9 @@ class Array_index_expression : public Expression
...
@@ -10337,9 +10353,9 @@ class Array_index_expression : public Expression
{
{
public
:
public
:
Array_index_expression
(
Expression
*
array
,
Expression
*
start
,
Array_index_expression
(
Expression
*
array
,
Expression
*
start
,
Expression
*
end
,
Location
location
)
Expression
*
end
,
Expression
*
cap
,
Location
location
)
:
Expression
(
EXPRESSION_ARRAY_INDEX
,
location
),
:
Expression
(
EXPRESSION_ARRAY_INDEX
,
location
),
array_
(
array
),
start_
(
start
),
end_
(
end
),
type_
(
NULL
)
array_
(
array
),
start_
(
start
),
end_
(
end
),
cap_
(
cap
),
type_
(
NULL
)
{
}
{
}
protected
:
protected
:
...
@@ -10363,6 +10379,9 @@ class Array_index_expression : public Expression
...
@@ -10363,6 +10379,9 @@ class Array_index_expression : public Expression
(
this
->
end_
==
NULL
(
this
->
end_
==
NULL
?
NULL
?
NULL
:
this
->
end_
->
copy
()),
:
this
->
end_
->
copy
()),
(
this
->
cap_
==
NULL
?
NULL
:
this
->
cap_
->
copy
()),
this
->
location
());
this
->
location
());
}
}
...
@@ -10394,6 +10413,9 @@ class Array_index_expression : public Expression
...
@@ -10394,6 +10413,9 @@ class Array_index_expression : public Expression
// The end index of a slice. This may be NULL for a simple array
// The end index of a slice. This may be NULL for a simple array
// index, or it may be a nil expression for the length of the array.
// index, or it may be a nil expression for the length of the array.
Expression
*
end_
;
Expression
*
end_
;
// The capacity argument of a slice. This may be NULL for an array index or
// slice.
Expression
*
cap_
;
// The type of the expression.
// The type of the expression.
Type
*
type_
;
Type
*
type_
;
};
};
...
@@ -10412,6 +10434,11 @@ Array_index_expression::do_traverse(Traverse* traverse)
...
@@ -10412,6 +10434,11 @@ Array_index_expression::do_traverse(Traverse* traverse)
if
(
Expression
::
traverse
(
&
this
->
end_
,
traverse
)
==
TRAVERSE_EXIT
)
if
(
Expression
::
traverse
(
&
this
->
end_
,
traverse
)
==
TRAVERSE_EXIT
)
return
TRAVERSE_EXIT
;
return
TRAVERSE_EXIT
;
}
}
if
(
this
->
cap_
!=
NULL
)
{
if
(
Expression
::
traverse
(
&
this
->
cap_
,
traverse
)
==
TRAVERSE_EXIT
)
return
TRAVERSE_EXIT
;
}
return
TRAVERSE_CONTINUE
;
return
TRAVERSE_CONTINUE
;
}
}
...
@@ -10451,6 +10478,8 @@ Array_index_expression::do_determine_type(const Type_context*)
...
@@ -10451,6 +10478,8 @@ Array_index_expression::do_determine_type(const Type_context*)
this
->
start_
->
determine_type_no_context
();
this
->
start_
->
determine_type_no_context
();
if
(
this
->
end_
!=
NULL
)
if
(
this
->
end_
!=
NULL
)
this
->
end_
->
determine_type_no_context
();
this
->
end_
->
determine_type_no_context
();
if
(
this
->
cap_
!=
NULL
)
this
->
cap_
->
determine_type_no_context
();
}
}
// Check types of an array index.
// Check types of an array index.
...
@@ -10473,6 +10502,14 @@ Array_index_expression::do_check_types(Gogo*)
...
@@ -10473,6 +10502,14 @@ Array_index_expression::do_check_types(Gogo*)
&&
(
!
this
->
end_
->
numeric_constant_value
(
&
nc
)
&&
(
!
this
->
end_
->
numeric_constant_value
(
&
nc
)
||
nc
.
to_unsigned_long
(
&
v
)
==
Numeric_constant
::
NC_UL_NOTINT
))
||
nc
.
to_unsigned_long
(
&
v
)
==
Numeric_constant
::
NC_UL_NOTINT
))
this
->
report_error
(
_
(
"slice end must be integer"
));
this
->
report_error
(
_
(
"slice end must be integer"
));
if
(
this
->
cap_
!=
NULL
&&
this
->
cap_
->
type
()
->
integer_type
()
==
NULL
&&
!
this
->
cap_
->
type
()
->
is_error
()
&&
!
this
->
cap_
->
is_nil_expression
()
&&
!
this
->
cap_
->
is_error_expression
()
&&
(
!
this
->
cap_
->
numeric_constant_value
(
&
nc
)
||
nc
.
to_unsigned_long
(
&
v
)
==
Numeric_constant
::
NC_UL_NOTINT
))
this
->
report_error
(
_
(
"slice capacity must be integer"
));
Array_type
*
array_type
=
this
->
array_
->
type
()
->
array_type
();
Array_type
*
array_type
=
this
->
array_
->
type
()
->
array_type
();
if
(
array_type
==
NULL
)
if
(
array_type
==
NULL
)
...
@@ -10510,8 +10547,10 @@ Array_index_expression::do_check_types(Gogo*)
...
@@ -10510,8 +10547,10 @@ Array_index_expression::do_check_types(Gogo*)
{
{
Numeric_constant
enc
;
Numeric_constant
enc
;
mpz_t
eval
;
mpz_t
eval
;
bool
eval_valid
=
false
;
if
(
this
->
end_
->
numeric_constant_value
(
&
enc
)
&&
enc
.
to_int
(
&
eval
))
if
(
this
->
end_
->
numeric_constant_value
(
&
enc
)
&&
enc
.
to_int
(
&
eval
))
{
{
eval_valid
=
true
;
if
(
mpz_sgn
(
eval
)
<
0
if
(
mpz_sgn
(
eval
)
<
0
||
mpz_sizeinbase
(
eval
,
2
)
>=
int_bits
||
mpz_sizeinbase
(
eval
,
2
)
>=
int_bits
||
(
lval_valid
&&
mpz_cmp
(
eval
,
lval
)
>
0
))
||
(
lval_valid
&&
mpz_cmp
(
eval
,
lval
)
>
0
))
...
@@ -10521,8 +10560,37 @@ Array_index_expression::do_check_types(Gogo*)
...
@@ -10521,8 +10560,37 @@ Array_index_expression::do_check_types(Gogo*)
}
}
else
if
(
ival_valid
&&
mpz_cmp
(
ival
,
eval
)
>
0
)
else
if
(
ival_valid
&&
mpz_cmp
(
ival
,
eval
)
>
0
)
this
->
report_error
(
_
(
"inverted slice range"
));
this
->
report_error
(
_
(
"inverted slice range"
));
mpz_clear
(
eval
);
}
}
Numeric_constant
cnc
;
mpz_t
cval
;
if
(
this
->
cap_
!=
NULL
&&
this
->
cap_
->
numeric_constant_value
(
&
cnc
)
&&
cnc
.
to_int
(
&
cval
))
{
if
(
mpz_sgn
(
cval
)
<
0
||
mpz_sizeinbase
(
cval
,
2
)
>=
int_bits
||
(
lval_valid
&&
mpz_cmp
(
cval
,
lval
)
>
0
))
{
error_at
(
this
->
cap_
->
location
(),
"array index out of bounds"
);
this
->
set_is_error
();
}
else
if
(
ival_valid
&&
mpz_cmp
(
ival
,
cval
)
>
0
)
{
error_at
(
this
->
cap_
->
location
(),
"invalid slice index: capacity less than start"
);
this
->
set_is_error
();
}
else
if
(
eval_valid
&&
mpz_cmp
(
eval
,
cval
)
>
0
)
{
error_at
(
this
->
cap_
->
location
(),
"invalid slice index: capacity less than length"
);
this
->
set_is_error
();
}
mpz_clear
(
cval
);
}
if
(
eval_valid
)
mpz_clear
(
eval
);
}
}
if
(
ival_valid
)
if
(
ival_valid
)
mpz_clear
(
ival
);
mpz_clear
(
ival
);
...
@@ -10602,9 +10670,17 @@ Array_index_expression::do_get_tree(Translate_context* context)
...
@@ -10602,9 +10670,17 @@ Array_index_expression::do_get_tree(Translate_context* context)
capacity_tree
=
save_expr
(
capacity_tree
);
capacity_tree
=
save_expr
(
capacity_tree
);
}
}
tree
cap_arg
=
capacity_tree
;
if
(
this
->
cap_
!=
NULL
)
{
cap_arg
=
this
->
cap_
->
get_tree
(
context
);
if
(
cap_arg
==
error_mark_node
)
return
error_mark_node
;
}
tree
length_type
=
(
length_tree
!=
NULL_TREE
tree
length_type
=
(
length_tree
!=
NULL_TREE
?
TREE_TYPE
(
length_tree
)
?
TREE_TYPE
(
length_tree
)
:
TREE_TYPE
(
cap
acity_tree
));
:
TREE_TYPE
(
cap
_arg
));
tree
bad_index
=
boolean_false_node
;
tree
bad_index
=
boolean_false_node
;
...
@@ -10676,6 +10752,29 @@ Array_index_expression::do_get_tree(Translate_context* context)
...
@@ -10676,6 +10752,29 @@ Array_index_expression::do_get_tree(Translate_context* context)
// Array slice.
// Array slice.
if
(
this
->
cap_
!=
NULL
)
{
if
(
!
DECL_P
(
cap_arg
))
cap_arg
=
save_expr
(
cap_arg
);
if
(
!
INTEGRAL_TYPE_P
(
TREE_TYPE
(
cap_arg
)))
cap_arg
=
convert_to_integer
(
length_type
,
cap_arg
);
bad_index
=
Expression
::
check_bounds
(
cap_arg
,
length_type
,
bad_index
,
loc
);
cap_arg
=
fold_convert_loc
(
loc
.
gcc_location
(),
length_type
,
cap_arg
);
tree
bad_cap
=
fold_build2_loc
(
loc
.
gcc_location
(),
TRUTH_OR_EXPR
,
boolean_type_node
,
fold_build2_loc
(
loc
.
gcc_location
(),
LT_EXPR
,
boolean_type_node
,
cap_arg
,
start_tree
),
fold_build2_loc
(
loc
.
gcc_location
(),
GT_EXPR
,
boolean_type_node
,
cap_arg
,
capacity_tree
));
bad_index
=
fold_build2_loc
(
loc
.
gcc_location
(),
TRUTH_OR_EXPR
,
boolean_type_node
,
bad_index
,
bad_cap
);
}
tree
end_tree
;
tree
end_tree
;
if
(
this
->
end_
->
is_nil_expression
())
if
(
this
->
end_
->
is_nil_expression
())
end_tree
=
length_tree
;
end_tree
=
length_tree
;
...
@@ -10701,11 +10800,12 @@ Array_index_expression::do_get_tree(Translate_context* context)
...
@@ -10701,11 +10800,12 @@ Array_index_expression::do_get_tree(Translate_context* context)
end_tree
,
start_tree
),
end_tree
,
start_tree
),
fold_build2_loc
(
loc
.
gcc_location
(),
fold_build2_loc
(
loc
.
gcc_location
(),
GT_EXPR
,
boolean_type_node
,
GT_EXPR
,
boolean_type_node
,
end_tree
,
cap
acity_tree
));
end_tree
,
cap
_arg
));
bad_index
=
fold_build2_loc
(
loc
.
gcc_location
(),
TRUTH_OR_EXPR
,
bad_index
=
fold_build2_loc
(
loc
.
gcc_location
(),
TRUTH_OR_EXPR
,
boolean_type_node
,
bad_index
,
bad_end
);
boolean_type_node
,
bad_index
,
bad_end
);
}
}
Type
*
element_type
=
array_type
->
element_type
();
Type
*
element_type
=
array_type
->
element_type
();
tree
element_type_tree
=
type_to_tree
(
element_type
->
get_backend
(
gogo
));
tree
element_type_tree
=
type_to_tree
(
element_type
->
get_backend
(
gogo
));
if
(
element_type_tree
==
error_mark_node
)
if
(
element_type_tree
==
error_mark_node
)
...
@@ -10729,8 +10829,7 @@ Array_index_expression::do_get_tree(Translate_context* context)
...
@@ -10729,8 +10829,7 @@ Array_index_expression::do_get_tree(Translate_context* context)
length_type
,
end_tree
,
start_tree
);
length_type
,
end_tree
,
start_tree
);
tree
result_capacity_tree
=
fold_build2_loc
(
loc
.
gcc_location
(),
MINUS_EXPR
,
tree
result_capacity_tree
=
fold_build2_loc
(
loc
.
gcc_location
(),
MINUS_EXPR
,
length_type
,
capacity_tree
,
length_type
,
cap_arg
,
start_tree
);
start_tree
);
tree
struct_tree
=
type_to_tree
(
this
->
type
()
->
get_backend
(
gogo
));
tree
struct_tree
=
type_to_tree
(
this
->
type
()
->
get_backend
(
gogo
));
go_assert
(
TREE_CODE
(
struct_tree
)
==
RECORD_TYPE
);
go_assert
(
TREE_CODE
(
struct_tree
)
==
RECORD_TYPE
);
...
@@ -10780,16 +10879,17 @@ Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
...
@@ -10780,16 +10879,17 @@ Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
const
{
{
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
array_
,
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
array_
,
this
->
start_
,
this
->
end_
);
this
->
start_
,
this
->
end_
,
this
->
cap_
);
}
}
// Make an array index expression. END may be NULL.
// Make an array index expression. END
and CAP
may be NULL.
Expression
*
Expression
*
Expression
::
make_array_index
(
Expression
*
array
,
Expression
*
start
,
Expression
::
make_array_index
(
Expression
*
array
,
Expression
*
start
,
Expression
*
end
,
Location
location
)
Expression
*
end
,
Expression
*
cap
,
Location
location
)
{
{
return
new
Array_index_expression
(
array
,
start
,
end
,
location
);
return
new
Array_index_expression
(
array
,
start
,
end
,
cap
,
location
);
}
}
// A string index. This is used for both indexing and slicing.
// A string index. This is used for both indexing and slicing.
...
@@ -11068,7 +11168,7 @@ String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
...
@@ -11068,7 +11168,7 @@ String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
const
{
{
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
string_
,
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
string_
,
this
->
start_
,
this
->
end_
);
this
->
start_
,
this
->
end_
,
NULL
);
}
}
// Make a string index expression. END may be NULL.
// Make a string index expression. END may be NULL.
...
@@ -11295,8 +11395,8 @@ void
...
@@ -11295,8 +11395,8 @@ void
Map_index_expression
::
do_dump_expression
(
Ast_dump_context
*
ast_dump_context
)
Map_index_expression
::
do_dump_expression
(
Ast_dump_context
*
ast_dump_context
)
const
const
{
{
Index_expression
::
dump_index_expression
(
ast_dump_context
,
Index_expression
::
dump_index_expression
(
ast_dump_context
,
this
->
map_
,
this
->
map_
,
this
->
index_
,
NULL
);
this
->
index_
,
NULL
,
NULL
);
}
}
// Make a map index expression.
// Make a map index expression.
...
...
gcc/go/gofrontend/expressions.h
View file @
26b8f7eb
...
@@ -232,19 +232,21 @@ class Expression
...
@@ -232,19 +232,21 @@ class Expression
Named_object
*
function
,
Location
);
Named_object
*
function
,
Location
);
// Make an index or slice expression. This is a parser expression
// Make an index or slice expression. This is a parser expression
// which represents LEFT[START:END]. END may be NULL, meaning an
// which represents LEFT[START:END:CAP]. END may be NULL, meaning an
// index rather than a slice. At parse time we may not know the
// index rather than a slice. CAP may be NULL, meaning we use the default
// type of LEFT. After parsing this is lowered to an array index, a
// capacity of LEFT. At parse time we may not know the type of LEFT.
// string index, or a map index.
// After parsing this is lowered to an array index, a string index,
// or a map index.
static
Expression
*
static
Expression
*
make_index
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
make_index
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
Location
);
Expression
*
cap
,
Location
);
// Make an array index expression. END may be NULL, in which case
// Make an array index expression. END may be NULL, in which case
// this is an lvalue.
// this is an lvalue. CAP may be NULL, in which case it defaults
// to cap(ARRAY).
static
Expression
*
static
Expression
*
make_array_index
(
Expression
*
array
,
Expression
*
start
,
Expression
*
end
,
make_array_index
(
Expression
*
array
,
Expression
*
start
,
Expression
*
end
,
Location
);
Expression
*
cap
,
Location
);
// Make a string index expression. END may be NULL. This is never
// Make a string index expression. END may be NULL. This is never
// an lvalue.
// an lvalue.
...
@@ -1672,9 +1674,9 @@ class Index_expression : public Parser_expression
...
@@ -1672,9 +1674,9 @@ class Index_expression : public Parser_expression
{
{
public
:
public
:
Index_expression
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
Index_expression
(
Expression
*
left
,
Expression
*
start
,
Expression
*
end
,
Location
location
)
Expression
*
cap
,
Location
location
)
:
Parser_expression
(
EXPRESSION_INDEX
,
location
),
:
Parser_expression
(
EXPRESSION_INDEX
,
location
),
left_
(
left
),
start_
(
start
),
end_
(
end
),
is_lvalue_
(
false
)
left_
(
left
),
start_
(
start
),
end_
(
end
),
cap_
(
cap
),
is_lvalue_
(
false
)
{
}
{
}
// Record that this expression is an lvalue.
// Record that this expression is an lvalue.
...
@@ -1683,10 +1685,11 @@ class Index_expression : public Parser_expression
...
@@ -1683,10 +1685,11 @@ class Index_expression : public Parser_expression
{
this
->
is_lvalue_
=
true
;
}
{
this
->
is_lvalue_
=
true
;
}
// Dump an index expression, i.e. an expression of the form
// Dump an index expression, i.e. an expression of the form
// expr[expr]
or expr[expr:expr],
to a dump context.
// expr[expr]
, expr[expr:expr], or expr[expr:expr:expr]
to a dump context.
static
void
static
void
dump_index_expression
(
Ast_dump_context
*
,
const
Expression
*
expr
,
dump_index_expression
(
Ast_dump_context
*
,
const
Expression
*
expr
,
const
Expression
*
start
,
const
Expression
*
end
);
const
Expression
*
start
,
const
Expression
*
end
,
const
Expression
*
cap
);
protected
:
protected
:
int
int
...
@@ -1702,6 +1705,9 @@ class Index_expression : public Parser_expression
...
@@ -1702,6 +1705,9 @@ class Index_expression : public Parser_expression
(
this
->
end_
==
NULL
(
this
->
end_
==
NULL
?
NULL
?
NULL
:
this
->
end_
->
copy
()),
:
this
->
end_
->
copy
()),
(
this
->
cap_
==
NULL
?
NULL
:
this
->
cap_
->
copy
()),
this
->
location
());
this
->
location
());
}
}
...
@@ -1723,6 +1729,10 @@ class Index_expression : public Parser_expression
...
@@ -1723,6 +1729,10 @@ class Index_expression : public Parser_expression
// The second index. This is NULL for an index, non-NULL for a
// The second index. This is NULL for an index, non-NULL for a
// slice.
// slice.
Expression
*
end_
;
Expression
*
end_
;
// The capacity argument. This is NULL for indices and slices that use the
// default capacity, non-NULL for indices and slices that specify the
// capacity.
Expression
*
cap_
;
// Whether this is being used as an l-value. We set this during the
// Whether this is being used as an l-value. We set this during the
// parse because map index expressions need to know.
// parse because map index expressions need to know.
bool
is_lvalue_
;
bool
is_lvalue_
;
...
...
gcc/go/gofrontend/parse.cc
View file @
26b8f7eb
...
@@ -3152,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
...
@@ -3152,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
}
}
// Index = "[" Expression "]" .
// Index = "[" Expression "]" .
// Slice = "[" Expression ":" [ Expression ] "]" .
// Slice = "[" Expression ":" [ Expression ]
[ ":" Expression ]
"]" .
Expression
*
Expression
*
Parse
::
index
(
Expression
*
expr
)
Parse
::
index
(
Expression
*
expr
)
...
@@ -3178,14 +3178,31 @@ Parse::index(Expression* expr)
...
@@ -3178,14 +3178,31 @@ Parse::index(Expression* expr)
// We use nil to indicate a missing high expression.
// We use nil to indicate a missing high expression.
if
(
this
->
advance_token
()
->
is_op
(
OPERATOR_RSQUARE
))
if
(
this
->
advance_token
()
->
is_op
(
OPERATOR_RSQUARE
))
end
=
Expression
::
make_nil
(
this
->
location
());
end
=
Expression
::
make_nil
(
this
->
location
());
else
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_COLON
))
{
error_at
(
this
->
location
(),
"middle index required in 3-index slice"
);
end
=
Expression
::
make_error
(
this
->
location
());
}
else
else
end
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
,
NULL
);
end
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
,
NULL
);
}
}
Expression
*
cap
=
NULL
;
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_COLON
))
{
if
(
this
->
advance_token
()
->
is_op
(
OPERATOR_RSQUARE
))
{
error_at
(
this
->
location
(),
"final index required in 3-index slice"
);
cap
=
Expression
::
make_error
(
this
->
location
());
}
else
cap
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
,
NULL
);
}
if
(
!
this
->
peek_token
()
->
is_op
(
OPERATOR_RSQUARE
))
if
(
!
this
->
peek_token
()
->
is_op
(
OPERATOR_RSQUARE
))
error_at
(
this
->
location
(),
"missing %<]%>"
);
error_at
(
this
->
location
(),
"missing %<]%>"
);
else
else
this
->
advance_token
();
this
->
advance_token
();
return
Expression
::
make_index
(
expr
,
start
,
end
,
location
);
return
Expression
::
make_index
(
expr
,
start
,
end
,
cap
,
location
);
}
}
// Call = "(" [ ArgumentList [ "," ] ] ")" .
// Call = "(" [ ArgumentList [ "," ] ] ")" .
...
...
gcc/go/gofrontend/statements.cc
View file @
26b8f7eb
...
@@ -5540,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
...
@@ -5540,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
ref
=
this
->
make_range_ref
(
range_object
,
range_temp
,
loc
);
ref
=
this
->
make_range_ref
(
range_object
,
range_temp
,
loc
);
Expression
*
ref2
=
Expression
::
make_temporary_reference
(
index_temp
,
loc
);
Expression
*
ref2
=
Expression
::
make_temporary_reference
(
index_temp
,
loc
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
ref2
,
NULL
,
loc
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
ref2
,
NULL
,
NULL
,
loc
);
tref
=
Expression
::
make_temporary_reference
(
value_temp
,
loc
);
tref
=
Expression
::
make_temporary_reference
(
value_temp
,
loc
);
tref
->
set_is_lvalue
();
tref
->
set_is_lvalue
();
...
@@ -5641,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo,
...
@@ -5641,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo,
ref
=
Expression
::
make_temporary_reference
(
for_temp
,
loc
);
ref
=
Expression
::
make_temporary_reference
(
for_temp
,
loc
);
Expression
*
ref2
=
Expression
::
make_temporary_reference
(
index_temp
,
loc
);
Expression
*
ref2
=
Expression
::
make_temporary_reference
(
index_temp
,
loc
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
ref2
,
NULL
,
loc
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
ref2
,
NULL
,
NULL
,
loc
);
tref
=
Expression
::
make_temporary_reference
(
value_temp
,
loc
);
tref
=
Expression
::
make_temporary_reference
(
value_temp
,
loc
);
tref
->
set_is_lvalue
();
tref
->
set_is_lvalue
();
...
@@ -5849,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*,
...
@@ -5849,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*,
Expression
*
zexpr
=
Expression
::
make_integer
(
&
zval
,
NULL
,
loc
);
Expression
*
zexpr
=
Expression
::
make_integer
(
&
zval
,
NULL
,
loc
);
mpz_clear
(
zval
);
mpz_clear
(
zval
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
zexpr
,
NULL
,
loc
);
Expression
*
index
=
Expression
::
make_index
(
ref
,
zexpr
,
NULL
,
NULL
,
loc
);
Expression
*
ne
=
Expression
::
make_binary
(
OPERATOR_NOTEQ
,
index
,
Expression
*
ne
=
Expression
::
make_binary
(
OPERATOR_NOTEQ
,
index
,
Expression
::
make_nil
(
loc
),
Expression
::
make_nil
(
loc
),
...
...
gcc/go/gofrontend/types.cc
View file @
26b8f7eb
...
@@ -5645,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name)
...
@@ -5645,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name)
Expression
*
e1
=
Expression
::
make_temporary_reference
(
p1
,
bloc
);
Expression
*
e1
=
Expression
::
make_temporary_reference
(
p1
,
bloc
);
e1
=
Expression
::
make_unary
(
OPERATOR_MULT
,
e1
,
bloc
);
e1
=
Expression
::
make_unary
(
OPERATOR_MULT
,
e1
,
bloc
);
ref
=
Expression
::
make_temporary_reference
(
index
,
bloc
);
ref
=
Expression
::
make_temporary_reference
(
index
,
bloc
);
e1
=
Expression
::
make_array_index
(
e1
,
ref
,
NULL
,
bloc
);
e1
=
Expression
::
make_array_index
(
e1
,
ref
,
NULL
,
NULL
,
bloc
);
Expression
*
e2
=
Expression
::
make_temporary_reference
(
p2
,
bloc
);
Expression
*
e2
=
Expression
::
make_temporary_reference
(
p2
,
bloc
);
e2
=
Expression
::
make_unary
(
OPERATOR_MULT
,
e2
,
bloc
);
e2
=
Expression
::
make_unary
(
OPERATOR_MULT
,
e2
,
bloc
);
ref
=
Expression
::
make_temporary_reference
(
index
,
bloc
);
ref
=
Expression
::
make_temporary_reference
(
index
,
bloc
);
e2
=
Expression
::
make_array_index
(
e2
,
ref
,
NULL
,
bloc
);
e2
=
Expression
::
make_array_index
(
e2
,
ref
,
NULL
,
NULL
,
bloc
);
Expression
*
cond
=
Expression
::
make_binary
(
OPERATOR_NOTEQ
,
e1
,
e2
,
bloc
);
Expression
*
cond
=
Expression
::
make_binary
(
OPERATOR_NOTEQ
,
e1
,
e2
,
bloc
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment