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
3ef479f3
Commit
3ef479f3
authored
Jun 12, 2013
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
compiler: implement Go 1.1 spec of terminating statements.
From-SVN: r200047
parent
4b02c962
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
136 additions
and
42 deletions
+136
-42
gcc/go/gofrontend/go.cc
+4
-5
gcc/go/gofrontend/statements.cc
+111
-35
gcc/go/gofrontend/statements.h
+21
-2
No files found.
gcc/go/gofrontend/go.cc
View file @
3ef479f3
...
...
@@ -44,7 +44,7 @@ go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
GO_EXTERN_C
void
go_parse_input_files
(
const
char
**
filenames
,
unsigned
int
filename_count
,
bool
only_check_syntax
,
bool
require_return_statement
)
bool
only_check_syntax
,
bool
)
{
go_assert
(
filename_count
>
0
);
...
...
@@ -84,6 +84,9 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Finalize method lists and build stub methods for named types.
::
gogo
->
finalize_methods
();
// Check that functions have a terminating statement.
::
gogo
->
check_return_statements
();
// Now that we have seen all the names, lower the parse tree into a
// form which is easier to use.
::
gogo
->
lower_parse_tree
();
...
...
@@ -104,10 +107,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
if
(
only_check_syntax
)
return
;
// Check that functions have return statements.
if
(
require_return_statement
)
::
gogo
->
check_return_statements
();
// Export global identifiers as appropriate.
::
gogo
->
do_exports
();
...
...
gcc/go/gofrontend/statements.cc
View file @
3ef479f3
...
...
@@ -1707,8 +1707,8 @@ Expression_statement::do_check_types(Gogo*)
this
->
expr_
->
discarding_value
();
}
// An expression statement
may fall through unless it is a call to a
//
function which does not return
.
// An expression statement
is only a terminating statement if it is
//
a call to panic
.
bool
Expression_statement
::
do_may_fall_through
()
const
...
...
@@ -1717,22 +1717,28 @@ Expression_statement::do_may_fall_through() const
if
(
call
!=
NULL
)
{
const
Expression
*
fn
=
call
->
fn
();
const
Func_expression
*
fe
=
fn
->
func_expression
();
if
(
fe
!=
NULL
)
// panic is still an unknown named object.
const
Unknown_expression
*
ue
=
fn
->
unknown_expression
();
if
(
ue
!=
NULL
)
{
const
Named_object
*
no
=
f
e
->
named_object
();
Named_object
*
no
=
u
e
->
named_object
();
Function_type
*
fntype
;
if
(
no
->
is_function
())
fntype
=
no
->
func_value
()
->
type
();
else
if
(
no
->
is_function_declaration
())
fntype
=
no
->
func_declaration_value
()
->
type
();
else
fntype
=
NULL
;
// The builtin function panic does not return.
if
(
fntype
!=
NULL
&&
fntype
->
is_builtin
()
&&
no
->
name
()
==
"panic"
)
return
false
;
if
(
no
->
is_unknown
())
no
=
no
->
unknown_value
()
->
real_named_object
();
if
(
no
!=
NULL
)
{
Function_type
*
fntype
;
if
(
no
->
is_function
())
fntype
=
no
->
func_value
()
->
type
();
else
if
(
no
->
is_function_declaration
())
fntype
=
no
->
func_declaration_value
()
->
type
();
else
fntype
=
NULL
;
// The builtin function panic does not return.
if
(
fntype
!=
NULL
&&
fntype
->
is_builtin
()
&&
no
->
name
()
==
"panic"
)
return
false
;
}
}
}
return
true
;
...
...
@@ -3700,9 +3706,6 @@ class Constant_switch_statement : public Statement
void
do_check_types
(
Gogo
*
);
bool
do_may_fall_through
()
const
;
Bstatement
*
do_get_backend
(
Translate_context
*
);
...
...
@@ -3746,22 +3749,6 @@ Constant_switch_statement::do_check_types(Gogo*)
this
->
set_is_error
();
}
// Return whether this switch may fall through.
bool
Constant_switch_statement
::
do_may_fall_through
()
const
{
if
(
this
->
clauses_
==
NULL
)
return
true
;
// If we have a break label, then some case needed it. That implies
// that the switch statement as a whole can fall through.
if
(
this
->
break_label_
!=
NULL
)
return
true
;
return
this
->
clauses_
->
may_fall_through
();
}
// Convert to GENERIC.
Bstatement
*
...
...
@@ -3911,6 +3898,22 @@ Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
ast_dump_context
->
ostream
()
<<
std
::
endl
;
}
// Return whether this switch may fall through.
bool
Switch_statement
::
do_may_fall_through
()
const
{
if
(
this
->
clauses_
==
NULL
)
return
true
;
// If we have a break label, then some case needed it. That implies
// that the switch statement as a whole can fall through.
if
(
this
->
break_label_
!=
NULL
)
return
true
;
return
this
->
clauses_
->
may_fall_through
();
}
// Make a switch statement.
Switch_statement
*
...
...
@@ -4050,6 +4053,17 @@ Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
}
}
// Return true if this type clause may fall through to the statements
// following the switch.
bool
Type_case_clauses
::
Type_case_clause
::
may_fall_through
()
const
{
if
(
this
->
statements_
==
NULL
)
return
true
;
return
this
->
statements_
->
may_fall_through
();
}
// Dump the AST representation for a type case clause
void
...
...
@@ -4148,6 +4162,25 @@ Type_case_clauses::lower(Type* switch_val_type, Block* b,
NULL
);
}
// Return true if these clauses may fall through to the statements
// following the switch statement.
bool
Type_case_clauses
::
may_fall_through
()
const
{
bool
found_default
=
false
;
for
(
Type_clauses
::
const_iterator
p
=
this
->
clauses_
.
begin
();
p
!=
this
->
clauses_
.
end
();
++
p
)
{
if
(
p
->
may_fall_through
())
return
true
;
if
(
p
->
is_default
())
found_default
=
true
;
}
return
!
found_default
;
}
// Dump the AST representation for case clauses (from a switch statement)
void
...
...
@@ -4237,6 +4270,22 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
return
Statement
::
make_block_statement
(
b
,
loc
);
}
// Return whether this switch may fall through.
bool
Type_switch_statement
::
do_may_fall_through
()
const
{
if
(
this
->
clauses_
==
NULL
)
return
true
;
// If we have a break label, then some case needed it. That implies
// that the switch statement as a whole can fall through.
if
(
this
->
break_label_
!=
NULL
)
return
true
;
return
this
->
clauses_
->
may_fall_through
();
}
// Return the break label for this type switch statement, creating it
// if necessary.
...
...
@@ -4954,6 +5003,19 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
return
Statement
::
make_block_statement
(
b
,
loc
);
}
// Whether the select statement itself may fall through to the following
// statement.
bool
Select_statement
::
do_may_fall_through
()
const
{
// A select statement is terminating if no break statement
// refers to it and all of its clauses are terminating.
if
(
this
->
break_label_
!=
NULL
)
return
true
;
return
this
->
clauses_
->
may_fall_through
();
}
// Return the backend representation for a select statement.
Bstatement
*
...
...
@@ -5114,6 +5176,20 @@ For_statement::set_break_continue_labels(Unnamed_label* break_label,
this
->
continue_label_
=
continue_label
;
}
// Whether the overall statement may fall through.
bool
For_statement
::
do_may_fall_through
()
const
{
// A for loop is terminating if it has no condition and
// no break statement.
if
(
this
->
cond_
!=
NULL
)
return
true
;
if
(
this
->
break_label_
!=
NULL
)
return
true
;
return
false
;
}
// Dump the AST representation for a for statement.
void
...
...
gcc/go/gofrontend/statements.h
View file @
3ef479f3
...
...
@@ -894,8 +894,7 @@ class Select_statement : public Statement
{
this
->
clauses_
->
check_types
();
}
bool
do_may_fall_through
()
const
{
return
this
->
clauses_
->
may_fall_through
();
}
do_may_fall_through
()
const
;
Bstatement
*
do_get_backend
(
Translate_context
*
);
...
...
@@ -1086,6 +1085,9 @@ class For_statement : public Statement
Statement
*
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
,
Statement_inserter
*
);
bool
do_may_fall_through
()
const
;
Bstatement
*
do_get_backend
(
Translate_context
*
)
{
go_unreachable
();
}
...
...
@@ -1399,6 +1401,9 @@ class Switch_statement : public Statement
void
do_dump_statement
(
Ast_dump_context
*
)
const
;
bool
do_may_fall_through
()
const
;
private
:
// The value to switch on. This may be NULL.
Expression
*
val_
;
...
...
@@ -1449,6 +1454,11 @@ class Type_case_clauses
lower
(
Type
*
,
Block
*
,
Temporary_statement
*
descriptor_temp
,
Unnamed_label
*
break_label
)
const
;
// Return true if these clauses may fall through to the statements
// following the switch statement.
bool
may_fall_through
()
const
;
// Dump the AST representation to a dump context.
void
dump_clauses
(
Ast_dump_context
*
)
const
;
...
...
@@ -1493,6 +1503,12 @@ class Type_case_clauses
lower
(
Type
*
,
Block
*
,
Temporary_statement
*
descriptor_temp
,
Unnamed_label
*
break_label
,
Unnamed_label
**
stmts_label
)
const
;
// Return true if this clause may fall through to execute the
// statements following the switch statement. This is not the
// same as whether this clause falls through to the next clause.
bool
may_fall_through
()
const
;
// Dump the AST representation to a dump context.
void
dump_clause
(
Ast_dump_context
*
)
const
;
...
...
@@ -1556,6 +1572,9 @@ class Type_switch_statement : public Statement
void
do_dump_statement
(
Ast_dump_context
*
)
const
;
bool
do_may_fall_through
()
const
;
private
:
// The variable holding the value we are switching on.
Named_object
*
var_
;
...
...
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