aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/parse.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-10-26 10:50:40 -0700
committerIan Lance Taylor <iant@golang.org>2021-10-26 16:11:26 -0700
commitab10383aaebf2feebd2b6d68247f2520eff48f79 (patch)
treeb7296e54620d4fbe3fef6d4ebad91a9bbe7065ff /gcc/go/gofrontend/parse.cc
parent1ff4dbddcf74203a1e16316b18e12f9e1b5085f0 (diff)
downloadgcc-ab10383aaebf2feebd2b6d68247f2520eff48f79.zip
gcc-ab10383aaebf2feebd2b6d68247f2520eff48f79.tar.gz
gcc-ab10383aaebf2feebd2b6d68247f2520eff48f79.tar.bz2
compiler: permit compiler directives in parenthesized groups
The original compiler directive support was only for //line at the start of a line and for //go: comments before function declarations. When support was added for //go:notinheap for types and //go:embed for variables the code did not adapt to permit spaces before the comment or to permit the comments in var() or type() groups. This change corrects those omissions. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/358699
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r--gcc/go/gofrontend/parse.cc128
1 files changed, 66 insertions, 62 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index e43b5f2..cc197e5 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -1307,46 +1307,14 @@ void
Parse::declaration()
{
const Token* token = this->peek_token();
-
- unsigned int pragmas = this->lex_->get_and_clear_pragmas();
- if (pragmas != 0
- && !token->is_keyword(KEYWORD_FUNC)
- && !token->is_keyword(KEYWORD_TYPE))
- go_warning_at(token->location(), 0,
- "ignoring magic comment before non-function");
-
- std::vector<std::string>* embeds = NULL;
- if (this->lex_->has_embeds())
- {
- embeds = new(std::vector<std::string>);
- this->lex_->get_and_clear_embeds(embeds);
-
- if (!this->gogo_->current_file_imported_embed())
- {
- go_error_at(token->location(),
- "invalid go:embed: missing import %<embed%>");
- delete embeds;
- embeds = NULL;
- }
- if (!token->is_keyword(KEYWORD_VAR))
- {
- go_error_at(token->location(), "misplaced go:embed directive");
- if (embeds != NULL)
- {
- delete embeds;
- embeds = NULL;
- }
- }
- }
-
if (token->is_keyword(KEYWORD_CONST))
this->const_decl();
else if (token->is_keyword(KEYWORD_TYPE))
- this->type_decl(pragmas);
+ this->type_decl();
else if (token->is_keyword(KEYWORD_VAR))
- this->var_decl(embeds);
+ this->var_decl();
else if (token->is_keyword(KEYWORD_FUNC))
- this->function_decl(pragmas);
+ this->function_decl();
else
{
go_error_at(this->location(), "expected declaration");
@@ -1367,8 +1335,7 @@ Parse::declaration_may_start_here()
// Decl<P> = P | "(" [ List<P> ] ")" .
void
-Parse::decl(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
- unsigned int pragmas, std::vector<std::string>* embeds)
+Parse::decl(void (Parse::*pfn)())
{
if (this->peek_token()->is_eof())
{
@@ -1378,15 +1345,18 @@ Parse::decl(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
}
if (!this->peek_token()->is_op(OPERATOR_LPAREN))
- (this->*pfn)(pragmas, embeds);
+ (this->*pfn)();
else
{
- if (pragmas != 0)
- go_warning_at(this->location(), 0,
- "ignoring magic %<//go:...%> comment before group");
- if (embeds != NULL)
+ if (this->lex_->get_and_clear_pragmas() != 0)
go_error_at(this->location(),
- "ignoring %<//go:embed%> comment before group");
+ "ignoring compiler directive before group");
+ if (this->lex_->has_embeds())
+ {
+ this->lex_->clear_embeds();
+ go_error_at(this->location(),
+ "ignoring %<//go:embed%> comment before group");
+ }
if (!this->advance_token()->is_op(OPERATOR_RPAREN))
{
this->list(pfn, true);
@@ -1410,10 +1380,9 @@ Parse::decl(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
// might follow. This is either a '}' or a ')'.
void
-Parse::list(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
- bool follow_is_paren)
+Parse::list(void (Parse::*pfn)(), bool follow_is_paren)
{
- (this->*pfn)(0, NULL);
+ (this->*pfn)();
Operator follow = follow_is_paren ? OPERATOR_RPAREN : OPERATOR_RCURLY;
while (this->peek_token()->is_op(OPERATOR_SEMICOLON)
|| this->peek_token()->is_op(OPERATOR_COMMA))
@@ -1422,7 +1391,7 @@ Parse::list(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
go_error_at(this->location(), "unexpected comma");
if (this->advance_token()->is_op(follow))
break;
- (this->*pfn)(0, NULL);
+ (this->*pfn)();
}
}
@@ -1469,6 +1438,8 @@ Parse::const_decl()
void
Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
{
+ this->check_directives();
+
Location loc = this->location();
Typed_identifier_list til;
this->identifier_list(&til);
@@ -1545,18 +1516,21 @@ Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
// TypeDecl = "type" Decl<TypeSpec> .
void
-Parse::type_decl(unsigned int pragmas)
+Parse::type_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_TYPE));
this->advance_token();
- this->decl(&Parse::type_spec, pragmas, NULL);
+ this->decl(&Parse::type_spec);
}
// TypeSpec = identifier ["="] Type .
void
-Parse::type_spec(unsigned int pragmas, std::vector<std::string>*)
+Parse::type_spec()
{
+ unsigned int pragmas = this->lex_->get_and_clear_pragmas();
+ this->check_directives();
+
const Token* token = this->peek_token();
if (!token->is_identifier())
{
@@ -1649,23 +1623,34 @@ Parse::type_spec(unsigned int pragmas, std::vector<std::string>*)
// VarDecl = "var" Decl<VarSpec> .
void
-Parse::var_decl(std::vector<std::string>* embeds)
+Parse::var_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_VAR));
this->advance_token();
- this->decl(&Parse::var_spec, 0, embeds);
+ this->decl(&Parse::var_spec);
}
// VarSpec = IdentifierList
// ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
void
-Parse::var_spec(unsigned int pragmas, std::vector<std::string>* embeds)
+Parse::var_spec()
{
Location loc = this->location();
- if (pragmas != 0)
- go_warning_at(loc, 0, "ignoring magic %<//go:...%> comment before var");
+ std::vector<std::string>* embeds = NULL;
+ if (this->lex_->has_embeds())
+ {
+ if (!this->gogo_->current_file_imported_embed())
+ go_error_at(loc, "invalid go:embed: missing import %<embed%>");
+ else
+ {
+ embeds = new(std::vector<std::string>);
+ this->lex_->get_and_clear_embeds(embeds);
+ }
+ }
+
+ this->check_directives();
// Get the variable names.
Typed_identifier_list til;
@@ -2339,9 +2324,13 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
// PRAGMAS is a bitset of magic comments.
void
-Parse::function_decl(unsigned int pragmas)
+Parse::function_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC));
+
+ unsigned int pragmas = this->lex_->get_and_clear_pragmas();
+ this->check_directives();
+
Location location = this->location();
std::string extern_name = this->lex_->extern_name();
const Token* token = this->advance_token();
@@ -5370,7 +5359,7 @@ Parse::for_stat(Label* label)
{
go_error_at(this->location(),
"var declaration not allowed in for initializer");
- this->var_decl(NULL);
+ this->var_decl();
}
if (token->is_op(OPERATOR_SEMICOLON))
@@ -5815,17 +5804,15 @@ Parse::import_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_IMPORT));
this->advance_token();
- this->decl(&Parse::import_spec, 0, NULL);
+ this->decl(&Parse::import_spec);
}
// ImportSpec = [ "." | PackageName ] PackageFileName .
void
-Parse::import_spec(unsigned int pragmas, std::vector<std::string>*)
+Parse::import_spec()
{
- if (pragmas != 0)
- go_warning_at(this->location(), 0,
- "ignoring magic %<//go:...%> comment before import");
+ this->check_directives();
const Token* token = this->peek_token();
Location location = token->location();
@@ -5916,6 +5903,23 @@ Parse::program()
this->skip_past_error(OPERATOR_INVALID);
}
}
+
+ this->check_directives();
+}
+
+// If there are any pending compiler directives, clear them and give
+// an error. This is called when directives are not permitted.
+
+void
+Parse::check_directives()
+{
+ if (this->lex_->get_and_clear_pragmas() != 0)
+ go_error_at(this->location(), "misplaced compiler directive");
+ if (this->lex_->has_embeds())
+ {
+ this->lex_->clear_embeds();
+ go_error_at(this->location(), "misplaced go:embed directive");
+ }
}
// Skip forward to a semicolon or OP. OP will normally be