aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r--gcc/go/gofrontend/parse.cc99
1 files changed, 76 insertions, 23 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 1664fe3..fd81a85 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -1315,12 +1315,36 @@ Parse::declaration()
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_->is_embed_imported())
+ {
+ 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);
else if (token->is_keyword(KEYWORD_VAR))
- this->var_decl();
+ this->var_decl(embeds);
else if (token->is_keyword(KEYWORD_FUNC))
this->function_decl(pragmas);
else
@@ -1343,8 +1367,8 @@ Parse::declaration_may_start_here()
// Decl<P> = P | "(" [ List<P> ] ")" .
void
-Parse::decl(void (Parse::*pfn)(void*, unsigned int), void* varg,
- unsigned int pragmas)
+Parse::decl(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
+ unsigned int pragmas, std::vector<std::string>* embeds)
{
if (this->peek_token()->is_eof())
{
@@ -1354,15 +1378,18 @@ Parse::decl(void (Parse::*pfn)(void*, unsigned int), void* varg,
}
if (!this->peek_token()->is_op(OPERATOR_LPAREN))
- (this->*pfn)(varg, pragmas);
+ (this->*pfn)(pragmas, embeds);
else
{
if (pragmas != 0)
go_warning_at(this->location(), 0,
"ignoring magic %<//go:...%> comment before group");
+ if (embeds != NULL)
+ go_error_at(this->location(),
+ "ignoring %<//go:embed%> comment before group");
if (!this->advance_token()->is_op(OPERATOR_RPAREN))
{
- this->list(pfn, varg, true);
+ this->list(pfn, true);
if (!this->peek_token()->is_op(OPERATOR_RPAREN))
{
go_error_at(this->location(), "missing %<)%>");
@@ -1383,10 +1410,10 @@ Parse::decl(void (Parse::*pfn)(void*, unsigned int), void* varg,
// might follow. This is either a '}' or a ')'.
void
-Parse::list(void (Parse::*pfn)(void*, unsigned int), void* varg,
+Parse::list(void (Parse::*pfn)(unsigned int, std::vector<std::string>*),
bool follow_is_paren)
{
- (this->*pfn)(varg, 0);
+ (this->*pfn)(0, NULL);
Operator follow = follow_is_paren ? OPERATOR_RPAREN : OPERATOR_RCURLY;
while (this->peek_token()->is_op(OPERATOR_SEMICOLON)
|| this->peek_token()->is_op(OPERATOR_COMMA))
@@ -1395,7 +1422,7 @@ Parse::list(void (Parse::*pfn)(void*, unsigned int), void* varg,
go_error_at(this->location(), "unexpected comma");
if (this->advance_token()->is_op(follow))
break;
- (this->*pfn)(varg, 0);
+ (this->*pfn)(0, NULL);
}
}
@@ -1522,13 +1549,13 @@ Parse::type_decl(unsigned int pragmas)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_TYPE));
this->advance_token();
- this->decl(&Parse::type_spec, NULL, pragmas);
+ this->decl(&Parse::type_spec, pragmas, NULL);
}
// TypeSpec = identifier ["="] Type .
void
-Parse::type_spec(void*, unsigned int pragmas)
+Parse::type_spec(unsigned int pragmas, std::vector<std::string>*)
{
const Token* token = this->peek_token();
if (!token->is_identifier())
@@ -1622,27 +1649,42 @@ Parse::type_spec(void*, unsigned int pragmas)
// VarDecl = "var" Decl<VarSpec> .
void
-Parse::var_decl()
+Parse::var_decl(std::vector<std::string>* embeds)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_VAR));
this->advance_token();
- this->decl(&Parse::var_spec, NULL, 0);
+ this->decl(&Parse::var_spec, 0, embeds);
}
// VarSpec = IdentifierList
// ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
void
-Parse::var_spec(void*, unsigned int pragmas)
+Parse::var_spec(unsigned int pragmas, std::vector<std::string>* embeds)
{
+ Location loc = this->location();
+
if (pragmas != 0)
- go_warning_at(this->location(), 0,
- "ignoring magic %<//go:...%> comment before var");
+ go_warning_at(loc, 0, "ignoring magic %<//go:...%> comment before var");
// Get the variable names.
Typed_identifier_list til;
this->identifier_list(&til);
+ if (embeds != NULL)
+ {
+ if (!this->gogo_->in_global_scope())
+ {
+ go_error_at(loc, "go:embed only permitted at package scope");
+ embeds = NULL;
+ }
+ if (til.size() > 1)
+ {
+ go_error_at(loc, "go:embed cannot apply to multiple vars");
+ embeds = NULL;
+ }
+ }
+
Location location = this->location();
Type* type = NULL;
@@ -1670,7 +1712,13 @@ Parse::var_spec(void*, unsigned int pragmas)
init = this->expression_list(NULL, false, true);
}
- this->init_vars(&til, type, init, false, location);
+ if (embeds != NULL && init != NULL)
+ {
+ go_error_at(loc, "go:embed cannot apply to var with initializer");
+ embeds = NULL;
+ }
+
+ this->init_vars(&til, type, init, false, embeds, location);
if (init != NULL)
delete init;
@@ -1683,11 +1731,12 @@ Parse::var_spec(void*, unsigned int pragmas)
void
Parse::init_vars(const Typed_identifier_list* til, Type* type,
Expression_list* init, bool is_coloneq,
- Location location)
+ std::vector<std::string>* embeds, Location location)
{
// Check for an initialization which can yield multiple values.
if (init != NULL && init->size() == 1 && til->size() > 1)
{
+ go_assert(embeds == NULL);
if (this->init_vars_from_call(til, type, *init->begin(), is_coloneq,
location))
return;
@@ -1729,8 +1778,12 @@ Parse::init_vars(const Typed_identifier_list* til, Type* type,
{
if (init != NULL)
go_assert(pexpr != init->end());
- this->init_var(*p, type, init == NULL ? NULL : *pexpr, is_coloneq,
- false, &any_new, vars, vals);
+ Named_object* no = this->init_var(*p, type,
+ init == NULL ? NULL : *pexpr,
+ is_coloneq, false, &any_new,
+ vars, vals);
+ if (embeds != NULL && no->is_variable())
+ no->var_value()->set_embeds(embeds);
if (init != NULL)
++pexpr;
}
@@ -2270,7 +2323,7 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
}
}
- this->init_vars(&til, NULL, init, true, location);
+ this->init_vars(&til, NULL, init, true, NULL, location);
}
// FunctionDecl = "func" identifier Signature [ Block ] .
@@ -5317,7 +5370,7 @@ Parse::for_stat(Label* label)
{
go_error_at(this->location(),
"var declaration not allowed in for initializer");
- this->var_decl();
+ this->var_decl(NULL);
}
if (token->is_op(OPERATOR_SEMICOLON))
@@ -5762,13 +5815,13 @@ Parse::import_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_IMPORT));
this->advance_token();
- this->decl(&Parse::import_spec, NULL, 0);
+ this->decl(&Parse::import_spec, 0, NULL);
}
// ImportSpec = [ "." | PackageName ] PackageFileName .
void
-Parse::import_spec(void*, unsigned int pragmas)
+Parse::import_spec(unsigned int pragmas, std::vector<std::string>*)
{
if (pragmas != 0)
go_warning_at(this->location(), 0,