summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim@lrde.epita.fr>2015-01-08 11:19:57 +0100
committerAkim Demaille <akim@lrde.epita.fr>2015-01-08 16:07:59 +0100
commit00cebd11d48e07065cd012929d96085cfe37d07b (patch)
tree83ddf31416059cc070b34926bc08d4fca02f6232
parentee2f433512c2bfc1f8fe0f518f0e80e5e540bf26 (diff)
downloadbison-00cebd11d48e07065cd012929d96085cfe37d07b.tar.gz
c++: variants: don't leak the lookahead in error recovery
During error recovery, when discarding the lookeahead, we don't destroy it, which is caught by parse.assert assertions. Reported by Antonio Silva Correia. With an analysis and suggested patch from Michel d'Hooge. <http://savannah.gnu.org/support/?108481> * tests/c++.at (Variants): Strengthen the test to try syntax errors with discarded lookahead.
-rw-r--r--data/lalr1.cc1
-rw-r--r--tests/c++.at69
2 files changed, 44 insertions, 26 deletions
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 9ab9421e..d3ab008b 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -901,6 +901,7 @@ b4_dollar_popdef])[]dnl
else if (!yyempty)
{
yy_destroy_ ("Error: discarding", yyla);
+ yyla.clear ();
yyempty = true;
}
}
diff --git a/tests/c++.at b/tests/c++.at
index 1aa730f1..30304019 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -175,6 +175,9 @@ AT_CLEANUP
## Variants. ##
## ---------- ##
+# Check that the variants are properly supported, including in error
+# recovery.
+
# AT_TEST([DIRECTIVES])
# ---------------------
# Check the support of variants in C++, with the additional DIRECTIVES.
@@ -243,6 +246,7 @@ typedef std::list<std::string> strings_type;
%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
+%token COMMA ","
%type <::std::string> item;
// Using the template type to exercize its parsing.
@@ -259,13 +263,13 @@ result:
;
list:
- /* nothing */ { /* Generates an empty string list */ }
-| list item { std::swap ($$,$][1); $$.push_back ($][2); }
-| list error { std::swap ($$,$][1); }
+ item { $$.push_back ($][1); }
+| list "," item { std::swap ($$, $][1); $$.push_back ($][3); }
+| list error { std::swap ($$, $][1); }
;
item:
- TEXT { std::swap ($$,$][1); }
+ TEXT { std::swap ($$, $][1); }
| NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); }
;
%%
@@ -285,30 +289,43 @@ namespace yy
parser::location_type* yylloc])[)]])[
{]AT_LOCATION_IF([
typedef parser::location_type location;])[
- static int stage = -1;
- ++stage;
- if (stage == STAGE_MAX)
- {]AT_TOKEN_CTOR_IF([[
+ // The 5 is a syntax error whose recovery requires that we discard
+ // the lookahead. This tests a regression, see
+ // <http://savannah.gnu.org/support/?108481>.
+ static char const *input = "0,1,2,3,45,6";
+ switch (int stage = *input++)
+ {
+ case 0:]AT_TOKEN_CTOR_IF([[
return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]],
[AT_LOCATION_IF([
*yylloc = location ();])[
return parser::token::END_OF_FILE;]])[
- }
- else if (stage % 2)
- {]AT_TOKEN_CTOR_IF([[
- return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]],
-[[
- yylval->BUILD (int, stage);]AT_LOCATION_IF([
- *yylloc = location ();])[
- return parser::token::NUMBER;]])[
- }
- else
- {]AT_TOKEN_CTOR_IF([[
- return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[
- yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([
+
+ case ',':
+ ]AT_TOKEN_CTOR_IF([[
+ return parser::make_COMMA (]AT_LOCATION_IF([location ()])[);]], [[
+]AT_LOCATION_IF([
*yylloc = location ();])[
- return parser::token::TEXT;]])[
- }
+ return parser::token::COMMA;]])[
+
+ default:
+ stage = stage - '0';
+ if (stage % 2)
+ {]AT_TOKEN_CTOR_IF([[
+ return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]], [[
+ yylval->BUILD (int, stage);]AT_LOCATION_IF([
+ *yylloc = location ();])[
+ return parser::token::NUMBER;]])[
+ }
+ else
+ {]AT_TOKEN_CTOR_IF([[
+ return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[
+ yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([
+ *yylloc = location ();])[
+ return parser::token::TEXT;]])[
+ }
+ }
+
abort ();
}
}
@@ -319,7 +336,7 @@ namespace yy
AT_FULL_COMPILE([list])
AT_PARSER_CHECK([./list], 0,
-[(0, 1, 2, 4)
+[(0, 1, 2, 4, 6)
])
AT_BISON_OPTION_POPDEFS
@@ -328,11 +345,11 @@ AT_CLEANUP
AT_TEST([[%skeleton "lalr1.cc" ]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %locations]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_} %locations]])
m4_popdef([AT_TEST])